News for hackers. Stuff that matters.
Re:Serious Chrome zero-day by wahern on Wednesday March 06, 2019 @09:38PM (#19325152)
UAF by whom? If it's through a bare reference held in the JavaScript VM where operations don't access the C++ object as a C++ object or as some shared primitive object as in the JVM or CLR, then the error is in maintaining state consistency across distinct environments. Such bugs look exactly the same in every language, although the risk is compounded by (a) JIT'd environments and (b) asynchronous execution.

In the context of a bug involving JavaScript ArrayBuffers (where JIT compilers are designed to optimize away both FFI accessors and bounds checks) and asynchronous events I think it would be prudent to withhold judgment.

Re:Serious Chrome zero-day by tptacek on Wednesday March 06, 2019 @09:46PM (#19325185)
Can you provide an example of a dangling reference of any type (not just a UAF) being exploitable for RCE in a managed language like Java, Rust, or Go?
Re:Serious Chrome zero-day by microcolonel on Wednesday March 06, 2019 @10:08PM (#19325250)
> Can you provide an example of a dangling reference of any type (not just a UAF) being exploitable for RCE in a managed language like Java, Rust, or Go?

The point is that it doesn't matter what language is hosting the JIT. You can write this same bug in a program with a JIT hosted on the JVM, in a Rust program, or in a Go program. The code generated by the JIT is the equivalent of C FFI or an unsafe block, which completely ignores your "managed" language. V8 calls directly into and out of the JIT heap with a couple stubs a handful of instructions long, code in the JIT heap is whatever you generated, and can do whatever you told it to.

Re:Serious Chrome zero-day by pcwalton on Wednesday March 06, 2019 @10:20PM (#19325289)
OK, but this bug isn't in jitcode.
Re:Serious Chrome zero-day by wahern on Wednesday March 06, 2019 @10:51PM (#19325392)
I never said it was. I said it implicated JIT'd code and the complex GC subsystem. The context is a JavaScript ArrayBuffer, the very type of object that JIT engines are built to optimize access to, and thus it's reasonable to infer that there may be some sort of cross-runtime scoping aspect at play. Such code by definition not only bypasses language protections, most relevant to this case it implicates interfaces that, in the parlance of Rust, could only ever be implemented using unsafe{} blocks. Without knowing more we can't meaningfully perform root cause analysis.

Imagine passing a pointer to the backing store for Rust or Go arrays across an interface boundary. Imagine a JavaScript implementation also written in either of those languages, but where the entry point interfaces prevent the language (caller or callee) from tracking and ensuring lifetime invariants across the boundary (certainly not statically, nor dynamically because we're not using a unified abstract VM like the JVM or CLR). Correct memory management necessarily relies on the programmer explicitly and manually synchronizing liveness between those distinct environments. If they get it wrong it's not Rust or Go's fault, nor can you squarely lay blame on either side of the interface boundary; it's the programmer's fault and/or poor interface design; and the likelihood of such a bug is equally likely in Rust, Go, or C++.

JIT also comes into play because even if the entirety of Chrome or Mozilla were nominally implemented in Rust or Go, the compilers and runtimes of either language could not ensure correctness of the generated JIT'd code nor track dependencies across native Rust/Go code and the generated JIT'd code--particularly for JavaScript code where the norm is object lifetimes escaping function scope. JIT'd native code effectively, if not formally, results in two distinct, disjoint runtime environments. Correctness, again, would be predicated on correct use of interfaces that might look suspiciously like malloc/free. The better interfaces would expose and emphasize the semantics of anchoring and referencing binding directly, but such interfaces are difficult to design and implement--after all, if they were then the argument that safe C++ is too difficult in practice wouldn't have such weight.

There are entirely interpreted JavaScript engines. Rhino is a obvious example for Java. Duktape is a nice, embeddable interpreter written in C. Theoretically it could be rewritten in Rust, but that wouldn't make it any more likely to displace implementations like V8. And that's my point. In reality the fundamental problem isn't that we're not using a Rust-written Duktape (it's manifestly not a realistic expectation, not in the domain of JavaScript engines), it's that we don't invest enough attention in integration across inevitable language boundaries.

Re:Serious Chrome zero-day by pcwalton on Wednesday March 06, 2019 @11:41PM (#19325545)
Yes, there has to be some unsafe glue code somewhere. So what? You write it once and wrap it in a safe interface (there are at least three relevant options in the crate ecosystem that I mentioned). That way, programmers who hack on FileBuffer don't have to worry about introducing zero-days like this.

This is not feasible in C++, because the language isn't safe to begin with.

Re:Serious Chrome zero-day by rocqua on Thursday March 07, 2019 @02:37AM (#19326236)
JIT isnt unsafe glue. The very core concept of JIT breaks all compiler guarantees at runtime.
Re:Serious Chrome zero-day by wahern on Wednesday March 06, 2019 @11:38PM (#19325533)
To be clear, regarding my rant about WebAssembly, it would be nice to see a WASM specification that permitted, for example, pluggable WebAssembly engines. Though performance may limit it's popularity, I'd like the choice to use an engine written entirely in a language like Rust or ATS. Many people here would use it, and it would add a useful competitive dimension that emphasizes security. Also, as I previously mentioned, such an interface could limit the risk of introducing and the scope of dangerous cross-subsystem dependencies invisible to host languages and which result in memory issues.

But that can never happen if the WASM specification insists on semantics that all but require tight integration with the browsers' JavaScript engine and GC.

Re:Serious Chrome zero-day by fooker on Thursday March 07, 2019 @05:37AM (#19327006)
Yes, sure.

You write to a file, save the file name or file descriptor. Then when you read it back later, maybe you forget to validate the contents. This can be exploited depending on what you were doing with the data.

Do you now want to restrict what you mean by a 'reference'? You'll see that once you keep restricting that enough you first lose the ability to write fast programs and eventually useful programs(evidence: various 'unsafe' modes in so called safe languages).

Re:Serious Chrome zero-day by titzer on Thursday March 07, 2019 @06:47AM (#19327289)
> where JIT compilers are designed to optimize away...bounds checks

V8 does not optimize away bounds checks on array buffers. For one thing, array buffers can be detached, so their length can suddenly drop to zero.

Re:Serious Chrome zero-day by wahern on Thursday March 07, 2019 @06:03PM (#19333520)
It does for native arrays, at least:

> This is the incorrect optimization we’re looking for. JavaScript array accesses are guarded by CheckBounds nodes, which ensure that the index falls within the array bounds. If the optimizer can determine statically that the index is always in-bounds, it can eliminate the CheckBounds node. Image tying the index to the result of Object.is: since the typing information is off, we could make the analyzer think the index is always in-bounds, while it can be out-of-bounds at runtime. The optimizer will incorrectly eliminate CheckBounds, giving us OOB access to a JS array, which we can use to construct more powerful exploitation primitives.

https://abiondo.me/2019/01/02/exploiting-math-expm1-v8/

See also

https://halbecaf.com/2017/05/24/exploiting-a-v8-oob-write/

Microsoft's Chakra engine:

https://www.thezdi.com/blog/2017/10/5/check-it-out-enforceme...

Hoisting a bounds check outside a loop is a common optimization, and I would be surprised if V8 doesn't do this for ArrayBuffers. But in any event my point is that the JIT compiler is in effect doing manual memory management outside the visibility of the host language, so for these types of bugs a memory-safe host language doesn't save you. And it can get this wrong and will get this wrong because these are extremely complex systems with high code churn.

Re:Serious Chrome zero-day by titzer on Sunday March 10, 2019 @04:45AM (#19351031)
JavaScript arrays and ArrayBuffers are totally separate animals.