Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/actions/check/check-replication.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions .github/actions/check/check-replication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ const run = async (): Promise<void> => {
core.setFailed(`Internal error. Cannot access the internal repo ${internalRepo}. Aborting`)
return
} else {
core.debug(`Retrieved ${internalIssues?.length} internal issues`)
const externalIssues = await getIssueList(github.context.repo.owner, github.context.repo.repo, process.env['GITHUB_TOKEN'], true, true)
if(!externalIssues) {
core.setFailed(`Internal error when retrieving all issues.`)
return
}
core.debug(`Retrieved ${externalIssues?.length} external issues`)
let failed = false
externalIssues.forEach( issue => {
const ref = internalIssueAlreadyCreated(issue?.html_url, internalIssues)
Expand Down
52 changes: 29 additions & 23 deletions .github/actions/replicate/issues.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 28 additions & 22 deletions .github/actions/replicate/issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,35 @@ export const getIssueList = async (owner: string, repo: string, token: string |
const octokit = new github.GitHub(token)
const issueState: Issue_state = open? 'open' : 'all'
// const labelFilter: string = replicate.BOUNTY_LABELS.join(',')
const issues = await octokit.issues.listForRepo({
owner,
repo,
state: issueState,
per_page: per_page? per_page : 100 // TODO: implement proper pagination
// labels: labelFilter -- Does not work properly
})

issues.data.forEach(issue => {
const bountyLabel = checkBountyLabels? issue.labels.some(label => {
return replicate.BOUNTY_LABELS.includes(label.name as replicate.BountyType)
}) : undefined
if(!checkBountyLabels || bountyLabel){
let item: Issue_info = {
title: issue.title,
author: issue.user?.login,
body: issue.body? issue.body : '',
number: issue.number,
html_url: issue.html_url
const issuesPerPage = per_page? per_page : 50
let pageNb = 0
do {
const issues = await octokit.issues.listForRepo({
owner,
repo,
state: issueState,
per_page: issuesPerPage,
page: pageNb
// labels: labelFilter -- Does not work properly
})

issues.data.forEach(issue => {
const bountyLabel = checkBountyLabels? issue.labels.some(label => {
return replicate.BOUNTY_LABELS.includes(label.name as replicate.BountyType)
}) : undefined
if(!checkBountyLabels || bountyLabel){
let item: Issue_info = {
title: issue.title,
author: issue.user?.login,
body: issue.body? issue.body : '',
number: issue.number,
html_url: issue.html_url
}
result.push(item)
}
result.push(item)
}
});
});
pageNb = (issues.data.length < issuesPerPage)? -1 : pageNb + 1
} while (pageNb >= 0)
return result
} catch(error) {
core.debug(error.message)
Expand Down
15 changes: 15 additions & 0 deletions .github/actions/replicate/replicate.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .github/actions/replicate/replicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export type Issue = {title: string, body: string, labels: string[], bountyType:
type GitHubIssue = { [key: string]: any, number: number, html_url?: string | undefined, body?: string | undefined}

const COMMENT_TASK_LIST_AFO = `## Task List

- **If this is your first time in this process, have a look at that [5 min video](https://drive.google.com/drive/folders/1Jq6UfqP3CRF9Iafde86_IPAQPfdgH5rR)**
- **Visit the [documented process](https://github.com/github/pe-security-lab/blob/master/docs/bug_bounty.md)**

- [ ] CodeQL Initial assessment - In case of rejection, please record your decision in the comment below:
- [ ] Acceptance
- [ ] Generate result set and post the URL in the comment
Expand Down Expand Up @@ -40,6 +44,10 @@ const COMMENT_TASK_LIST: CommentMap = {
}

const COMMENT_SCORING = `## Scoring

- **Visit the [scoring guidelines](https://github.com/github/pe-security-lab/blob/master/docs/bug_bounty.md)**
- **Accepted values are: 0 (= NA), or 1 (minimal) to 5 (maximal). Any other value will throw an error**

| Criterion | Score|
|--- | --- |
| Vulnerability Impact | |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-replication-manual.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'Bounty issue replication workflow'
name: 'Bounty issue manual replication check'
on: workflow_dispatch

jobs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-replication.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'Bounty issue replication workflow'
name: 'Bounty issue replication check'
on:
schedule:
- cron: '0 17 * * *'
Expand Down
6 changes: 3 additions & 3 deletions CodeQL_Queries/cpp/Chrome/bindings.qll
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class StrongBinding extends ClassTemplateInstantiation {
}

Type getBindingType() {
result = this.getTemplateArgument(0).stripType()
result = this.getTemplateArgument(0).(Type).stripType()
}
}

Expand All @@ -21,7 +21,7 @@ class Binding extends ClassTemplateInstantiation {
}

Type getBindingType() {
result = this.getTemplateArgument(0).stripType()
result = this.getTemplateArgument(0).(Type).stripType()
}
}

Expand All @@ -32,7 +32,7 @@ class MojoReceiver extends ClassTemplateInstantiation {
}

Type getBindingType() {
result = this.getTemplateArgument(0).stripType()
result = this.getTemplateArgument(0).(Type).stripType()
}
}

Expand Down
1 change: 0 additions & 1 deletion CodeQL_Queries/cpp/Chrome/callbacks.qll
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ predicate reach(Function f, Function g) {
else
overrides*(g, gc.getTarget())
|
g = gc.getTarget() and
gc.getEnclosingFunction() = f
) or
exists(CallbackSinks sink | sink.getEnclosingCallable() = f and
Expand Down
3 changes: 3 additions & 0 deletions CodeQL_Queries/cpp/Chrome/qlpack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: chrome_ql
version: 0.0.0
libraryPathDependencies: codeql-cpp
24 changes: 24 additions & 0 deletions SecurityExploits/Chrome/blink/CVE-2020-6449/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Exploit for Chrome CVE-2020-6449

The write up can be found [here](https://securitylab.github.com/research/CVE-2020-6449-exploit-chrome-uaf). This is a bug in the webaudio component I discovered in March 2020. Chromium issue ticket can be found [here.](https://bugs.chromium.org/p/chromium/issues/detail?id=1059686)

The exploit is tested on Ubuntu 18.04 LTS, version 80.0.3987.137, with the following build config: (Probably can reduce symbol level)

```
is_debug=false
symbol_level = 2
blink_symbol_level = 2
```

Offsets and object sizes used are based on the linux build.

The exploit is mostly reliable when testing on localhost with python `SimpleHTTPServer`. However, it is not 100% reliable. This is due to the hardcoded offset between the address of a memory bucket that was leaked and the memory bucket that is actually used to store controlled data. This offset is used in `calculateControlledAddress`:

```
//Hardcoded offset between heap bins.
let controlledAddress = bigIntView[0] + 0x184798n;
```

This mostly fail when there is a broken pipe problem with the `SimpleHTTPServer`, which happens when the browser is not shutdown properly (shutdown by `Ctrl+C` rather than closing it from UI) Reliability can probably be improved by using memory buckets that are closer together, or just by putting the whole thing inside an out-of-process-iframe so that if it crashed, it can be restarted from the parent. (Although the bucket offset would need to be tuned again in this case)

The exploit takes a couple of minutes to run. If successful, it will overwrite memory permission for a page that holds our controlled data and will print out the address of this page. It can then be verified that the memory permission has been written to `rwx` for that page using `/proc/<id>/maps` (the renderer can be easy to spot by as it should consumed about 400Mb of memory). After that, executing shell code is easy, although I have not included or executed any shell code in this exploit.
15 changes: 15 additions & 0 deletions SecurityExploits/Chrome/blink/CVE-2020-6449/delay-processor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// white-noise-processor.js
function sleep(miliseconds) {
var currentTime = new Date().getTime();
while (currentTime + miliseconds >= new Date().getTime()) {
}
}

class DelayProcessor extends AudioWorkletProcessor {
process (inputs, outputs, parameters) {
sleep(2);
return true
}
}

registerProcessor('delay-processor', DelayProcessor)
Loading