4 ms·
Aaaaaand It's not the first time WASM seen in [0] wild. [0] https://bugs.chromium.org/p/chromium/issues/detail?id=835887 https://bugs.chromium.org/p/chromium/i
by v8dev123 5y ago
Aaaaaand It's not the first time WASM seen in [0] wild.
[0] https://bugs.chromium.org/p/chromium/issues/detail?id=835887 https://bugs.chromium.org/p/chromium/issues/detail?id=835887
- titzer 5y agoYeah. And it's not even bugs in the Wasm engine that are the problem; the RWX memory for Wasm JIT code makes all other bugs into potential RCE bugs. It must be banished! :)
- rkangel 5y agoHaving worked in other spaces ensuring W^X on the basis that there is no good reason for it, the only exception is usually "because I need to code generate". How do you even go about getting rid of WRX in a JIT? Do you generate and then remove W?
- 0xC0ncord 5y agoYou pretty much can't, because once memory has been written to at runtime it is assumed to be untrusted. JIT in and of itself is a W^X violation, so the only real solution is to not use it when security over performance is preferred.
- baybal2 5y agoRemove support for raw data types from JS. Remove Array buffers, remove blob support, remove anything which can be used to assembly a continuous binary without passing some sanitation.
- wizzwizz4 5y agoThat isn't sufficient. You know why? exploit("X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*") Okay, so we remove strings. Good thing the in-memory object format isn't known by the atta– wait. Okay, never mind; we can get rid of objects too. And bignums, while we're at it; that leaves us just with bog-standard floating-point integer primitives. Which are stored in a JavaScript call frame. Oops.
- baybal2 5y ago1. String are not executable code 2. Can be sanitised to be valid UTF-16 3. Can be intentionally mangled in memory to prevent abuse
- wizzwizz4 5y ago1. This one is. 2. Won't help. 3. Simply reverse, or make use of, the mangling.
- baybal2 5y ago> 1. This one is. I can check browser memory with a profiler and see if this page is marked as executable. It would not be.
- sfink 5y agoArrayBuffers aren't meant to be executable code either. JS strings are not UTF-16, they are 16-bit chunks of (potentially) nonsense, and enforcing valid UTF-16 would break quite a few existing uses. For example, anything that stores encrypted data in a string. Which "shouldn't" be done, that should be a Uint8Array, but existing APIs basically force you to do it. And there's such a thing as backwards compatibility. Your 3rd point is much more feasible. I doubt any "real" mangling would be good enough from a performance standpoint while still being too difficult for attackers to use. But I could imagine eg breaking any invalid UTF-16/UTF-8 string up into separate rope nodes, maybe even ensuring the nodes don't get allocated too close to each other and/or injecting disrupting hardcoded bytes in between them. (I work on SpiderMonkey, the Firefox JS engine, and we do at least make sure to allocate string data in a separate part of the heap from everything else.)
- baybal2 5y agoValid UTF16 is already being sporadically enforced. People who hack JS to store arbitrary data in strings are already fighting a loosing battle, and I see no point to help them. But my point is that we have moved from the JS as a scripting language which did not allow for arbitrary binary data, to one which did without much though over that. Half of existing problems with zero click, zero days, and zero browse exploits running in the wild, and Chrome becoming the ActiveX 2.0 is that. There is really no reason for a web browser to do computing on the web, and thus no need for binary manipulations in Javascript on the web. I'm not saying to axe it from JS, but JS may limit the the browser use case by a limited set of JS standard.
- titzer 5y agoIn V8, JITed JavaScript code is never writable and executable at the same time; the JIT writes into a buffer, then quiesces JS execution, then copies/flips permissions, then starts running JS code again. In the Wasm engine inside of V8, the code is writable and executable at the same time because the JIT uses multiple concurrent threads in the background during execution and incrementally commits new JITed code as it is finished. (And, funnily enough, this performance optimization is mostly for asm.js code, which is verified and internally translated to Wasm, to be compiled and executed by the Wasm engine). The long-term holy grail is to move the JIT compiler entirely to another process, so only that process has write permissions, and the renderer process (where Wasm and JS execute) has only R and execute permissions, and they used shared memory underneath.