7 ms·
Rust wont save us, but its ideas will
- hknmtt 3y ago[dead]
- Animats 3y ago"Defense in depth" worked fine against amateur attacks. Well-funded attackers who can work on breaking each stage and have a library of attacks to combine are a much worse threat. More attacks like that are appearing. Stuxnet is the strongest example.
- HenriTEL 3y agoFrom my understanding it's the contrary. The success of Stuxnet relied on the fact that siemens recommended to not change the default passwords as it could affect the operations of critical infrastructure, which is not exactly what I would call defense in depth. Modern defense in depth would require the use of 2FA for manual access (in addition to strong passwords).
- rollcat 3y agoThat's a very pessimistic take. I think defense in depth works exactly as advertised: you need progressively disproportionate resources to mount successful attacks, to the point where you need state-level actors/funding. E.g. modern cryptography works, the proof being that the UK wants to change the law to effectively ban it. We've commoditized e2ee. The next step is to commoditize secure software, so that the baseline effort for any attack is too high for less determined / funded actors. You will still occasionally have to face a stuxnet, but we shouldn't need to face another epidemic of cryptolockers.
- MattPalmer1086 3y agoDefence in depth is a sound principle. It helps to raise the cost of successful attack, and to avoid single points of failure in your security architecture. It mitigates malicious attacks, human error and component failure. You are right that nation states can throw more resources at an attack. All you can do is make attacks as difficult and expensive as possible for an attacker to pull off without detection (commensurate with the value of the assets being protected).
- saagarjha 3y ago> More attacks like that are appearing. I don't think so. Generally as software becomes more secure the hacks you hear about will become more sophisticated to match, but this does not mean that they are more prevalent.
- vlovich123 3y agoThe example with IEF doesn’t make sense. Whether you declare a function private or public doesn’t impact its usability as a gadget. And as I understand it reading up on IEF, the problem with removeDatabase is when it’s exposed as a remotely callable API without any auth check which is a very different problem. Am I misunderstanding what the author is saying? I think the main problem with the article referenced in the submission is that percentages of vulnerabilities change based on the problem domain. The main threat for web facing services isn’t memory safety but that’s because most web facing services already use memory safe languages like JS, Java/JVM, Python, Ruby, or Go. It’s weird to pick Rust for its memory safety for web services. The reason to pick Rust is because you get C/C++ like performance without the memory safety issues. If you don’t need the perf, all the other languages are better choices because you’ll probably move quicker. It’s interesting that 20% are still memory vulnerabilities. Assuming this is all the same class of attacks on web services, that means 20% of applications do care about perf and have exploitable memory safety issues. Or the methodology is shoddy and they’re comparing different classes of software. Regardless, the premise of the first article is flawed and rife with statistical analysis problems that paint a misleading picture while the response isn’t infusing me with a lot of confidence on the merits and comes off as unnecessarily fanboish trying to stretch for a reason of “but no rust still makes sense”. 70% of vulnerabilities in Chrome are memory safety. This holds for similar classes of software written in c/C++ (eg Windows). There’s a reason all major c/c++ codebases have started getting grass roots and organizational support to transition away as quickly as possible.
- phicoh 3y agoRust has other advantages as well. For example, a common error when something goes wrong in Python is that a 'None' value ends up somewhere where it shouldn't be. Typically this None has traveled quite a while before some code tried to use it. The richer and stricter type system of Rust makes such errors a lot less likely. And if an error escapes, there usually is a way better indication of the origin of the error than just 'None'.
- pjmlp 3y agoMost of those Rust features over Python, that are commonly referred to, are available in any programming language of ML linage. Caml Light, SML, OCaml, Haskell, F#, Scala, and whatever else is out there. Most of them also come with a REPL, and have multiple toolchains, no need for always be waiting for the compiler.
- hyperhello 3y agoI'm only learning Rust, but the borrow checker and ownership and lifetimes could be duplicated in C with a little extra syntax, couldn't they?
- vlovich123 3y agoNo, there’s lots of technical reasons why. Not least of which is that c/c++ has be try very loose aliasing rules as well as the lack of a concept of move/drop (language nerds can chime in with all the other reasons). Even c++ would struggle even though committed members are aware c++ is dying and are trying to bridge the gap somehow. If you changed the language to support a Rust-like borrow checker, you’d lose back compat which defeats the purpose of stick with C semantics in the first place. There’s the related problem that the borrow checker isn’t automatic. There are places it does good inference, but any structure that has ownership needs to have that owner ship explicitly defined (and often in functions too). That is hard to do when you have to deal with a lot of legacy code that doesn’t have it - while that part can be solved through annotations, things inexpressible in the Rust borrow checker are perfectly legal C so you’d somehow also have to change that code. Additionally the Rust borrow checker can still fail spectacularly on very reasonable code. That’s being addressed in Polonius if that project ever lands, but even then it’s just a step function improvement to solve specific what should be valid code - it doesn’t fix all issues with the borrow checker. C++ is exploring gradual safeness to provide for optionally strengthening the safety but it’s unclear that approach actually makes sense other than as a balwark to c++ dieing completely (ie the switching cost would be weighed against the cost of fortifying the safety of the code and relying on a poor estimate of the risks involved since there’s too many unknowns) TLDR: structural, cultural, and back compat issues will prevent anything like the borrow checker.
- adastra22 3y agoWhy do you think C++ is dying? Maybe in your industry, but not in general.
- vlovich123 3y agoEvery major tech organization has indicated their shifting focus of their flagship products to shift the codebases from c/c++ to rust. Microsoft (Windows, Azure maybe office, not sure), Google (Chrome and probably a bunch of internal projects), Apple (various kernel pieces to harden and fix the ability to jailbreak). Linux has dipped its toe in the water with drivers but honestly I expect that to shift away from C and then eventually C will go into a “no new subsystem in C” policy followed by a “rewrite critical subsystems in pure rust). Dying doesn’t mean that there’s not going to be developers. It just means that it’s no longer growing and the ability to hire developers that have significant c/c++ experience will get harder and harder. It’s still very early days and c/c++ has a lot more legacy code still running than COBOL ever did and COBOL is still alive and kicking in a sense. I would still classify cobol as a largely dead language even though technically people still know it and the code is running. As for industry, could be. I imagine you think finance but I have a hard time seeing them stick to c/c++ if the rest of tech proper has switched. For new projects, maintenance will be cheaper because of things like cargo crates and other ecosystem niceties that c/c++ will never have. And rust performance is on par with c/C++. So what would be the case for starting any new project in c/C++? I’m not predicting a timeline. I’m just describing a clear trend. It could easily take 50+ years. Depends on investments by corporations + grass roots + how effective the c++ committee is at stopping the bleeding + whether the rust community does an own goal like trying to standardize the language through ISO which is a huge contributor for why c++ and c will be unable to adjust. But right now rust has a clear velocity and acceleration advantage and has achieved “escape” velocity for when a language will likely take over for another.
- self_awareness 3y agoI think the author cheats a little bit, because in the first example on "IEF" he compares a function declaration containing an explicit visibility modifier "public" to the default Rust version (private). But in reality, omitting Java visibility keyword puts the function into the "default" visibility rules, which is package-private. So, public in the same package, but private when seen from other packages. So the impact is severily limited, depending on the architecture of the application (it's de facto public for applications contained in 1 package). Still, Rust version is more restrictive, so the point holds, but I think it should be fixed somehow.
- OskarS 3y agoYeah, I had the same reaction, it was a very bad strawman: the author had explicitly set the function to be public in the Java example, and then not done so in the Rust example, and then argued that Rust is safer. But that's absurd: you deliberately made dropDatabase public in Java, which you could just as easily do in Rust by making it pub. The author just opted not to do that in order to argue that Rust is safer. Your argument is fair that the "default" state in Rust is more restrictive, but the difference honestly is tiny. In practice, basically all Java code I've seen always explicitly states whether every function is private, public or protected, that's just how you write Java. Should it be compiler-enforced that you always do so? Maybe, but we're really splitting hairs here.
- self_awareness 3y agoTrue, I've written "the argument holds" in strictly theoretical sense that Rust version is more restrictive, but since the degree of this restriction is so small, I don't think this particular trait has any impact on security of anything.
- _zagj 3y ago> We should expect all our languages to be safer. My prediction is modern C++, and even (looking at C23) modern C, will be evolved, albeit gradually, to offer enough of Rust's safety so that on a cost-benefit analysis of either updating an existing C or C++ codebase to its modern, safer dialect or rewriting it in Rust, it will be a no-brainer to stick with C or C++. Rust will ultimately become a marginal language, like (sorry) Zig: https://www.phoronix.com/news/CPP-Linux-Kernel-2024-Discuss https://www.phoronix.com/news/CPP-Linux-Kernel-2024-Discuss
- pjmlp 3y agoC++ is already a much safer C, yet plenty insist in using it like C, full of Cisms. When copy paste compatibility to C is available, only regulated industry practices like MISRA force devs to adopt them.
- PhilipRoman 3y agoI don't know about that. The average C++ software is probably safer purely because you can delegate most memory management to standard library. But I've found C to be much easier to reason about. You can inline all the functions and macros and all that's left is a bunch of pointer assignments and arithmetic. C++ has a much more complicated lifetime model which is surprisingly easy to violate. Combined with templates, it becomes really difficult to dig in. Due to this, C is much more practical to use with formal verification tools like Frama-C and various model checkers. If Rust had a restricted subset which had a footprint compared to C and allows formal verification (including functional requirements) I would switch right now.
- lll-o-lll 3y agoSo, like Zig then?
- dannymi 3y ago>If Rust had a restricted subset which had a footprint compared to C Take a look at "#![no_std]", a Rust feature. If you do that, your Rust Hello World program will have 14 kiB (with no linker optimizations). >and allows formal verification (including functional requirements) See <https://rust-formal-methods.github.io/tools.html https://rust-formal-methods.github.io/tools.html>. Also, the Rust compiler can be used as a library and you can add whatever checks you want like that. See <https://yoric.github.io/post/uom.rs/ https://yoric.github.io/post/uom.rs/> for an example (not used that much). Also, I like <https://docs.rs/pre/latest/pre/attr.pre.html https://docs.rs/pre/latest/pre/attr.pre.html>. It allows you to define and then mandate specifying textual requirements (in addition to the usual conditionals).
- jillesvangurp 3y agoI actually enjoyed reading this and found this somewhat insightful. A critique of modern languages is that while they are more rigorous, there is still the issue of module visibility which is kind of weak and limited. For example, Java has packages and a notion of package private. But that was always a bit of a weak form of modularization. So you end up with a lot of public functions just so some code in a different package can reach it. And while packages are hierarchical, visibility ignores that notion. Java of course has proper modules now. But they are a weak derivative of things like OSGI that while widely used at some point never really went mainstream. Module visibility in OSGI included explicitly defining exposed and required interfaces. If not exposed explicitly, the class loader would prevent you from calling it. Even if it was defined as public. That kind of mechanisms are still missing in most languages. You kind of get some of this by using micro-services. But routing your function calls over a network is kind of stupid from a performance point of view. It doesn't scale. I've seen some graphql based systems that are a bit challenged on this front. There are other examples of trying to solve this problem outside of the compiler at run/deploy time. A lot of sandboxing used for docker, wasm, etc. is basically about that. But that is kind of mitigating the lack of solutions at the source code level. OSGI was clunky but it definitely had some interesting ideas. Very sad that that never caught on.
- dash2 3y agoThis article indeed did not make sense. The key point it doesn't get is that the majority of issues described in the original were not deeply embedded in the language. They weren't use-after-free etc. They were simply the programmer doing something bad, where something bad is highly domain-specific. There will never be language-level protection against e.g. trusting a URL which you shouldn't trust, or making a function public when it should be private, because languages have to be general enough to trust some URLs and make some functions public. Languages cannot take away the responsibility of the programmer not to do stupid stuff.
- deleted 3y ago[deleted]
- xyzzy123 3y agoAgree you can't kill all the badness, but e.g. web security has gotten better in many respects primarily (I have no proof of this claim but I was a pentester for a long time) because of improvements in libraries and frameworks. I don't think Rust offers anything special in this regard however. Rather I think it is better understanding of the security nuances of particular problem domains that lead to api safety improvements. Devs today are not particularly better at preventing xss or sqli than they used to be but the default tools they reach for have APIs that make it harder to do the wrong thing.
- saagarjha 3y agoLanguages can actually help here! They aren't a panacea, of course, but you can do all sorts of things like encode things into the type system ("this is a safe string, you cannot put user tainted input into it without escaping it") or be amenable to static analysis ("this variable is not declared") or even manual code review ("I can understand the entire semantics of this block of code because it is impossible to override the behavior of the operations here").
- berkes 3y agoA fair point that programers mustn't do stupid stuff. But languages (and frameworks) can help a lot with that. When a language (or framework) makes it easy to do the right thing, and hard to do the bad thing, a large category of "stupid stuff" is avoided. I'm lazy, or tired, or stressed, or focused elsewhere. Make it so, that at these moments I'm forced to run extra miles to "do stupid stuff" and we've avoided several bugs (or code smells and such). Like you say, that still leaves the domain logic to make mistakes in. But if we could make our mistakes only there, we've eliminated a lot of bugs too: we only have to pay extra close attention in a fraction of our codebase! Now,we aren't there. Rust isn't, at least. There's still a lot of boilerplate or utility code where I can (and will) do stupid stuff. But rust, with it's proper defaults, secure by defaults, is a lot closer than most other languages. And rusts' emerging frameworks inherit that mindset and help us get closer even.
- steinuil 3y agoThis post is not very good, sorry. Let's start with the first example about IEF: first of all, I think that the security advisory was mostly referring to web APIs that allow users without the necessary permissions to perform actions they shouldn't be able to. If you can already call Java APIs you already have access to the machine so it matters little what visibility the method was declared with. And as somebody else mentioned, the default visibility for Java methods is package-private. Second example about the URL interception: first of all, you could have `match`ed on the result of `strip_prefix` instead of checking `starts_with` and then `unwrap`ping the result of the former. Second, why not use a URI parsing library? And third: that is not what checking the source of the URL means in this context! I'm assuming there's a way to tell what is the URL currently shown on the webview, and that you should check that before doing an RPC. The Rust code example shown in the post is functionally identical to the Java version. Also, `&str` doesn't mean the string size is known at compile time, the bounds checks are all performed at runtime. Third example about path traversal: again, that's functionally the same code as the Java version. What is missing in both is a check that the path is relative to a well-known list of paths and doesn't contain any `..` which could possibly lead to, well, a path traversal vulnerability! I appreciate the effort that went into the post and I agree that Rust is still better than many other languages out there (because of its API design in many important areas), but man, this ain't it.
- Havoc 3y agoEven if you can only eliminate the 19% memory related ones - that’s a huge win.
- fogus 3y agoNo programming language is more important than its best and worst ideas.
- Levitating 3y agoConcerning Chromium: [1] > Around 70% of our high severity security bugs are memory unsafety problems (that is, mistakes with C/C++ pointers). Half of those are use-after-free bugs. Rust isn't just about cyber security. [1]: https://www.chromium.org/Home/chromium-security/memory-safety/ https://www.chromium.org/Home/chromium-security/memory-safet...
- deterministic 3y agoAs far as I understand there are no new ideas in Rust. Linear types (for example) was invented in academia a long time ago. So perhaps a more accurate statement would be that it is the first practical programming language to implement those ideas? But what about F* (F-star) for example? That is a language used by Microsoft to write a proven correct network stack used in industry (and Firefox I think). That seems very practical to me.