8 ms·
> "The exploit used a race condition bug between two threads due to missing proper synchronization between them. It gives an attacker a Use-After-Free (UaF) con
by willtim 7y ago
> "The exploit used a race condition bug between two threads due to missing proper synchronization between them. It gives an attacker a Use-After-Free (UaF) condition that is very dangerous because it can lead to code execution scenarios"
This is why C++ needs to be retired; and why we need to use safer languages. Not even Google can write safe C++. Thankfully Mozilla have already realised this.
- pjmlp 7y agoWe should start by retiring C. It doesn't matter if userspace is fully safe, when the basement looks like a Swiss cheese of security.
- willtim 7y agoMaybe. I'm happy to run any formally verified C as my basement, for example the seL4 kernel, or for C to be used as an intermediate language. Especially as there should be less code at the bottom of the stack. But C++ seems worse, it's a far more complex language, designed and built to try and scale C to building applications. This creates a far larger attack surface.
- zozbot234 7y ago> This is why C++ needs to be retired; and why we need to use safer languages. These problems can easily happen in a language like Go, unfortunately. Go is memory safe for sequential code, but that guarantee does not extend to in-process concurrency - Goroutines can access shared state without synchronization, and create memory unsafety.
- willtim 7y agoWhat do you mean by memory unsafety? A stale read would be bad, but wouldn't lead to arbitrary code execution.
- zozbot234 7y agoA 'stale' read of atomic data may be fine (it wouldn't really be "unsynchronized" in that sense), but as soon as you're dealing with stuff that's not completely atomic in-hardware and need actual synchronization, there's a potential of breaking expected invariants and creating further unsafety as a consequence of that.
- willtim 7y agoI agree a stale read is bad. And I am surprised that the Go designers have repeated many past mistakes. It is possible to design a concurrent high-level language that does not have such issues, despite the hardware. For example, if all communication is done via channels, then synchronisation can be automatically performed during channel read/write. For shared mutable state, Haskell's software transactional memory and Erlang's Mnesia are both excellent examples of safely dealing with it.
- zozbot234 7y agoThe issue wrt. Go is not with communication via channels in and of itself, but rather with using channels to share pointers to in-memory data. This is idiomatic in Go, people do it all the time even though it's what introduces unsafety.
- willtim 7y agoYes, but my point is that it's a flaw in the language to allow this. Not all high-level languages share Go's problems. However, even Go would be a huge safety improvement over C++.
- cre-ker 7y agoGo is actually one of the best in terms of design. Not every language has to be so complex. Go is easy to use and that's the point. Concurrency in it is best in class in many regards and that's what allowed the language to pretty much became THE language for backend, infrastructure and other web related things. Rust is in completely different spectrum and doesn't compete with Go. It's much more complex, harder to write and read. That's the cost of safety. For kernel or browser engine - that's the compromise people are willing to take. For other applications - better use something else.
- MrBuddyCasino 7y agoGo isn’t really a C++ replacement. I‘m not sure if that solves this particular issue, Rust is provably free of data races (excluding unsafe).
- m00dy 7y agois it possible to have arbitrary code execution in Go? I'm just curious.
- roblabla 7y agoGo has a few escape hatches like the unsafe package, but outside from that, I'm pretty sure arbexec isn't achievable in Go. The compiler inserts bounds check to prevent overflows, UAF isn't really achievable thanks to the GC, etc...
- pcwalton 7y agoYou can have UAF in Go due to slicing in the presence of concurrency: the implementation doesn't use multi-word atomics to update fat pointers like slices and interfaces. That said, it's not easy to do so.
- nicoburns 7y agoBut not in Rust. Go isn't exactly a bastion of safety. It's memory safe due to the GC, but it has a weak type system, so logic bugs are not well guarded against.
- zozbot234 7y ago> It's memory safe due to the GC That gets debatable as soon as you start using concurrency, like I said. There are idiomatic patterns in concurrent Go that are very much not safe.
- MaxBarraclough 7y agoWhat do you mean? It has a GC, right? So use-after-free is impossible, no?
- petjuh 7y agoSerious question - has that been verified, especially with regards to concurrency? Also does it rely on the assumption that GC implementions such as Java's are bug-free in this regard, and if so - has that been verified as well?
- lima 7y agoOn the other hand, Go code is a lot easier to audit. The kind of logic bug that the Rust compiler prevents due to stronger typing is typically a crash in Go, not a security issue.
- cre-ker 7y agoNo they can't. UaF is impossible in memory safe languages like Go. Concurrency doesn't matter here. Only thing you would get is logical errors resulting in crashes or weird behavior.
- rndgermandude 7y agoJavascript, that the exploit uses, is a memory safe language too, at lest in theory... None of the languages around, that are in major production use, are really completely memory safe in practise. There is always a runtime lurking under it, most times a libc (not in Go tho, IIRC) and assortment of various libraries written in memory unsafe languages and always a kernel. While it's probably harder to exploit Go, as, as far as I know, most of the Go runtime is written in Go, it's not impossible, just a lot less likely.
- saagarjha 7y agoGo depends on libc on certain platforms, such as macOS.
- staticassertion 7y agoJavascript is used to perform the exploit. The renderer, where the vulnerable code exists (I assume), is C++. The problem with protecting a C++ codebase like a JS renderer is that the attacker has HUGE amounts of control. They can literally already execute arbitrary code in the renderer, making information leaks and other techniques much easier. ASLR was never intended to protect against an attacker with such a level of control.
- rndgermandude 7y ago> Javascript is used to perform the exploit. The renderer, where the vulnerable code exists (I assume), is C++. Yes, that way my point. There is a runtime and/or VM and/or stdlib under these "memory safe" languages and these things are never fully written in memory safe languages themselves, at least as far as the current state of affairs goes. And even then, they run on insecure hardware (rowhammer and spectre anybody?). Would using a language with better memory safety and other guarantees like Rust be better to write these things? Most certainly, as the attack surface becomes smaller and e.g. Rust would prevent a lot of programming mistakes in the first place. Would that be a complete silver bullet, tho? Nope. So I agree with you that using a language with C++ isn't exactly "optimal" to implement these runtimes that are meant to run untrusted code. I just didn't like that the OP declared "memory safe languages like Go" to be a silver bullet. >ASLR was never intended to protect against an attacker with such a level of control. ASLR is not a protection. It's an additional roadblock put in place to make things harder for attackers once shit already hit the fan.
- bouncycastle 7y agoMy bullshit detector is at 3.6 Go has a garbage collector (i.e memory safety) & race detection tooling built in. https://golang.org/doc/articles/race_detector.html https://golang.org/doc/articles/race_detector.html Even if a race condition bug does sneak in, it won't be as catastrophic as C/C++. Writing concurrent code is hard in any language. There's no magic bullet & Go or Rust are not immune to concurrency bugs. If anything, tools like the race detector should always come built in and every dev working on concurrent code should use one.
- SolarNet 7y agoGC does not provide memory safety at a system level, it has the same issues as C++ in poorly programmed code once compiled. Also C++ has "memory safety" idioms similar to garbage collection through reference counting and RAII. Google has a C++ race detector based on the Go one and it did not detect this issue (or was ignored). Neither of those things you listed reduce the severity of the bug, and both are available in well written C++ code as google tends to do.
- Thaxll 7y agoWhat do you mean? If you don't use unsafe package you can't have the same problem as C/C++ so it is memory safe. The bug in Chrome can't happen in Go without unsafe usage.
- SolarNet 7y agoThat is categorically not true. Go compiles down to machine code, it has a stack and heap, it has structures on that stack and heap, and it has data races; those are all of the required components for a use after free. You can have data races compiled by the stock go compiler without the use of unsafe (also, why have race detector tooling if this is false?). It would probably be easier to exploit than here even because one wouldn't even need to bother with the ASLR pointer exfiltration they had to do here. It may be harder to write exploitable code, but memory safety does not guarantee runtime memory safety. Especially in the face of concurrency.
- dexen 7y agoSecurity bugs are unavoidable, Rust/Java or not. This calls for architectural defense in depth. A lot of the exploits would be rendered harmless by employing well established technique of splitting one huge monolithic app into processes with limited capabilities and communicating via simple and narrow channels. Qmail[1] is a good example of such architecture. The architectural support is already present in common OSes. -- https://en.wikipedia.org/wiki/Qmail https://en.wikipedia.org/wiki/Qmail
- safercplusplus 7y agoThose interested can check out a (nascent) "borrow checker"[1] for enforcement of C++'s memory and data race safe subset. [1] https://github.com/duneroadrunner/scpptool https://github.com/duneroadrunner/scpptool
- gok 7y agoWeb browsers are unfortunately a case where even memory safe-ish languages are really an incomplete solution. Writing a JavaScript JIT in Rust won't prevent optimizer bugs.
- pcwalton 7y agoWhile this is true, a lot of exploitable bugs attributed to the JS engines are actually in implementations of built-in methods (String.split, Array.join, etc.). These can benefit from memory-safe languages. Occasionally you do just end up with straight-up exploitable optimizer bugs, though. The literature has some powerful techniques to let us get rid of those too over time, but it's not as simple as rewrite-it-in-Rust. One thing that might help is simple layering: if the JIT could compile to something like wasm as an intermediate target, then you would have an extra layer of defense against optimizer bugs. This is something that's been talked about, but I don't know if anyone has seriously looked into how practical it is.
- saagarjha 7y agoIt would add significant limits on what an optimizer bug would allow an attacker to do, though.
- Jyaif 7y ago> Not even Google can write safe C++. Technically it was a samsung engineer that introduced the vuln.