azblue wrote:Thank you Brendan and willedwards for your answers
willedwards wrote:
You can harden your exploit mitigation further by W^X, even for JITed code
It's funny you mentioned W^X in the context of JIT compiling as I was just thinking about that today. I'm trying to figure out how to maintain the security W^X offers while still allowing JIT compiling; my understanding is that the application writes the code to data pages(W) and then asks the OS to change the pages to code pages (X). If the OS always honors this request, then W^X is essentially non-existent (surely an attacker doesn't care if they have to first ask the OS for permission before executing their malicious code if the OS will always grant it).
So the only thing I can figure is that the OS will not always grant permission to change page permissions. Which begs the question, how does the OS differentiate between legitimate requests to change page permissions and malicious requests?
The best I can come up with is that at install time an admin can grant* programs like JIT compilers authority to request changing pages from writable to executable; programs that do not have this permission will be treated as if they're generating a GPF if they try calling this function.
Is there a better approach?
*(I've considered a few such privileges which will be determined at install time).
I think that RWX for JITs is not just technical, its also historic. Back when the JITting started, it wasn't seen as much of a problem. Now, there are lots of sunk effort in making those JITs work the way they do, and there's not much appetite for rewriting them. Also, on the technical side, theres not a lot of options if you want any semblance of portability. Its hard to support new processor or OS features that require major reorganisation when you expect the same binaries to run on older machines.
I believe the modern iOS stopped embedding the WebView browser in apps and started running the browser in a separate process and using UI composition to give the user experience of a seamless browser in order to be able to enable stronger mitigations like W^X in normal iOS apps, even though they can't enable them in webkit processes. Something like that.
The normal attack is to string together a row of vulnerabilities. First you want to find a bug that lets you write to arbitrary memory that the language VM (e.g. Java, Flash, Javascript) can write to. Then you want to find the address of something on the heap, so you can rewrite some of the javascript vtable-like pointers so you can get code executed. Then you want to find somewhere to put your code that is WX, and then you want to write the address of the code you injected into that function pointer in the heap. And finally, now you can take over the VM and make it run arbitrary code, you want to find a sandbox escape
Take this to Pwn2Own and make your millions
Anyway, fundamentally, even the Mill CPU security is based on strong memory isolation. But a new CPU can facilitate W^X-type mitigations for JITs to thwart or impede the chain of vulnerabilities leading to an exploit. For example: you could have two turfs, one that can X and one that can W. You can portal to the JITter turf that can W in order to do the JIT. This means that the attacker can't just write to executable memory, they have to find a vulnerability in the JIT to get it to do that for it. Another example is that the sandbox escape seems to invariably be that the kernel and graphics subsystem is such a large API that nobody seems to be able to squash all the privilege escalation vulnerabilities. On the Mill, the Javascript turf can be sandboxed so it can only write to a handful of portals, and these portals need not even be the kernel but rather some whitelisting validator. NaCL also went in this direction but perhaps not so far. There can still be bugs in whitelisting validators that let things through.
All in all, the attackers keep winning, but we must never ever give up! The only truly secure code seems to be the code that is never run