[HN Gopher] Bringing Memory Safety to sudo and su
___________________________________________________________________
Bringing Memory Safety to sudo and su
Author : mritzmann
Score : 69 points
Date : 2023-04-26 14:39 UTC (8 hours ago)
(HTM) web link (www.memorysafety.org)
(TXT) w3m dump (www.memorysafety.org)
| jmclnx wrote:
| Will this replace the current sudo ?
| zimpenfish wrote:
| There's always doas[1] if you want a simpler, safer version.
|
| [1] https://en.wikipedia.org/wiki/Doas
| Gigachad wrote:
| Still written in an insecure language.
| dochtman wrote:
| It's a separate project. We'll see if/when these new Rust-based
| versions become good enough for people to adopt as their daily
| driver sudo/su.
| therein wrote:
| I am sure they'll use the same name, though. Hard to come up
| with a name for this one.
|
| rsu, rsudo
|
| surs, sudors (and then /etc/sudorsers as the cherry on top)
| hannob wrote:
| This sounds good, however, I hope they don't try to replicate all
| of sudo.
|
| sudo fails a basic security principle on Unix systems, and that
| is that suid binaries should be simple. Their developers have a
| tendency to add all kinds of stuff that barely anyone ever uses,
| but that bloats its size.
| rnijveld wrote:
| Definitely one of the things that is on our radar! Lots of
| features in sudo are just basically legacy features, remnants
| from the 90s or 00s that are no longer necessary in a modern
| setup, but nevertheless exist because in past times they used
| to be the default or only option. We are particularly aware of
| how much power a suid binary has, so we do try to be cautious!
| steveklabnik wrote:
| If you read the README https://github.com/memorysafety/sudo-rs
|
| > Our current target is to build a drop-in replacement for most
| basic use cases of sudo. ...
|
| > Some parts of the original sudo are explicitly not in scope.
| Sudo has a large and rich history and some of the features
| available in the original sudo implementation are largely
| unused or only available for legacy platforms. In order to
| determine which features make it we both consider whether the
| feature is relevant for modern systems, and whether it will
| receive at very least decent usage. Finally of course a feature
| should not compromise the safety of the whole program.
|
| So seems like they're on the same wavelength as you are.
| stephc_int13 wrote:
| This so-called memory safety is looking like a buzzword
| engineered to be extremely appealing to a type of mildly
| technical but mostly illiterate about computer security kind of
| people.
|
| This has been said before, this has been tried before, OOP was
| also seen as silver bullet at some point, like several others.
|
| Computer security is a deeply complex and dirty field, switching
| programming language won't help much if programmers are expecting
| the work to be done for them by the compiler.
|
| If you want robust code : hire experts in the field and pay the
| price.
|
| Rewriting sudo is almost certainly going to be painful and to
| increase the vulnerabilities potential.
| cedilla wrote:
| Alright, I'll take the obvious bait.
|
| The experts in the field are right over there, getting paid to
| rewrite it in rust.
| stephc_int13 wrote:
| Experts with Rust? Experts about sudo implementation
| requirements? Or computer security experts? Because you'll
| probably need all of that.
| notorandit wrote:
| > But because it's written in C, sudo has experienced many
| vulnerabilities related to memory safety issues.
|
| Or because it's not been developed with enough care?
|
| I for one think that there is no unsafe language, only careless
| programmers.
| rnijveld wrote:
| I think your expectations are too high. During our initial
| exploration we actually managed to talk to Todd Miller, the
| maintainer of sudo. In our (brief) interactions with him he did
| not sound cavalier like this at all. Instead I think that a lot
| of the issues with sudo are more about it being a thirty+ year
| old program and codebase, and sometimes features turn into bugs
| and security issues all on their own in such time periods. But
| then again, C just cannot offer the kinds of protections that
| Rust can, and mistakes will be made eventually by every human,
| better to have some protection from your mistakes than none at
| all.
| actionfromafar wrote:
| Right! Like with airplanes, there are no unsafe airplanes, only
| careless pilots.
| stephc_int13 wrote:
| This analogy is completely wrong. The programmer would be the
| aero engineer, not the pilot.
|
| The pilot would be the sysadmin, maybe?
| justin_oaks wrote:
| > there is no unsafe language
|
| Perhaps you didn't intend it this way, but that implies that
| there is no difference in safety between languages. This is a
| patently absurd idea.
|
| C is clearly less safe than many languages that don't allow
| unsafe memory practices.
| musicale wrote:
| A few years back I was annoyed that sudo would consistently crash
| with a memory error.
| Dolamifa wrote:
| Can't be more excited for that!
| nhellman wrote:
| There is also 'doas' from the OpenBSD project. It's a replacement
| for 'sudo' with fewer features and a smaller codebase, with the
| aim of a smaller attack surface.
|
| https://en.m.wikipedia.org/wiki/Doas
| smabie wrote:
| Though written in C for no apparent reason. It's ironic to me
| how security focused OpenBSD is while at the same time looking
| down on any other language besides C.
| JohnFen wrote:
| Just because something is written in C doesn't automatically
| mean it's unsafe. It's 100% possible to write safe C code.
| It's just not "automatic".
| Gigachad wrote:
| Safe C code is like functional communism, we are yet to see
| a real example. It probably could exist though.
| rhdunn wrote:
| SQLite? That has an extensive test suite and has been
| extensively vetted/checked.
| dwattttt wrote:
| True, but there are quite a few CVEs (of varying
| severity) https://www.cvedetails.com/vulnerability-
| list/vendor_id-9237...
|
| Another way to look at that is "SQlite has had these bugs
| in the past, and our standards are unlikely to be that
| high". It does deal with a quite complex problem domain,
| but is still a strong warning re. vulnerabilities in C.
| yjftsjthsd-h wrote:
| > for no apparent reason
|
| Here's the list of hardware platforms that OpenBSD supports:
|
| https://www.openbsd.org/plat.html
|
| Note that when they say support, they mean that it's fully
| supported and actually works well, including that OpenBSD is
| fully self-hosting on that platform (read: "oops, the
| compiler OOMs on 32-bit" is a no-go).
|
| Now, here's the list of targets that rust supports:
|
| https://doc.rust-lang.org/beta/rustc/platform-support.html
|
| Notice that _all_ the OpenBSD targets are tier 3, and it 's a
| strict subset of OpenBSD's platoforms. Even if we ignore
| everything else - a questionable choice - rust is unsuitable
| for writing core parts of OpenBSD because it can't actually
| build for all the systems that OpenBSD supports.
| jcranmer wrote:
| The point GP was (probably) trying to make is that
| OpenBSD's vision of security is at odds with its insistence
| on C, a notoriously unsafe and insecure language. There's
| no reason that the replacement language has to be Rust; it
| could be Nim or Zig or C# or Java or Vala or OpenBSD Custom
| Memory-Safe Language.
|
| What it takes for OpenBSD to choose to support whichever
| language it wants to is primarily a commitment to actually
| spend its resources to support said language. That the
| OpenBSD targets for Rust are tier 3 is a sign of its
| unwillingness to consider moving away from C: what it takes
| to move from tier 3 to tier 2 is a set of maintainers who
| have a commitment to be responsive to patches, and an
| automated CI solution.
|
| (Also note that OpenBSD is the largest Unix "stuck" in tier
| 3 for Rust. Solaris/Illumos, FreeBSD, and NetBSD all manage
| to have tier 2 builders. Even Fuchsia and Redox have tier 2
| support!)
| tedunangst wrote:
| I think sometimes people forget the openbsd project was
| not started with a text editor opening an empty file.
| Karellen wrote:
| OpenBSD doesn't have a Rust compiler in their core system.
| Having a core utility written in a language that isn't
| buildable with tools in their core system is a non-starter.
|
| Once they have their own Rust compiler, or are able to import
| a Rust compiler that supports OpenBSD to the point where bugs
| on that platform are release-blockers for that compiler, and
| which is suitably licensed, they should be able to start
| (re-)writing core tools in Rust.
| hannob wrote:
| Yeah, but...
|
| Recently learned that it doesn't implement using a new pty,
| which makes it vulnerable to TIOCSTI and TIOCLINUX ioctl
| attacks. Which doesn't matter on OpenBSD, because OpenBSD does
| not have these features. But Linux does, so not ideal.
| https://github.com/Duncaen/OpenDoas/issues/106
| rnijveld wrote:
| I'm on the team that is implementing sudo-rs, and we are
| definitely aware of doas and other similar utilities. Doas does
| definitely have its usages, especially with the 'just let me
| run this as root' use case in mind. That said, there is also
| something to say for the more extensive configurability of
| sudo, and doas does sometimes have an execution model that
| might be a little too simple. And having another alternative is
| never a bad thing in my mind.
| rurban wrote:
| Memory safety would be good, but why then use a memory unsafe
| language?
| PeterWhittaker wrote:
| Correct me if I am wrong, but isn't Rust unsafe only when
| explicitly using unsafe? Provided this project does not do
| that, it would be memory safe, no?
| sc68cal wrote:
| My concern is that while re-implementing sudo in rust would solve
| bugs due to memory safety and off by one errors, it is a complex
| piece of software where logic errors can create serious security
| issues.
|
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2280...
| rnijveld wrote:
| I'm one of the people working on this. While I do think that
| the memory safety aspect is an important one, I think that one
| thing where we can win even more is that Rust has a type system
| that is much more robust than what C offers. If set up right,
| we can prevent lots of these kinds of bugs right from the
| start. We can also simplify things in lots of cases by removing
| unnecessary details no longer relevant in a modern
| implementation.
| hannob wrote:
| > it is a complex piece of software
|
| That's the problem. It shouldn't be. I hope the sudo-rs variant
| does better.
| yjftsjthsd-h wrote:
| Actually, there's a point: doas is already smaller and safer,
| so it would probably be easier to port to a new language as
| well as having less attack surface in the first place. Of
| course, it's still necessary to work with sudo as well
| because it genuinely supports a lot more features and some of
| them are even useful, but if you want the low hanging
| fruit...
| ape4 wrote:
| They should just replace /etc/sudoers.d with a Domain
| Specific Language ;) /s
| throwawaaarrgh wrote:
| [flagged]
| jcranmer wrote:
| Rust protects against most memory safety vulnerabilities:
| use-after-free, out-of-bounds accesses, returning dangling
| pointers. Probably the memory safety vulnerability it's the
| least protective against is using uninitialized memory. And
| recall that memory safety vulnerabilities are the vast
| majority of software vulnerabilities--somewhere in the 70+%
| range.
|
| But Rust doesn't _only_ touch memory safety, it also has some
| measure of protection for other vulnerabilities. It 's
| somewhat stricter on integer overflow vulnerabilities.
| Newtypes can be used to provide protection against validation
| vulnerabilities (e.g., SQL injection). Send and Sync traits
| can provide some measure of protection against data races: it
| takes a little bit of effort to use an object on a different
| thread if it's not able to be used from multiple threads. You
| don't hear as much about these protection efforts because,
| quite frankly, memory safety is so important that it alone is
| sufficient to drive many decisions.
| woodruffw wrote:
| "Free-after-use" is not a vulnerability class; it's "use-
| after-free." And Rust's borrow checker provides temporal
| memory safety; you could even say that it _primarily_ exists
| to prevent temporal vulnerability classes like UAFs.
| Rusky wrote:
| This isn't how people seriously approach memory safety.
|
| Memory safety is a critical _starting point_ , because
| without it you can no longer trust the logic you wrote in
| your program to behave in any particular bounded way. Memory
| safety bugs undermine everything else.
| IshKebab wrote:
| Fortunately Rust also has a very good type system and strict
| ownership system that greatly reduces the chance of logic
| bugs too.
|
| Imagine not using seatbelts because they don't help if
| someone shoots you in the face.
| steveklabnik wrote:
| You are not wrong, but logic errors are a pervasive concept
| that applies to all code bases. Logic errors in the existing
| codebase, as you've demonstrated, can _also_ cause issues. The
| pro-Rust argument here would be "letting the compiler handle
| memory safety for you frees up your attention to focus on those
| logic errors even more."
|
| Time will tell!
| tptacek wrote:
| That's not really responsive to the concern. The issue is
| that we've already had decades of experience with the
| existing sudo codebase looking for logic vulnerabilities.
| And, in fact, that's what the overwhelming majority of sudo
| vulnerabilities are; they're not generally memory safety
| bugs. So rewriting in a new language to get rid of memory
| safety vulnerabilities is not, in fact, an obviously good
| tradeoff.
| steveklabnik wrote:
| I don't _directly_ disagree with what you 're saying here
| either. All of these things need to be weighed against each
| other. I am not familiar with sudo's codebase, and so I
| can't speak to if I personally agree with Prossimo or you
| here.
|
| What I _will_ say is that I certainly agree that memory
| safety _on its own_ would be a weaker justification for the
| reasons you cite. But this analysis doesn 't take into
| account the relative usefulness of various language
| features for preventing logic errors. For example, I find
| that enums really help catch edge cases that are easy to
| forget about, causing bugs. Tagged unions are obviously a
| thing in C codebases but aren't as easy to use nor
| integrated into the language in useful ways, like
| exhaustiveness checking. You're absolutely right that, at
| the moment, the sudo codebase is more well understood, but
| one could make the argument that C's various weaknesses in
| areas like the typesystem means that as this codebase
| matures, and becomes well known itself, logic errors become
| more tractable.
|
| One could _also_ make an argument that a new codebase is a
| good idea, even disregarding the C vs Rust factors. For
| example, they 're not going for "100% drop-in replacement
| for sudo," they're going for "a drop in replacement for
| common cases." Sudo has users who I assume would be upset
| at removing features they rely on, whereas this project has
| no userbase, and therefore, can do whatever they'd like.
| Removing a bunch of code can also help reduce logic errors,
| as it's impossible to have logic errors in code that
| doesn't exist, obviously. Of course, this article focuses
| on the memory safety aspects and not the others, maybe
| that's a marketing mis-step. Then again, what's important
| here is the engineering, not the marketing.
|
| So yeah. It's not obviously a slam dunk either way, it
| really depends on how one personally weighs all sorts of
| factors. As I said above, time will tell.
| tptacek wrote:
| While I appreciate Rust's correctness features and dearly
| miss `match` statements, as a software security
| professional with (I think I can say) a lot of experience
| looking for the kinds of vulnerabilities we're talking
| about here: I do not buy this theory of Rust's security
| advantage, like, at all. People have been saying things
| like this about strongly typed languages of varying sorts
| (Haskell was once a favorite) for over a decade, and it
| hasn't panned out. I think you'll find, if you look at
| the last (say) 10 meaningful sudo vulnerabilities, that
| there isn't a clear story about how enums would have
| steered you away from the problem.
|
| Certainly, if there's an appetite for a reduced-fat
| version of sudo that caters to the 80-90% use case, I'm
| all for a Go, Rust, or whatever version of that thing.
| But then, C programmers were making the same argument 15
| years ago, and nobody was able to sell the reduced-fat
| sudo (or, for the matter, the reduced-fat ssh, which
| we're all still dealing with). If it works out, great.
|
| If it ends up gradually becoming a 1:1 equivalent to
| sudo, wartfeatures, and all, that's less great.
| steveklabnik wrote:
| > I do not buy this theory of Rust's security advantage,
| like, at all.
|
| Don't worry, you've made that overwhelmingly clear.
|
| (I also know that I am _not_ a security engineer, and
| respect your overall expertise here tremendously.)
|
| > that there isn't a clear story about how enums would
| have steered you away from the problem.
|
| Yeah man, I picked an example solely based on something
| that's done in both languages, but differently, because I
| thought it would be illustrative of the general idea. I
| am not claiming that enums will magically fix CVEs in
| sudo, that would be ridiculous. I'm saying "if we're
| saying memory safety is irrelevant, and logic errors are
| what matters, you should compare the tools that let you
| model your problem." Maybe Rust's features are truly
| irrelevant here, but as you say, I dearly miss match
| statements when I'm working in a language without them,
| so I suspect they do help in the general case of this
| argument, even if they don't for this one specific
| codebase.
|
| > People have been saying things like this about strongly
| typed languages of varying sorts (Haskell was once a
| favorite) for over a decade, and it hasn't panned out.
|
| I actually agree with this, but I don't think that the
| typesystem aspects are the cause here. Programming
| language adoption is weird, complex, organic, and really
| hard to see the future of. I think it's taken decades to
| "productize" more advanced type systems, and it's really
| only relatively recently (like, I'm not gonna try and pin
| down an exact moment, but like, let's say "the last ten
| years" but I suspect even that may not be far enough
| back) that we've seen larger adoption of this stuff. I
| don't even personally consider static typing to be
| strictly better than dynamic typing!
|
| Oh and, if we're gonna nitpick examples, Haskell was
| never going to be a language to do that, one that
| expressly doesn't try to pursue popularity and broad
| usage. Those people (and I remember them too) were wrong
| then, and wrong now. But that's not (only) the fault of
| the type system.
|
| That said, while I agree with the description of the
| history, I don't see how the trend points to this being
| impossible, but rather than we're now living in the time
| of truly being able to answer the question one way or the
| other. And the only way you do it is by putting in the
| work.
| tptacek wrote:
| I'm aware that there is more to Rust than enums, and that
| you were using that as an example of a correctness
| feature that is part of a gestalt of correctness
| features. My point is that people have been arguing that
| more expressive languages with stronger type systems will
| be better able to model problems and thus avoid logic
| vulnerabilities, and that hasn't panned out at all.
|
| Since I don't think there's any evidence to support your
| point that's a Google query away from you, I guess
| something you could present that would weaken my argument
| is an example of a recent meaningful sudo vulnerability
| where idiomatic Rust, written in the manner that a
| typical Rust programmer would use to solve the relevant
| problem, would have foreclosed on that vulnerability.
| Obviously: we pre-agree about memory corruption
| vulnerabilities here.
| steveklabnik wrote:
| To be honest, on these issues, I'm not invested in
| winning an argument about it. I can see good arguments
| for why this would be beneficial, and I think they make
| sense. But I also know there's good arguments for why
| this would _not_ be, and I can think they make sense too.
| I want to see both sides represented here, because I
| think it 's interesting, and seeing both sides is good.
| That's good enough for me.
|
| If in five years (or whatever) no distros use this new
| tool, it's had zero impact on things, I'll go "damn,
| tptacek is right," and that's an outcome I am totally
| fine with.
| phkahler wrote:
| >> it is a complex piece of software where logic errors can
| create serious security issues.
|
| I know many unix commands have a lot of capabilities I never
| use, sudo? Not much logic other than "run this as root if user
| has permission" is there? OTOH I never thought about how a cli
| app can escalate privilige without already having it....
| wongarsu wrote:
| The escalating privileges part is easy: the file
| /usr/bin/sudo is owned by root and has the setuid flag set,
| meaning it gets executed with the permissions of the file
| owner instead of those of the caller.
|
| The complexity has more to do with the fact that it has 28
| command line flags, plus a fairly complex config file to
| configure who is allowed to do what, impersonating which
| user, and whether they need a password to do so. All of that
| dealing with security critical stuff like what exactly should
| carry over and what should be reset (all configurable ofc).
|
| su is very simple by comparison (and you can do `sudo -s`
| anyways to get the same result as calling su without
| parameters).
| PeterWhittaker wrote:
| Good plan. Reimplementing in Rust using a carefully planned
| milestone-based approach should result in feature parity with
| fewer security vulnerabilities.
| temporarara wrote:
| There is zero guarantee about that. The result could have fewer
| vulnerabilities, but it's not an easy thing to do. I'd say
| there definitely are some vulnerabilities left in sudo code,
| but over the years all the obvious bugs have already been
| eliminated and rewriting it in a new language can reintroduce a
| lot of those. Now, if the people doing this are competent and
| have time and money in their hands, rust enables doing some
| things better and basically lets you forget about basic and
| advanced memory bugs, so the final product may well be a good
| (better) one.
|
| But just using another language to reimplement something in
| order to make it "safer" in some abstract manner does not
| guarantee anything. Good coding practices combined with
| "elementary" and highly-portable language like C can also
| result in victory that can't really be challenged. We'll see.
___________________________________________________________________
(page generated 2023-04-26 23:03 UTC)