Catch up on stories from the past week (and beyond) at the Slashdot story archive

 



Forgot your password?
typodupeerror
×
Security Linux

10-year-old Sudo Bug Lets Linux Users Gain Root-Level Access (zdnet.com) 166

A major vulnerability impacting a large chunk of the Linux ecosystem has been patched today in Sudo, an app that allows admins to delegate limited root access to other users. From a report: The vulnerability, which received a CVE identifier of CVE-2021-3156, but is more commonly known as "Baron Samedit," was discovered by security auditing firm Qualys two weeks ago and was patched earlier today with the release of Sudo v1.9.5p2. In a simple explanation provided by the Sudo team today, the Baron Samedit bug can be exploited by an attacker who has gained access to a low-privileged account to gain root access, even if the account isn't listed in /etc/sudoers -- a config file that controls which users are allowed access to su or sudo commands in the first place.
This discussion has been archived. No new comments can be posted.

10-year-old Sudo Bug Lets Linux Users Gain Root-Level Access

Comments Filter:
  • It’s yet another "null-terminated sting buffer bug".

    It's really time to put the idiotic null-terminated buffer paradigm behind the barn and shoot it in the head.

    It's no longer 1972 where memory is so expensive that you have to scratch everywhere to save memory as much as possible!

    What's wrong with strings (or buffers) with a separate length indicator?

    • Re: (Score:3, Insightful)

      Well, the alternative to it is the length in front (aka Pascal strings) paradigm. Have you played with that one to see just how badly can that suck?
      • by Rockoon ( 1252108 ) on Wednesday January 27, 2021 @03:10PM (#60997840)

        Well, the alternative to it is the length in front (aka Pascal strings) paradigm.

        ....or know the size of, and then correctly handle, the backing buffer.

        The problem with C "strings" is also a problem for all other C array allocations, that neither it nor the standard and practices evolved.

        I'm not talking about garbage collection here. I'm talking about maintaining simple knowledge such as the size of that array allocation. I'm not talking about a language-enforced overbearing protection of memory with guards around every memory access, but come on...

        The alternative as you call it, the length "in front" of the strings, is just a symptom fix. The problem is not knowing at all how big that memory block is after its allocated, which may at runtime eventually find itself to be larger OR smaller than what that string length field currently says.

        • by Uecker ( 1842596 )

          You can use VLAs and pointer to VLAs and then arrays have the size information in C. You can then compile in run-time bounds checking (-fsanitize=undefined). .

          int main()
          {
                  int n = 3;
                  int x[n];
                  x[n] = 1;
          }
          x.c:6:3: runtime error: index 3 out of bounds for type 'int [*]'

      • by lsllll ( 830002 )
        Why not multiple types? Just like integers do? stringtiny for 256 bytes, stringsmall for 65536, and stronglong for 2^32?
        • Because that wastes about half of your RAM in the case where you CORRECTLY guess the maximum length that a user will need in the future.

        • by spitzak ( 4019 )

          Bacause you would require N versions of every function and structure that took a string. That would be a nightmare to maintain.

      • It doesn't suck at all. It's objectively better. It doesn't prevent one from having 'NUL' bytes inside of a string. It doesn't make finding the length of a string a O(N) operation. It can be coupled with other useful mechanisms such as reference counting to improve performance even more. The only reason C uses null-terminated strings is because they are a good match for pointer arithmetics, which is another of C's foot-shooting misfeatures.
      • by Junta ( 36770 )

        Most people use that strategy unwittingly, as most string-like things in most interpretations. I don't know of a huge outcry of how badly it sucks?

        Contrast to having a sentinel value like '\x00' and it's more flexible, faster, and robust and is generally some implementation detail you don't have to think about.

        • faster

          Depends on the use case. Calculating string length? Nope. Copying strings? Nope. Equal-comparing strings? Nope. Concatenating strings? Nope. Basically anything that requires knowing the string length is slowed down by needing to call strlen(), unless you cart around the string length independently, which a lot of C APIs require, including the highly common ISO C and POSIX APIs and even Win32 APIs.

          Since you're carrying around the string length all the time anyway, it's faster and takes less space (even if

      • I have played around with it, and it doesn't suck.

        Got any actual arguments? Because right now, your lack of arguments is a good argument that you are wrong.

      • by gweihir ( 88907 )

        Well, the alternative to it is the length in front (aka Pascal strings) paradigm. Have you played with that one to see just how badly can that suck?

        I have. It is pretty broken as well. You would have to put in 64 bit length fields to make it work generally, but then small systems may get a space problem and an efficiency problem. In addition, in a language like C, it will not be secure. A string is just an array in C and it will be very easy to accidentally write to the length field.

        • That's why in C++, the std::string is a nested typedef, and can therefore be platform (and even library implementation) specific.
          • by gweihir ( 88907 )

            Forget C++. We are talking C here and for good reasons.

            Also, there are really only two options: Make sure the length field is long enough to never be exceeded (not possible, see small platforms and memory-load) or to deal with it in every case (not possible because it blows up the respective libraries and comes at a performance penalty, see small platforms or really any platform).
            In addition, any length field would need special protection (not possible in C).

            Face it: This problem has no good solution. If th

            • Forget C++. We are talking C here and for good reasons.

              sudo, an occasionally used system utility - what are the "good reasons"?

              Make sure the length field is long enough to never be exceeded (not possible, see small platforms and memory-load)

              Most C APIs that take an array argument also takes a length argument. If the implementation defined length is good enough for that system, then it's good enough. There's not problem with small platforms and memory load, because those platforms will have APIs that take the same field type.

              comes at a performance penalty, see small platforms or really any platform

              Calculating the string length all the time is a bigger performance penalty. You're ALREADY carting around the string length in a lot of code already. T

              • by gweihir ( 88907 )

                Forget C++. We are talking C here and for good reasons.

                sudo, an occasionally used system utility - what are the "good reasons"?

                Moving the goal-posts just says you have run out of arguments.

                • The article is about a bug found in sudo. How is mentioning sudo "moving the goalposts", you flaming retard?

                  Seems like this is your tactic to avoid the fact that I shot down your other arguments.
    • The problem is this software is rather old. Decades old, and were made during a time where RAM and CPU processing was expensive.
      But also languages like C which are really low level where you have more control on what is written and how, then you have SUDO which is designed to break security. Creates a high risk application.

      Oddly enough the C++ String options is a new feature in C, where people had to code for character pointers. And there is a lot of code written in that method.

      Your fix, may mess up some

      • Unix (Eunichs see above) was born of Multics, which somehow avoided these pitfalls.

        I do not see this as a generational error, but rather an intentional inclusion

        • This is a problem with Unix as well. As C/C++ managed strings the same way. You may have used a different language, COBOL, or FORTRAN which its compiler would deal with strings in a more robust way.

          • Multics was designed in Algol and written in PL/1, afaik

            There was some feature of PL/1 that precluded pointers, that may have been the heart of the matter

            The teacher had a funny way of approaching things. To teach about buffer overflow, he asked us to include laying a book on the keyboard as a test case.

            This was in the early 90's (can't remember the teacher's name, and he was retired at that time). I moved on to pl/sql (a descendant of ADA) in the late nineties and have never looked back

    • true enough, but I have to wonder why people still install fingerd, which has the same exploit and provides zero value

    • I know that the article specifically says that ASLR was defeated, but I wonder if these other compiler/linker mitigations prevent (some of) these vulnerabilities (specifically fortify)?

      The "hardening-check" perl script is available from EPEL on redhat platforms. Here I use it to report mitigations in an old FWTK component that I use for an internal legacy system.

      $ hardening-check /home/fwjail/usr/local/etc/ftp-gw
      /home/fwjail/usr/local/etc/ftp-gw:
      Position Independent Executable: yes
      Stack protected: yes

    • Um, I work on systems where memory is tight and you can't just bloat things up by hiring the cheapest developers. I've worked on things with 384 bytes, 256 bytes, 20K bytes, 1M bytes, etc.

      Buffers with a length indicator have their own sets of problems and security bugs just as bad as null terminated string does. Nothing fixes the problem except to spend money to examine code carefully by developers trained in how their system, language, and libraries work.

    • What's wrong with strings (or buffers) with a separate length indicator?

      The problem is typically less about memory consumption, and more about computational efficiency. The bounds checking and updating isn't free, and if you're doing a massive amount of string work, that can add up quickly.

      Of course, programs that need that kind of string efficiency are the exception, and not the rule -- so in general I agree (as do most modern languages, which do have bounds-checked strings). But you're going to have a really hard time converting billions of lines of legacy C code to use a n

      • by Uecker ( 1842596 )

        I think a good first step is to audit security critical software. This seem what happened here.

        Then one could rewrite security critical code to use safe string libraries which should be far less work than rewriting everything in a different language.

    • by godrik ( 1287354 ) on Wednesday January 27, 2021 @04:40PM (#60998368)

      Fundamentally sudo is a rare operation. There is no reason to implement this in C. Let's implement that in a language with proper memory safety. Or at least in C++.

      I am usually not one to call to rewrite operating systems in languages like go and rust. The overhead can kill you. But how often is sudo used? Very rarely, if you call sudo all the time, there is something fundamentally wrong in your infrastructure. Since it is not called often, it is not time-critical. So let's write it safely.

      If it were the IP stack, I'd be a bit more concern in rewriting it in a possibly slower language because it is on the critical path of many things. But sudo, not time-critical; we should probably rewrite it.

    • by tlhIngan ( 30335 )

      Itâ(TM)s yet another "null-terminated sting buffer bug".

      It's really time to put the idiotic null-terminated buffer paradigm behind the barn and shoot it in the head.

      It's no longer 1972 where memory is so expensive that you have to scratch everywhere to save memory as much as possible!

      What's wrong with strings (or buffers) with a separate length indicator?

      Back in 1972, a null terminator or a string length indicator took the same amount of memory. Strings would be limited to whatever the smallest word le

      • by tlhIngan ( 30335 )

        array[x] == *(array + x) == (x + array) == x[array]

        Grr. I meant

        array[x] == *(array + x) == *(x + array) == x[array]

    • by gweihir ( 88907 )

      Buffers with length indicators are not inherently more secure in a language like C. The real problem is careless coding and coders that over-estimate their skills and hence are not careful enough.

      On the plus-side, "sudo" is basically a finished product and eventually, it will be bug-free. Unless the systemd-morons decide to re-implement this one, badly, as well.

  • The FUCK (Score:3, Insightful)

    by Forty Two Tenfold ( 1134125 ) on Wednesday January 27, 2021 @02:31PM (#60997616)
    How the FUCK was that possible, multiple eyes?
    • Re:The FUCK (Score:4, Informative)

      by phantomfive ( 622387 ) on Wednesday January 27, 2021 @02:37PM (#60997650) Journal

      Privilege escalation bugs are common in all operating systems. The paradigm of "we want to let you do everything but not really everything" is a hard one to implement in a secure way.

      Remote exploits are easier to defend against.

    • Well, one reason could be that people who take security seriously were already omitting sudo from their installs. The fact of the matter is that it's by it's very nature a giant hole drilled right through your system security barriers, even on a good day.

    • Comment removed based on user account deletion
      • by shanen ( 462549 )

        Concurrence except for "only". Some of the eyes are attackers who don't want to modify the code but seek to find exploitable weaknesses like this one. Perverse incentives strike again.

        What always scares me about deep-bug stories like this one is that we'll probably never know when it was first discovered. We only get the bad news early in the cases where the first bad guys were clumsy and got caught.

    • by couchslug ( 175151 ) on Wednesday January 27, 2021 @02:46PM (#60997712)

      Multiple eyes doesn't mean anyone can be arsed to do the chore of fixing what the eyes find.

    • Well, clearly you missed it when you were auditing the code, so don't get mad at everybody else missing it, either.
    • Re:The FUCK (Score:4, Interesting)

      by Dutch Gun ( 899105 ) on Wednesday January 27, 2021 @03:00PM (#60997814)

      Answer: C.

      How are people still surprised by this? It's a classic buffer overflow. C is insanely dangerous, and entire OSes are written in it. Any tiny mistake can mean a major memory-related security issue. There are likely dozens, even hundreds of equally serious bugs in any given major OS that simply haven't been noticed yet.

      Unfortunately, there isn't really a good solution for this. It's not exactly practical to replace a million lines of C code with Rust or whatever. C++ is a bit more compatible, but still isn't memory-safe (even if better than C), and Linus hates C++ besides. It's been decades and apparently tools still don't exist to catch stuff like this, or at least, not ones the Linux team are using. We'll likely hear from the "git gud" brigade, telling us that we just need perfect programmers who never make mistakes, but that's pure fantasy.

      Obviously, memory safety alone won't fix all bugs. But it absolutely would have prevented this one. Both Google and Microsoft have performed audits on their own code that indicate over two-thirds of security issues are memory-safety bugs. I'd love for someone to perform a similar audit on Linux-related CVEs, as I bet we'd see roughly the same proportion.

      • Watching the arc of Java was pretty discouraging as to fixing the situation with typesafe runtimes. (Even if it could be used for system-level programming). As a developer I did find it much easier to avoid and diagnose problems in Java, but there were still enough critical bugs in the runtime(s) that the reputation of Java was shot and it fell out of use for untrusted code. And that was that.
    • by gweihir ( 88907 )

      a) It got found, even if late
      b) Closed-source will be much worse

    • If you haven't noticed, they found it.
  • doas (Score:5, Informative)

    by computer_tot ( 5285731 ) on Wednesday January 27, 2021 @03:08PM (#60997836)
    This is why my servers run doas instead of sudo. There have been a few series sudo bugs in the past year or so and it's nice not needing to worry about them.
    • Still waiting for persistence outside of OpenBSD but yeah doas is a solid alternative.

      • by jmccue ( 834797 )
        I think if POSIX would take some string handling functions from OpenBSD and make official, and people use then, it could avoid many of these issue. For example strlcpy(3)
    • This is why my servers run doas instead of sudo.

      Pfft amateur. Real men just log in as root and don't ask the system to pretend to be someone else. Sure there's the issue that when you create files your daemons can't read them, but the solution there is to simply run all those critical services as root too.

      Some people say it's a security risk, but my servers are running great. Even my ISP sends me daily congratulatory emails about how much traffic my mail server is handling. Though for some reason they are threatening to cut me off. They must be jealous.

  • by benjymouse ( 756774 ) on Wednesday January 27, 2021 @05:01PM (#60998478)

    sudo is just another example of the giant (intentional) hole in the security barrier that is setuid root.

    Just because of poor delegation design to start with, the setuid bit was invented instead of changing the design to a proper fine-grained access control. Instead of having proper access control lists for all resources like e.g. printers or privileges to set the system time or time zone, Dennis Richie though that setuid was such a neat idea the he went and patented it.

    setuid root elevates the process itself to the all-powerful root account as the effective user. This means that all existing access control is moot. An audit of the access control setup can never reliably list what a user is allowed to do on a system. The existence of just a single setuid root tool means that you will need to know what that tool can do intentionally or unintentionally because of a bug as in this case.

    a setuid "service" is not a real service with a limited and discoverable surface which can be independently secured, like e.g. a proper daemon with which you communicate through interprocess means. It is a process of which a would-be attacker has tremendous control the environment and parameters. To know what a setuid tool can do you need to read the source code and be able to verify that the tool is indeed the correct manifestation of the source code.

  • Automated "fuzzers" and static analyzers do help up to a point. However when C is used as a "slightly higher level assembly language", and most programs have micro-optimizations they can help so far. Basically you either get too many false positive warnings, or don't get enough at all.

    We are lucky this bug was fixed. But you can be sure many others are lurking in unsuspecting tools.

    That is why for example, we abandoned OpenSSL and replaced with LibreSSL, which heavily drops unused parts to reduce potential

    • However when C is used as a "slightly higher level assembly language"

      Its neither that nor the opposite problem ("slightly lower level high level language.")

      C is, was, and always will be a high level language. In spite of the fact that it is a high level language.

      C has pointers. Pointers dont make it low level language (even BASIC can peek and poke!), but they do introduce issues when they are used. It is specifically that neither the language proper nor the standards and practices of its practitioners have evolved to aid in those issues.

      There are different ways to hel

      • by stikves ( 127823 )

        C's history is based in B (which was based on another language called BCPL), and B was designed to be a machine independent system language.

        https://en.wikipedia.org/wiki/... [wikipedia.org]

        It did not have types, and everything was a system "word" (auto). You could multiply or dereference the same variable. If you look at the examples, some of them are still valid K&R style C programs.

        Over time C became higher level (dynamic arrays, and whatnot). However the low level roots are still there.

  • If you got user access, you already got everything you need.

    And when was the last time you were logged in on a shell as a user on a multi-user server? They all give you some kind of virtualized encapsulated container.

    I mean we're not using mainframes with terminals anymore. (Or the webCancer variant.)
    No matter how much the Silicon Valley mafia wants that again.

    • BAReFO0t, please get professional help. Both for your mental condition and for someone to apply updates on the server you just announced to the world you're neglecting.

  • There are a number of reason this is done in C this way. One is to keep the run-time system small. Another one is to be space-efficient. Another one is to not impose arbitrary length restrictions. Another one is that an explicit length field would be overwritten just as easily. I am sure there are more.

    If there were a really superior solution, it would have been moved into the C standard library a long time ago. There is not. The only thing that helps is careful coding.

  • For the people who complain a 64-bit string length field is not portable.
  • If this was written in Pascal, it wouldn't have had this exact bug, it would have been a different bug.

    Too bad Pascal was considered a toy "teaching language" and we went with a high-level wrapper around a rather clunky assembly-language variant. (I'm a C programmer and have been doing almost 100% C for the past 30 years)

    We could write something like sudo in Rust or Go pretty easily. Of course we'd have to update the program every time the language changes too much. But probably a small price to pay in a fa

  • I guess at least we can remove sudo if we don't use it, rather than being a built-in part of a more monolithic OS. That's what I've just done to my production servers.

    Maybe it shouldn't come as standard for any server oriented distro through, is there even any advantage to using sudo over adding users to the root group in server use cases?

"Look! There! Evil!.. pure and simple, total evil from the Eighth Dimension!" -- Buckaroo Banzai

Working...