Securing Browsers Through Isolation Versus Mitigation

The big difference between the Chrome and Edge approach security

Yesterday Microsoft released a blog post on old and new mitigations that they’re shipping in the Edge browser. There was some very interesting work here that I absolutely commend them on, but I’ve also seen some responses that just don’t seem to reflect reality. Take Dan Guido’s comment on Twitter yesterday (with apologies for calling Dan out 😉):

In response, I think it’s important to take what Microsoft is doing here apart, and get a better sense of what’s going on compared to Chrome. Granted, as the engineering lead for Chrome Security I’m going to be biased. However, a big part of my job requires me to objectively evaluate security mechanisms and determine where my team needs to invest effort, so ideally my bias won’t color the conclusions.

Mitigating Remote Code Execution (RCE)

Microsoft is investing heavily in front-end RCE mitigations that attempt to break the first link in the exploit chain, by preventing an attacker from achieving reliable code execution in the first place. When this works it’s a great way to stop an attacker cold. However, the downside of these things is that they can turn into a cat and mouse game, where each mitigation just demands more work from an attacker, but none of them can actually block an exploit outright.

Personally, I interpret Microsoft’s position here as a direct response to the specific attack patterns they see most often used in the wild against Internet Explorer and Edge. That certainly strikes me as logical strategy, and shows that they’re concentrating on what their data is telling them. So, the result has been a number of new RCE mitigation technologies. I’ve listed the noteworthy ones below, along with comparisons to their analogs in Chrome:

MemGC — MemGC reduces the chances of exploitable use-after-free vulnerabilities by garbage collecting DOM objects and adding some mitigations on the free operation. This is comparable to Chrome’s use of Oilpan to garbage collect DOM objects, and PartitionAlloc to employ different mitigations against exploiting use-after-frees that do occur. On balance, this one feels like a slight advantage to Chrome, but that’s mainly due to the relative infrequency of exploitable Chrome vulnerabilities in this area, so maybe it’s a wash.

— MemGC reduces the chances of exploitable use-after-free vulnerabilities by garbage collecting DOM objects and adding some mitigations on the free operation. This is comparable to Chrome’s use of Oilpan to garbage collect DOM objects, and PartitionAlloc to employ different mitigations against exploiting use-after-frees that do occur. On balance, this one feels like a slight advantage to Chrome, but that’s mainly due to the relative infrequency of exploitable Chrome vulnerabilities in this area, so maybe it’s a wash. Control Flow Guard ( CFG ) — CFG provides a form of control flow integrity, which adds some enforcement mechanisms that attempt to prevent an exploit from directing execution into illegitimate paths. Edge currently employs CFG for both its internal code and system libraries, whereas Chrome applies CFG only to system DLLs. We don’t plan to employ CFG on Chrome internally because we are instead investing in a migration to the Clang/LLVM toolchain. That will allow us to use Clang CFI, which is a superior option for Chrome’s needs. On balance this seems like only a slight advantage to Edge, as CFI/CFG are still relatively unproven technologies, with significant weakness still being identified and hammered out.

— CFG provides a form of control flow integrity, which adds some enforcement mechanisms that attempt to prevent an exploit from directing execution into illegitimate paths. Edge currently employs CFG for both its internal code and system libraries, whereas Chrome applies CFG only to system DLLs. We don’t plan to employ CFG on Chrome internally because we are instead investing in a migration to the Clang/LLVM toolchain. That will allow us to use Clang CFI, which is a superior option for Chrome’s needs. On balance this seems like only a slight advantage to Edge, as CFI/CFG are still relatively unproven technologies, with significant weakness still being identified and hammered out. JavaScript JIT hardening — Microsoft is currently employing a collection of technologies to prevent their JIT from being leveraged by exploits. The most innovative of these involves moving the JIT out of process, and preventing their sandboxed processes from directly generating executable pages. This could force an attacker to compile their full RCE as a ROP chain, which is a very significant undertaking. In contrast, Chrome’s current JIT mitigations are admittedly much weaker. Although, v8’s upcoming JavaScript interpreter (ignition) and replacement JIT (turbofan) will improve Chrome quite a bit in the near future. Regardless, this is one area where Edge seems well ahead of Chrome.

Security Isolation Mechanisms

While Microsoft has invested more heavily in RCE mitigations, Chrome has focused more on defining and hardening consistently available isolation boundaries for normal Web browsing. Just like Microsoft, our work is driven by the exploits that we’ve seen employed against Chrome in the wild. However, it also represents a difference in philosophy and operating constraints, where we’ve observed that isolation appears to be a more effective strategy over the long term, and more portable across the various platforms we must support.

First, let’s consider the long term effectiveness of a security mechanism. What we’ve observed on Chrome is that over time the underlying OS platforms tend to improve their security isolation primitives. For example, Linux derived OSes added seccomp-bpf and then alternate syscall tables. And Windows added integrity levels (IL) and later the process mitigation policy we use for win32k lockdown. So, by investing more effort in security isolation, we find that we’re able to take advantage of the bigger OS security improvements that we see over time.

As for portability, let’s look at the example of what Microsoft is doing with their recent JIT hardening. This work relies on features that were added to Windows 10 explicitly for Edge, and in a number of cases are restricted to Microsoft signed binaries. Now, these sort of OS restrictions are not uncommon, and there are ways for our engineers to potentially work around them. However, we also have to consider that this requires major architectural changes, and we have to determine whether or not that architecture is portable to the other platforms we support, or would provide a significant security improvement. Right now, it’s very hard to say either way.

the Chrome renderer process is far more robustly sandboxed than the comparable Edge content process

The practical effect of this is that Chrome Security has invested its energy in both creating stronger isolation primitives — e.g. the Chrome renderer process is far more robustly sandboxed than the comparable Edge content process — and in expanding the use of those isolation primitives on things like our GPU process sandbox and our upcoming network process sandbox.

The biggest of our isolation bets is the site isolation project, which is currently rolling out over the course of this year. Site isolation represents multiple engineering decades of work, and will ultimately allow Chrome’s renderer sandbox to enforce web origin restrictions, thus preventing even RCE inside our renderer sandbox from manipulating other web origins. That is a far more robust security guarantee than any other browser is currently even attempting.

So, What Was The Point of This Post?

Browser security is a complicated and confusing topic. So, I wanted to provide some context on the decisions we’ve made for Chrome, and why I think these decisions still make Chrome the most secure browser available on any platform (and I think the real-world track record bears that out).

The problem is that there’s an easy temptation to reduce these security discussions down to simple checklists, or play a game of comparing security features or CVEs — but that’s just not useful for assessing real-world security. Because the architectures at play in browsers are the most complex you’ll find in software, and the motivations behind the decisions are often extremely opaque. And while I do think we’ve made the right decisions and prioritize the right things for Chrome, I’ll readily admit that if I were responsible for securing Edge, I would be getting different data, focusing on a different set of users, and possibly making different decisions.

How About Ending With Something We All Agree On?

One very interesting thing in Microsoft’s blog post is the effort they’ve invested in blocking third-party code injection in Edge. This is actually a big pain point for all browsers. Misbehaving third-party applications inject code that not only creates major stability and performance issues, but is a huge obstacle to security. I’ve personally complained about how we’ve been unable to enable Lowbox Tokens (the AppContainer security restriction) and CSRSS restrictions in Chrome’s sandbox, because when we do major third-party antivirus software crashes Chrome.

It’s good to see that Microsoft made a clean cut with Edge, and has set a precedent of blocking these third-party injections. Chrome is looking into deploying similar measures this year, and the same seems true for Firefox. So, I think that’s one area where we’re all aligned on how to best help our users.