12 ms·
Not to go all 'Rust Evangelism Strike Force' but almost universally, these exploits leverage memory unsafety somewhere in the stack, usually in a parser of some
by xavxav 5y ago
Not to go all 'Rust Evangelism Strike Force' but almost universally, these exploits leverage memory unsafety somewhere in the stack, usually in a parser of some kind (image, text, etc). The fact that this is still tolerated in our core systems is a pox on our industry. You don't have to use Rust, and it won't eliminate every bug (far from it), but memory safety is not optional.
We truly need to work more towards eliminating every memory unsafe language in use today, until then we're fighting a forest fire with a bucket of water.
- chromanoid 5y agoFollowing this idea, using a memory managed language like Go, Java or C# should also prevent most security issues (at least in non-core systems). Somehow I don't think this would work.
- tester756 5y agoWhat makes you think so?
- chromanoid 5y agoWhile I think garbage collected languages produce programs that are more safe, I also think they are often enablers for new classes of security issues. For example ysoserial, log4j etc.
- tester756 5y ago(This is genuine question) Is log4j's bug actually unique to Java/C#/gc-based languages?
- 41b696ef1113 5y ago>Is log4j's bug actually unique to Java/C#/gc-based languages? Not to my understanding. It would be possible in any language with or without a GC.
- catdog 5y agoNo, not validating user input and passing it to some crazy feature rich library like JNDI is possible in any language. Not denying that Java did contribute by shipping with such an overengineered mess like JNDI in the first place. Log4Shell wasn't a bug, log4j worked as expected and documented. It's just a stupid idea for a logging library to work in such a way.
- jerf 5y agoThe underlying bug in log4j is having a deserialization mechanism that can automatically deserialize to any class in the system, combined with method code that runs upon deserialization that does dangerous things. It has nothing to do with GC at all. It's a recurring problem in dynamic scripting languages where the language by its very nature tends to support this sort of functionality. It's actually a bit weird that Java has it because statically-typed languages like that don't generally have the ability to do that, but Java put a lot of work into building this into its language. Ruby has a very large issue with this a few years back where YAML submitted to an Ruby on Rails site would be automatically deserialized and execute a payload before it got to the logic that would reject it if nothing was looking for it. Python's pickle class has been documented as being capable of this for a long time, so the community is constantly on the lookout for things that use pickle that shouldn't, and so far they've mostly succeeded, but in principle the same thing could happen with that, too. It would be nearly impossible for Go (a GC'd language) to have that class of catastrophic security error, because there is nowhere the runtime can go to get a list of "all classes" for any reason, including deserialization purposes. You have to have some sort of registry of classes. It's possibly to register something that can do something stupid upon unmarshaling, but you have to work a lot harder at it. Go is not unique. You don't see the serialization bugs of this type in C or C++ either (non-GC'd languages), because there's no top-level registry of "all classes/function/whatever" in the system to access at all. You might get lots of memory safety issues, but not issues from deserializing classes that shouldn't be deserialized simply because an attacker named them. Many other languages make this effectively impossible because most languages don't have that top-level registry built in. That's the key thing that makes this bug likely.
- formerly_proven 5y ago> The underlying bug in log4j is having a deserialization mechanism that can automatically deserialize to any class in the system Getting objects out of a directory services is what JNDI is all about, I'm hesitant to call it a bug. The bug is that Java is way too keen on dynamically loading code at runtime. Probably because it was created in the 90s, where doing that was kinda all the rage. I think retrospectively the conclusion is that it may be the easiest way to make things extensible short-term, but also the worst way for long-term maintenance. Just ask Microsoft about that.
- chromanoid 5y agoNo, it's not unique. But a GC strengthens, like dynamic typing, your ability to develop more dynamically and together with reflection or duck typing to write code that can deal with to some extent unknown input more easily. You can pass arbitrary objects (also graphs of objects) around very generously. Ysoserial is based more or less on this idea. Passing arbitrary objects around was deemed so useful, that it is also supported by java's serialization mechanism and thus could be exploited. Log4shell exploits similar mechanisms that would be a hell to implement in non-gc languages.
- deleted 5y ago[deleted]
- daniel-cussen 5y agoYeah, I started noticing huge flaws in Apple's Music app, which I told them about and work around mostly, but...are they because Apple software is written in C? C++, Objective-C, same thing. Like can C code ever really be airtight?
- can16358p 5y agoI'd say lack of QA. Apple Music (especially on macOS) is EXTREMELY buggy, unresponsive, slow, and feels like a mess to use. Same for iMessage. Other apps are also written using the same stack with almost no bugs. I wouldn't blame the language here, but the teams working on them (or more likely their managers trying to hit unrealistic deadlines).
- daniel-cussen 5y agoNo, I would not blame the teams or their managers. You can't just blame a manager you've never met just because he's a manager, we're talking about the manager of Apple Music, they could very well be capable and well-minded, likely personally capable of coding. So let me give you another example in the same vein as C, where everybody uses a technology that is terrible, questioning it only at the outset, and then just accepting it: keyboard layouts. QWERTY is obsolete. It wasn't designed at random, it would have aged better if it did, it was designed to slow down typing so typewriters wouldn't jam. And secondly, in order for salesmen to type "TYPEWRITER" with just the top row, so the poor woman he was selling didn't realize typewriters were masochistic. So that's how you end up with millions of people hunting and pecking, or getting stuck for months trying to learn touch typing for real with exercises like "sad fad dad." It takes weeks before you can type "the". It's just the network effects of keyboard layouts are just next-level. Peter Thiel talks about this in "Zero to One" as an example of a technology that is objectively inferior but is still widely used because it's so hard to switch, illustrating the power of network effects. I for one did switch, and it was hard because I couldn't type neither Qwerty nor Dvorak for a month. But after that Dvorak came easily, you don't need an app to learn to type, you just learn to type by typing, slowly at first, then very soon, very fast. So with regard to C, I would say it is not objectively inferior like QWERTY became, it's actually pretty well designed. It does produce fast code. I use it myself sometimes, not a bad language for simple algorithm prototypes of under 60 lines. But it's based to a huge degree on characters, the difference between code that works and code that fails can come down to characters, C is about characters, pretty much any character, there's no margin of error. Whereas with Lisp, you have parentheses for everything, you have an interpreter but you can also compile it, I am actually able to trust Lisp in a way that is out of the question with C. There's just so incredibly many gotchas and pitfalls, buffer overflows, it's endless, you have to really know what you're doing if you want to do stunts with pointers, memory, void types. I guess the bottom line is if you're want your code to be perfect, and you write it in C, you can't delegate to the language, you yourself have to code that code perfectly in the human capacity of perfection.
- benreesman 5y agoHonestly at this point I’ve given in and am now advocating that we rewrite every damned widget from scratch in Rust, because by the time we’re mostly done, my career will be winding down, and seeing that shit still gets pwned like, exactly as much, will be “good TV”. Rust is cool because it’s got a solid-if-slow build story that doesn’t really buy into the otherwise ubiquitous .so brain damage. Rust is cool because Haskell Lego Edition is better than no Haskell at all, and Rust is cool because now that it’s proven affine/linear typing can work, someone will probably get it right soon. But if I can buy shares in: “shit still gets rocked constantly”, I’d like to know where.
- axiosgunnar 5y ago> Haskell Lego Edition Gatekeeping much?
- benreesman 5y agoI took the time to learn Rust well in spite of how annoying the Jehovas Witness routine has been for like, what, 5-10 years now? I worked with Carl and Yehuda both on the project right before Cargo (which is pretty solid, those guys don’t fuck around). I think I’ve paid my cover-fee on an opinion.
- benreesman 5y agoDo you have a different opinion on whether or not syntax for a clumsy Maybe/Either Monad is a bit awkward? Do you think that trait-bound semantics are as clean as proper type classes as concerns trying to get some gas mileage out of ad-hoc polymorphism? Do you think that the Rust folks might have scored a three-pointer on beating the Haskell folks to PITA-but-useable affine types? Or were you just dissing knowing things?
- deleted 5y ago[deleted]
- xavxav 5y ago> Honestly at this point I’ve given in and am now advocating that we rewrite every damned widget from scratch in Rust, because by the time we’re mostly done, my career will be winding down, and seeing that shit still gets pwned like, exactly as much, will be “good TV”. Rust won't solve logic bugs but it can help bring up the foundations. So long as memory safety bugs are so pervasive we can't even properly reason on a theoretical level about logic bugs. The core theorem of any type system is "type safety" which states that a well-typed program never goes wrong (gets stuck, aka UB). Only then can you properly tackle correctness issues. > Rust is cool because Haskell Lego Edition is better than no Haskell at all, and Rust is cool because now that it’s proven affine/linear typing can work, someone will probably get it right soon. I don't understand the condescending remarks about "Haskell Lego Edition". I do agree that Rust has shown that substructural type systems work and are useful, and that they will be a 'theme' in the next batch of languages (or I can hope).
- zuzun 5y agoMemory safety is optional in Rust. It might not be obvious at the moment, because Rust is written by enthusiasts who enjoy fighting with the compiler until their code compiles, but once developers will be forced to use it on their jobs with tight deadlines, unsafe becomes the pass-the-borrow-checker cheat code.
- Gigachad 5y agoI was under the impression that even in rust unsafe blocks, you still had massive safety advantages over C and it isn’t just instant Wild West.
- benreesman 5y agoI’d love to red team the program that thinks Rust unsafe is easier to get right than tight ANSI C.
- Closi 5y agoWhy compare 'non-tight' Rust against 'tight' C? Surely we should compare tight Rust (with some 'tight' unsafe sections) against tight C?
- benreesman 5y agoI must be more tired than I thought if I said “non-tight Rust” and forgot ten minutes later. I just think if mistakes need to be literally low as possible you’ve got a better bet than Rust unsafe. The language spec is smaller, the static analyzers have been getting tuned for decades, and the project leaders arent kinda hostile to people using it in the first place.
- nyanpasu64 5y agoI think it's easier to write correct safe Rust than C, I wouldn't say it's easier to write correct Rust with unsafe blocks than C (many operations strip provenance, you can't free a &UnsafeCell<T> created from a Box<T>, you can't mix &mut and const but you might be able to mix Vec<T> and const (https://github.com/rust-lang/unsafe-code-guidelines/issues/262 https://github.com/rust-lang/unsafe-code-guidelines/issues/2...), self-referential &mut or Pin<&mut> is likely unsound but undetermined), and it's absolutely more difficult to write sound unsafe Rust than C (sound unsafe Rust must make it impossible for callers to induce UB through any possible set of safe operations including interior mutability, logically inconsistent inputs, and panics).
- CyberRage 5y agoAs if rewriting entire OS components is easy or viable for vendors, even big ones like Apple or Microsoft. Also backwards compatibility is a feature many wouldn't give away for extra security, at least not now.
- alophawen 5y agoNobody said it would be easy, but it is already happening. https://medium.com/@tinocaer/how-microsoft-is-adopting-rust-e0f8816566ba https://medium.com/@tinocaer/how-microsoft-is-adopting-rust-... https://preettheman.medium.com/this-is-what-apple-uses-rust-for-37ddfb9e9237 https://preettheman.medium.com/this-is-what-apple-uses-rust-...
- CyberRage 5y agoDid you even read what you linked? I wouldn't say "already happening" more like first early steps. Operating systems have a massive attack surface, would take years to convert code from C\C++ to Rust and likely be more vulnerable initially(the old code base went through decades of scrutiny, hundreds of scanners\fuzzers etc)
- deleted 5y ago[deleted]
- saagarjha 5y agoI don't think Apple is shipping anything customer facing that's built on Rust?
- dagmx 5y agoNot in rust, but they did: - Add reference counting to ObjC to get rid of a lot of use after free bugs (still of course possible because it's just a language suggestion and not strictly enforced like Rust or Swift) - push for adding ObjC notations to let the tooling help catch some set of bugs. Still not perfect by any means but helps a little. - created an entirely new memory safe language as Swift.
- benreesman 5y ago
- lysozyme 5y agoThis tracks with your comment history https://news.ycombinator.com/item?id=567736 https://news.ycombinator.com/item?id=567736
- dang 5y agoPlease don't cross into personal attack. https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- benreesman 5y agoI think I’ve probably said something dumb to be cherry-picked more recently than 13 years ago.
- benreesman 5y agoHow well do the best and worst thing you’ve done in the last 7 days “track” with where you were at 13 years ago? We’re there any ups or downs during that time?
- scythe 5y agoIt doesn't have to be Rust. But for all the people who insisted for more than a decade that GCs and VMs don't necessarily compromise performance of practical applications, there has never been an acceptable browser engine in C#, Java, D, Common Lisp, Go, OCaml, Haskell or any of the others. Meanwhile Apple uses Objective-C with its ARC (and later Swift, which is even more like Rust) for everything and it was great. So the community tried to make OCaml with the memory model of ObjC and as much backwards compatibility with C as they could muster. In context, this doesn't seem like a weird strategy.
- NohatCoder 5y agoNothing wrong with Rust, but I still think making operating systems with airtight sandboxing and proper permission enforcement is the only thing that can truly solve these issues.
- jl6 5y agoStill not enough, because apps still need to interact with the outside world, so there would have to be intentional holes in the sandbox out through which the compromised app could act maliciously.
- NohatCoder 5y agoThat is why you need a well designed permission system. Android and iOs had a chance of doing this in a time when the requirements could reasonably be understood, but I don't think either came close.
- anon_123g987 5y agoAnd what language should we use to create such an OS? Maybe Rust?
- NohatCoder 5y agoIt is a better choice than C++ for sure.
- malwarebytess 5y agoMay I humbly suggest Holy C? https://www.youtube.com/watch?v=BUrbyfzm6i0 https://www.youtube.com/watch?v=BUrbyfzm6i0 https://templeos.holyc.xyz/Wb/Doc/HolyC.html https://templeos.holyc.xyz/Wb/Doc/HolyC.html
- rcxdude 5y agoOnly if the barriers have a finer resolution than a single application. Most applications need access to more than enough data to cause problems in the case of an exploit. You need sandboxing between different components of the application as well.
- radford-neal 5y agoWouldn't it be a lot easier to just use a C compiler that produces memory-safe code? I'm sure someone else has already thought of this, but in case not... All you need to do is represent a pointer by three addresses - the actual pointer, a low bound, and a high bound. Then *p = 0 compiles to code that checks that the pointer is in bounds before storing zero there. I believe such a compiler would conform to the C standard. Of course, programs that assume that a pointer is 64-bits in size and such won't work. But well-written "application level" programs (eg, a text editor) that have no need for such assumptions should work fine. There would be a performance degradation, of course, but it should be tolerable.
- retrac 5y agoYes, such approaches can be compliant. There's even a few C interpreters. Very popular back in the day for debugging C programs when you didn't have full OS debugging support for breakpoints and etc. Such an approach would be quite suitable for encapsulating untrusted code. There is definitely some major overhead, but I don't see why you couldn't use JIT.
- deleted 5y ago[deleted]
- xavxav 5y agoThere are similar approaches, ie: Checked-C which work surprisingly well. However, I'm not sure that this approach would be expressive enough to handle the edge cases of C craziness and pointer arithmetic. There's more to memory unsafety than writing to unallocated memory, even forcing a write to slightly wrong memory (ie setting `is_admin = true`) can be catastrophic.
- radford-neal 5y agoI think it handles all standards-conforming uses of pointer arithmetic. Even systems-level stuff like coercing an address used for memory-mapped IO may work. For example, struct dev { int a, b; } *p; p = (struct dev *) 0x12345678; should be able to set up p with bounds that allow access only to the a and b fields - eg, producing an error with int *q = (int *) p; q[2] = 0; Of course, it doesn't fix logic errors, such as setting a flag to true that shouldn't be set to true.
- tptacek 5y agoIt's worth engaging with the fact that essentially nobody disagrees with this (someone will here, but they don't matter), and that it's not happening not because Apple and Google don't want it to happen, but because it's incredibly, galactically hard to pull off. The Rust talent pool required to transition the entire attack surface of an iPhone from C, C++, and ObjC to Rust (substitute any other memory safe language, same deal) doesn't exist. The techniques required to train and scale such a talent pool are nascent and unproven. There is probably not a check Apple can write to fix this problem with memory safe programming languages. And Apple can write all possible checks. There's something profound about that.
- honkdaddy 5y agoIs that more-so due to a lack of Rust engineers or a lack of firmware engineers capable of rebuilding the iOS stack?
- rrradical 5y agoWell to some extent these companies are self sabotaging by centering interviews around algorithm problems, not only by selecting a certain kind if talent for further investment of resources, but also by signaling to the market the kinds of training needed to land a good job. If instead, the talent pool were incentivized to increase their ability to understand abstractions, and we selected for that kind of talent, it might not be so hard to use new languages.
- phendrenad2 5y agoAbstractions are fun, security isn't. I doubt there are even that many programmers who enjoy writing (correct, safe) Rust.
- rrradical 5y agoWait, this whole thread is about moving to languages that eliminate classes of security holes by virtue of the language itself. The premise is that being a security conscious programmer is not by itself enough to achieve good security.
- _wldu 5y agoI agree and anything above the OS layer can be written in Go or Java or C#. Lots of those devs out there to hire.
- phendrenad2 5y agoYou don't know what you're asking for. In reality, you'll end up replacing C code with memory unsafely with Rust code written by people who understand Rust less than they understand C. The problem? The Rust Evangelism Strike Force always assumes that if you replace a C program with a Rust program, it'll be done by a top-tier expert Rust programmer. If that isn't the case (which it won't be), then the whole thing falls apart. There are vulnerabilities in JS and Ruby code, languages that are even easier (and just as type-safe) as Rust.
- emerongi 5y agoI think the only question that matters is how much longer it takes to write a moderately-sized program in Rust vs C. If it takes around the same time, then an average C programmer will probably write code with more bugs than an average Rust programmer. If it takes longer in Rust, the Rust programmer could start taking some seriously unholy shortcuts to meet a deadline, therefore the result could be worse. All code can have bugs, it's mostly just a question of how many. Rust code doesn't have to have zero bugs to be better than C. It's not like all C programmers are top-tier programmers and all Rust programmers are the bottom of the barrel.
- xxpor 5y agoThis is part of the issue though: Writing things in C correctly takes more time than in rust (once you get past the initial learning curve) Writing things in C that appear to work may take less time. I think we can be reasonably sure that Apple didn't introduce those image parsing bugs intentionally. But that means they thought it was correct.
- dagmx 5y agoI've written a few things at work in C/C++ and Rust. I can move much faster in Rust, personally, as long as the pieces of the ecosystem I need are there. Obviously I only speak for myself. Part of that is because I'm working in code where security is constantly paramount, and trying to reason about a C or C++ codebase is incredibly difficult. Maybe I get lucky and things are using some kind of smart ptr, RAII and/or proper move semantics, but if they're not then I have to think about the entire call chain. In rust I can focus very locally on the logic and not have to try and keep the full codebase in my head
- ghusbands 5y agoAround 70% of security flaws are from memory unsafety (according to Google and Microsoft), which isn't "almost universally" but is still a significant percentage and worth attacking. But we'll still have a forest fire to fight afterwards from the other 30%.
- codechad 5y ago
- parentheses 5y agothe core problem is trusting a byte you read and use to make decisions. this is the superset of memory safety and not protected against by any language as of now. let’s kill bytes. :P