Eyes Above The Waves

Robert O'Callahan. Christian. Repatriate Kiwi. Hacker.

Wednesday 18 October 2017

Microsoft's Chrome Exploitation And The Limitations Of Control Flow Integrity

Microsoft published an interesting blog post about exploiting a V8 bug to achieve arbitrary code execution in a Chrome content sandbox. They rightly point out that then even if you don't escape the sandbox, you can break important Web security properties (e.g., assuming the process is allowed to host content from more than one origin, you can break same-origin restrictions). However, the message we're supposed to take away from this article is that Microsoft's CFI would prevent similar bugs in Edge from having the same impact. I think that message is basically wrong.

The problem is, once you've achieved arbitrary memory read/write from Javascript, it's very likely you can break those Web security properties without running arbitrary machine code, without using ROP, and without violating CFI at all. For example if you want to violate same-origin restrictions, your JS code could find the location in memory where the origin of the current document is stored and rewrite it to be a different origin. In practice it would quite a lot more complicated than that, but the basic idea should work, and once you've implemented the technique it could be used to exploit any arbitrary read/write bug. It might even be easier to write some exploits this way than using traditional arbitrary code execution; JS is a more convenient programming language than ROP gadgets.

The underlying technical problem is that once you've achieved arbitrary read/write you can almost completely violate data-flow integrity within the process. As I recently wrote, DFI is extremely important and (unlike CFI) it's probably impossible to dynamically enforce with low overhead in the presence of arbitrary read/write, with any reasonable granularity.

I think there's also an underlying cultural problem here, which is that traditionally "Remote Code Execution" — of unconstrained machine code — has been the gold standard for a working exploit, which is why techniques to prevent that, like CFI, have attracted so much attention. But Javascript (or some other interpreter, or even some Turing-complete interpreter-like behavior) armed with an arbitrary memory read/write primitive is just as bad in a lot of cases.

Comments

Peter Kasting
Also, we Chrome folks have had our eyes on this problem for several years, which the primary motivation for things like the OOPIF work; malware served in an ad frame should not be able to snoop data from the hosting page even if we have a renderer or JS engine bug.
Robert
That's good, although it's still a long way to being able to reliably enforce one process per origin AFAICT.
Will
It's closer than you think. Try enabling it in chrome://flags/#enable-site-per-process - run latest Canary for best to experience. I run on all my machines with no issues but YMMV.
Robert
http://www.chromium.org/developers/design-documents/site-isolation says "How to handle Chrome's renderer process limit remains an open question." Is that out of date?
Peter Kasting
Per the status there, there's a plan to handle it. It's "open" in the sense that we'd like to revisit the question over time to see if the plan was, and remains, the right one. I agree with Will's assessment; site isolation in Chrome is pretty near at hand.
Robert
The text there still seems a bit vague --- "We could choose to protect only a set of sensitive web sites, perhaps including those the user has logged into, or all HTTPS sites." Protecting all HTTPS sites doesn't seem like it will mitigate the overhead of multiple processes very effectively in the world of "HTTPS everywhere". I guess we'll see how it goes when you ship!
Peter Kasting
No, the plan is below that: "We are planning to initially protect only a set of opt-in, high-value sites. We will expand this set as resource usage permits."
Robert
OK, but it's not what I would call "reliable enforcement of one process per origin" when only a (relatively small?) set of sites get the protection.
Unknown
They might be referring to the per-tab hypervisor that was just launched today in ie/edge which would protect against this, not their CFI. https://docs.microsoft.com/en-us/windows/threat-protection/windows-defender-application-guard/wd-app-guard-overview
Robert
No, their post explicitly refers to CFI.
Unknown
They talk about both and explicitly names application guard too. There is a "key findings" area with one dot point about CFI and one about lack of RCE mitigations - " We continue to make strides in preventing both Remote Code Execution (RCE) with mitigations like Control Flow Guard (CFG), export suppression, and Arbitrary Code Guard (ACG), and isolation, notably with Less Privileged AppContainer (LPAC) and Windows Defender Application Guard (WDAG)." They just mention CFI later again during exploitation discussion.
Robert
CFG and ACG are both forms of CFI. LPAC and WDAG are both forms of sandboxing. None of them would block the sort of data-only attack on Web security boundaries that I talked about.
Unknown
Sandboxing _does_ stop this sort of attack by locking down the renderer to a single origin. The other commenters brought up chrome's experimental site-isolation feature but it's mentioned in the article specifically about how it would stop this. They imply that edge already does this. Did you not read the entire article before deciding to blog about its 'shortcomings'? That's pretty funny.
Robert
Of course I read it. Can you quote where the article says (or implies) Edge has process-per-site isolation? I can't see it. I don't think you can read the article as "really being about sandboxing, not CFI". It's strongly focused on RCE: it has an entire section called "The dangers of RCE", two of the four "findings" are about RCE, and most of the content is the details of achieving RCE. But sandboxing doesn't block RCE --- CFI does. And they don't even try to compare Chrome's sandbox vs Edge's, while they DO talk about Chrome's lack of CFI. Oh, and the entire post is titled "Beyond Sandboxing"!!! I stand by what I wrote in my post. The attacks under "the dangers of RCE" in Microsoft's post are just as feasible without RCE and are not effectively mitigated by CFI, and therefore Microsoft's post is basically wrong.
Unknown
That whole section "dangers of RCE" is about about how with RCE on chrome you can break same origin - this implies that Edge isn't vulnerable to this. You generally don't make a big deal about how you competitor is vulnerable to X while also being vulnerable to X. It's implied in the "key findings" area too. I didn't say it was "really about sandboxing" but effective sandboxing is a part of mitigating same origin bypasses through some RCE bugs, like the one discussed in the article. Sandboxing does stop RCE by reducing attack surface. You might not think of it in the same was as ASLR but it's for the same reason.
Robert
If Edge has process-per-site isolation, and the author was aware that it's process-per-site isolation that's *really* preventing escalation of arbitary-read/write bugs to same-origin violations, why would they write an article focusing on RCE/CFI, which would be basically irrelevant in that case --- and never mention process-per-site isolation in Edge, even when they mention Chrome's? That would make the article grossly misleading. FWIW a bunch of security people agreed with my interpretation. If Microsoft grossly misled us all, that's on them. Process-boundary sandboxing doesn't stop RCE by the way. You sandbox to limit what an RCE can do after it has taken over the process. This discussion is getting tedious. I'll try not to reply again.