29 ms·
Testing the memory safe Rust implementation of Sudo/Su
- hfkwer 3y agoIs sudo known to be memory _un_safe? Because otherwise, calling this one "the memory safe [Rust] implementation of Sudo" is a bit weird.
- dannymi 3y agoSudo 1.8.0 to 1.9.12 (the latter is from 2023(!)) are memory unsafe. Sudo before 1.9.5p2 is memory unsafe. Sudo before 1.8.26 is memory unsafe. Sudo before 1.6.6 is memory unsafe. Source: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=sudo https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=sudo
- peoplefromibiza 3y agomost of the issues linked are not memory related. Am I missing something?
- iknowstuff 3y agoYou’re missing the ones that are
- c_crank 3y agoOnly six entries mention overflows, only half of those involve the heap.
- dspillett 3y agoA number of those entries reference multiple overflows. And a memory safe language will protect against some overflows on the stack (overflows within frames corrupting other values, rather than errant loops that blow the stack by creating too many frames and/or too large frames).
- c_crank 3y agoYeah, if you really wanted to be extra super secure, you can always rewrite it in Java or something.
- gpm 3y agoRust will protect against all overflows on the stack (up to compiler bugs, tier 2 and lower platforms do not necessarily get this guarantee). If you use too much stack space, it terminates the program. It does now however allow for arbitrary code execution like most C compilers do.
- asveikau 3y agoAre you aware of what an exploitable scenario of using too much stack space looks like? The buffer needs to be so large that it not only exceeds the offset to the guard page, but it reaches a non-faulting address. Lastly it needs to be accessed from the front first rather than the back. I don't know if compilers commonly generate benign memory accesses from the back of the buffer for large stack allocations to get the page fault handler going. I thought that they did after some prominent Linux exploits in this area. If they do do that, this is safe. Also, this issue would also affect the rust compiler, so they must employ that strategy if this works.
- dspillett 3y agoThat each of the versions dannymi listed had at least one potentially exploitable issue that a natively memory safe language would have mitigated, versions actively used in production as recently as this year even by people who keep bang up-to-date? I'm sceptical that the chance of introducing new and interesting bugs of other varieties with a rewrite is worth the protection offered by the new environment¹, but either your dismissal of dannymi's point is rather disingenuous or you genuinely were missing something that had been stated quite obviously… -- [1] except where existing problems are so systemic that fixing them in the original stack would effectively be a partial rewrite anyway, so susceptible to the same risk
- peoplefromibiza 3y ago> That each of the versions dannymi listed had at least one potentially exploitable Can you please point me to each one of those? I can only see a few of them. > memory safe language would have mitigated potentially, assuming there are no bugs anywhere in the toolchain. > but either your dismissal of dannymi's point I wasn't dismissing no one's point. I simply scrolled through the list of issues and found out that the majority of them were things like (picked them randomly) systemd before 247 does not adequately block local privilege escalation for some Sudo configurations, e.g., plausible sudoers files in which the "systemctl status" command may be executed. Specifically, systemd does not set LESSSECURE to 1, and thus other programs may be launched from the less program. This presents a substantial security risk when running systemctl from Sudo, because less executes as root when the terminal size is too small to show the complete systemctl output. An issue was discovered in Zimbra Collaboration (ZCS) 8.8.x and 9.x (e.g., 8.8.15). The Sudo configuration permits the zimbra user to execute the NGINX binary as root with arbitrary parameters. As part of its intended functionality, NGINX can load a user-defined configuration file, which includes plugins in the form of .so files, which also execute as root. A privilege escalation vulnerability in FortiNAC version below 8.8.2 may allow an admin user to escalate the privileges to root by abusing the sudo privileges. It was found that cifs-utils' mount.cifs was invoking a shell when requesting the Samba password, which could be used to inject arbitrary commands. An attacker able to invoke mount.cifs with special permission, such as via sudo rules, could use this flaw to escalate their privileges I am genuinely asking if memory safe languages could prevent this kind of issues, which represent the overwhelming majority of the issues reported on that specific page, and how.
- jeffbee 3y agoSudo has displayed an endless parade of heap overflows and suchlike. It is written in the extreme YOLO style by people with very poor taste.
- peoplefromibiza 3y ago> Sudo has displayed an endless parade of heap overflows and suchlike. sudo is 43 years old though > It is written in the extreme YOLO style by people with very poor taste. Sounds a bit exaggerated to me. Do you happen to have data on this?
- Veserv 3y agoHow many hundreds of thousands of lines of code do you think sudo is? How many hundreds of thousands of lines of churn do you think happen per year in sudo? If your answer is: What do you mean hundreds of thousands? That is the right question, but the wrong answer. The answers being around ~500,000 and on average ~200,000, including this year, respectively. In contrast, OpenBSD doas, which exists to serve the same primary purpose of executing commands as a super user, clocks in somewhere around a few hundred to maybe 1 or 2 thousand lines total just eyeballing it.
- 0cf8612b2e1e 3y agoI must have a fundamental misunderstanding of exactly what sudo does. That is so much code.
- j16sdiz 3y agosudo integrates with PAM, parse command, sends email, record session logs, do IPC.....
- littlestymaar 3y agoTurns out even in the 80s the so-called “UNIX philosophy” wasn't so ubiquitous…
- deleted 3y ago[deleted]
- woodruffw 3y agoOn a basic level: programs written in C almost always have memory access patterns that can't be proven safe generally. sudo, in particular, has had a few public bugs over the past few years that directly trigger potentially exploitable memory unsafety[1][2]. Note that not all bugs receive public reports, much less are assigned CVEs. Rust's memory semantics are safe by construction: unless you intentionally write the the part of the language that requires you to explicitly mark things as unsafe, your programs cannot contain the kinds of temporal or spatial memory bugs that can occur in C and C++. Given that, calling this the "memory safe" implementation seems pretty reasonable, in the same way that calling a Java or Python implementation of sudo "memory safe" would also be reasonable. [1]: https://www.cvedetails.com/cve/CVE-2021-3156/ https://www.cvedetails.com/cve/CVE-2021-3156/ [2]: https://www.cvedetails.com/cve/CVE-2019-18634/ https://www.cvedetails.com/cve/CVE-2019-18634/
- nullc 3y agoSo 6 out of 174 CVEs could have been avoided this way. ... but how many more of the unavoided logic errors will be created by using a language which is far more complicated, less clear, and readable/reviewable to far fewer people? That said, It's a great sign for that the tests that it was was comprehensive enough to find bugs in the original sudo. But a set of tests isn't really complete until it finds a compiler bug too. :)
- iknowstuff 3y agoRust is far more readable and reviewable than C code. As attested by 1000 Googlers.
- c_crank 3y agoI wouldn't trust Googlers as a measure of any sort of quality, given their love of Go. C code relying on tons of macros will be harder to read then C code that delegates preprocessing to another language. Rust code that leans heavily into the ML features and unwrap.parent.unwrap.parent.unwap... will be a lot more unpleasant than Rust code written to just get the bit shifting job done. I imagine it really depends on the code base.
- jeffbee 3y agoYou might be overestimating the popularity of Go within Google. That said, a tool like sudo should be written almost entirely in a very high-level language that is easy to use and review. C, C++, or even Rust should be reserved for places where the system interface requires it, if there are any such points of interface.
- c_crank 3y agoA job for Common Lisp!
- Chabsff 3y agoOn the flip side, languages like C,C++ and Rust have the major benefit of having next to no runtime component to it, allowing trace-driven fuzz testing to achieve a much higher level of confidence in its test coverage. For a tool like sudo, this can matter a lot.
- JeremyBarbosa 3y agoIf you want to move away from Sudo, but don't want to try this rust implementation just yet, I have had great success with OpenBSD's doas. It has been ported to every Linux distro I know of as well: https://github.com/Duncaen/OpenDoas https://github.com/Duncaen/OpenDoas
- inferiorhuman 3y agoThere's also a straight port of doas: https://github.com/slicer69/doas/ https://github.com/slicer69/doas/ However unlike sudo and opendoas this does not implement the persist feature on not-OpenBSD.
- curtis3389 3y agodoas is great with 2 caveats (from my experience on debian): the persist feature has a sketchy implementation that didn't work; and plenty of other software assumes you use sudo and may require it as a dependency.
- PhilipRoman 3y agoRegarding software support - the situation is definitely improving. I remember being pleasantly surprised that various Arch package management tools support it out of the box and I didn't even bother installing sudo on Debian.
- thiht 3y ago> If you want to move away from Sudo Is there something wrong with sudo?
- bayindirh 3y agoCurrently vendoring all of the dependencies for Rust implementation pulls in 1.75 million SLOC, which I find amusing. This is a lot of SLOC, and a huge surface area to pull targeted supply-chain attacks, IMO. P.S.: I know you don't compile in all of this into the binary, yet consider the eyes and work hours required to verify that the whole chain is sane and safe. This is how it looks: vagrant@rust-playground:~/development/sudo-rs$ cloc . 3549 text files. 3271 unique files. 453 files ignored. 1 error: Line count, exceeded timeout: ./vendor/proc-macro2/src/parse.rs github.com/AlDanial/cloc v 1.86 T=9.67 s (320.2 files/s, 208065.8 lines/s) -------------------------------------------------------------------------------- Language files blank comment code -------------------------------------------------------------------------------- Rust 2637 49276 111413 1754298 diff 2 884 32618 35892 Markdown 182 4903 9 13341 TOML 137 807 1073 5734 Assembly 8 90 71 1244 YAML 5 80 26 393 JSON 106 0 0 120 reStructuredText 1 70 4 90 C/C++ Header 9 5 2 79 Bourne Shell 5 14 17 64 C 2 6 6 46 Bourne Again Shell 2 7 8 41 Python 1 17 19 38 Dockerfile 1 0 0 2 -------------------------------------------------------------------------------- SUM: 3098 56159 145266 1811382 --------------------------------------------------------------------------------
- hkwerf 3y agoIn general, you have a very valid point, but how many lines of code do we need to build the normal sudo if you are generously adding stuff we don't compile into the binary? Compiler, tools, some machine with some userspace and kernel for those to run on and so on?
- Zamiel_Snawley 3y agoAs others have mentioned, there is a long list of sudo CVEs that are unrelated to memory safety. I didn't see it mentioned in the article, but I hope that they have mined the CVEs for tests to ensure they don't accidentally reintroduce a known vulnerability. I was also surprised to see no mention of tests originally written for ogsudo, surely there are some? Overall, I appreciate the rewrite-it-in-rust 'movement', I think it is an excellent learning opportunity for people who may not otherwise bother with learning the details of the foundations of our modern systems. And, as in this case, taking a detailed look at the original can improve the original.
- jackmott42 3y agoOne of the famous non memory safety bugs in sudo recently was related to using a sigil, which Rust would have prevented because the natural and easy solution in Rust for those use cases is an Enum/Sum Type. Which is to say that Rust has safety features beyond just what we are used to from garbage collected languages. Sum types, stricter typing, data race protections, etc.
- c_crank 3y agoA whole laundry list of languages have stricter typing than C, garbage collected or not.
- Zamiel_Snawley 3y agoAnd yet, Rust is being taken seriously in many places where those languages have been unable to displace C. I wonder if it hadn't taken 15 years for a FOSS Ada compiler to become available, maybe it would have taken off.
- c_crank 3y agoAda never had the same level of marketing power towards engineers that Mozilla came up with. GNAT still came out well before Rust did.
- shrubble 3y agoTo be blunt, I don't think that this really matters very much. The reason is that if you used Pascal or Modula-2 , both of which use "counted strings" you would very likely have the same kind of safety. I think the potential of Rust is greatly oversold, because it only ever gets compared to known-unsafe cases, such as string handling in C; there are plenty of other languages that handle this safely out of the box. And Modula-2 is in the GCC 13 compiler and FreePascal has been out for over a decade at this point; both languages are far more compact and have formal specifications...
- aaomidi 3y ago80% of bugs come back to memory safety… don’t think it’s overselling it. Sure other language can do better here too, but you’re not just getting memory safety from Rust.
- lelanthran 3y ago> 80% of bugs come back to memory safety… don’t think it’s overselling it. I think you are misremembering the statistic. It's 70% of security bugs that are related to memory safety: https://www.zdnet.com/article/chrome-70-of-all-security-bugs-are-memory-safety-issues/ https://www.zdnet.com/article/chrome-70-of-all-security-bugs... The way you say it, it means that out of every 100 bugs, 80 are due to memory safety. The reality is that out of every 100 security bugs, 70 are due to memory safety. For example, a codebase with a thousand bugs might only have 10 that are security bugs, of which 7 are due to memory safety. You imply that a codebase with a thousand bugs have 800 memory safety issues.
- majewsky 3y agoThe framing in the last two lines only makes sense if you consider the amount of total bugs as a prior. In practice, the more realistic prior is something that's more observable, e.g. the number or rate of published CVEs or of security breaches. If something like that can be reduced by 70%, that's much more significant than your framing of "0.7% of all bugs in this example are security bugs due to memory safety" makes it out to be.
- PhilipRoman 3y agoMemory safety is just the tip of the iceberg of issues with sudo. Repeat after me - sudo is not a security tool. Maybe if you stick with a tiny subset of it then yes. But that subset would be better off being its own program (doas).
- aaomidi 3y agoWhy would it be better being it’s own program?