Hacker News new | past | comments | ask | show | jobs | submit login
Mac OS X Sudo Password Bypass (packetstormsecurity.com)
159 points by llambda on Aug 30, 2013 | hide | past | web | favorite | 51 comments

This is quite a common way to bypass sudo (get access to a user who already logged in as sudo and reset clock), I remember seeing the same exploit (or variations) time and time again, for multiple systems.

I'm very surprised that the 'sudo' timeout feature wasn't implemented against the system's RTC using something like CLOCK_MONOTONIC. Or put differently, the idea that you'd use absolute time to implement a requirement that's defined in terms of relative time seems a bit absurd. Anyone have any clues as to why this wasn't implemented that way?

For reference, CLOCK_MONOTONIC is defined in time.h and is part of the POSIX standard.

From the 2004 version of 1003.1:

    The identifier for the system-wide monotonic clock, which is defined
    as a clock whose value cannot be set via clock_settime() and which
    cannot have backward clock jumps. The maximum possible clock jump
    shall be implementation-defined.

Edit: This is also an excellent example of why "nullability" is a really, really important concept. If the choice was to delete the timestamp file rather than set it to a magic number which is also an allowed value, this issue could be avoided by simply treating "missing timestamp file" as a timestamp value of -inf.

Edit 2: Just doing a bit more reading on this... on many platforms CLOCK_MONOTONIC resets on reboot, so that's no bueno unless combined with a surefire reboot detection method (if you know of one, go answer my StackOverflow question here [1]). You'll also want to fail the check if the time value read is less than the one stored (indicates overflow or other tampering, and overflows should be far enough apart that this will never happen). It's also subject to NTP time slewing [2] which could be another attack vector. Some systems have support for a CLOCK_MONOTONIC_RAW which is not subject to slewing, however I don't believe this is part of the POSIX standard, and if you were to use this there's a decent chance it wouldn't be very accurate on systems with cheap/noisy/otherwise-inaccurate RTCs.

1: http://stackoverflow.com/q/18539724/203705

2: http://www.ntp.org/ntpfaq/NTP-s-algo.htm#Q-CLOCK-DISCIPLINE

CLOCK_MONOTONIC is not available on OS X. Also, isn't CLOCK_MONOTONIC_RAW fetching the counter from rdtsc instruction on x86? (And therefore can go backwards in time if your process is migrated to another CPU).

Keep in mind, also, that the CLOCK_MONOTONIC is not part of the core POSIX standard, so OS X is technically "compliant" even though they didn't implement it. Add this to a list of annoyances, such as no pthread_cond_timed_wait().

You can, however, get a monotonic clock by getting access to the clock service on mach.


In a David Tennant voice: Wait, what?? What?!

  ~$ grep CLOCK_MONOTONIC /usr/include -rn
Ahh, it's in the POSIX realtime extension... Dammit.

Apparently [1] one solution would be to #IFDEF DARWIN the following, as on Darwin SYSTEM_CLOCK is supposed to be a monotonic boot clock.

  #include <mach/clock.h>
  #include <mach/mach.h>
  clock_serv_t cclock;
  mach_timespec_t mts;

  host_get_clock_service(mach_host_self(), SYSTEM_CLOCK,
  clock_get_time(cclock, &mts);
  mach_port_deallocate(mach_task_self(), cclock); 
Not sure if processor affinity would affect that code (don't have time right now to do the in depth reading on it), but you could always set affinity to CPU0. Though then you'd have to make sure to run the sudo'd command as a child process and appropriately reset affinity to default before a call to exec...

On OS X, use mach_absolute_time() to get a monotonic clock. A lot of APIs in OS X use the monotonic clock, e.g. CoreAnimation wraps mach_absolute_time() as CACurrentMediaTime() and uses that to calculate animation start times and delays.

pthread_cond_timedwait has existed on OS X since Tiger. Look in /usr/include/pthread.h.

"If [...], it is possible to become the super user by running `sudo -k` and then resetting the system clock to 01-01-1970"

Can users reset the Mac OS X system clock without being an admin?

You need to be an administrator, but you do not need to be root. This exploit lets you start from an administrator account for which you don't have a password (but have gained access to through other means, like exploiting an app run by an administrator user) and then leverage that into root access, something that normally requires the password for the account.

You can actually prevent the exploit from working by locking the "date and time" tab of the system preferences. The exploit will then cause the usual password popup to appear. (On 10.6 at least.)

sudo offers updated binaries for OS X 10.5 and up so you don't have to wait for Apple: http://www.sudo.ws/sudo/download.html#binary

If you don't trust the binaries, I found it easy to update the vulnerable sudo v1.7.0 on my OS X 10.6 machine by building from source and overwriting the one supplied by Apple:

0) Backup /usr/bin/sudo (temporarily; you'll want to delete the old sudo after verifying the new one works), and backup /etc/sudoers just to be safe

1) Download the source for sudo v1.7.10p7 linked on sudo's homepage: http://www.sudo.ws

2) Untar, ungzip, go to resulting source directory

3) Run configure, telling it to overwrite the vulnerable sudo

    configure --prefix=/usr/bin
4) Compile

5) Install

    sudo make install
6) Delete the old sudo you backed up in (0)

See also the sudo installation notes here: http://www.sudo.ws/sudo/install.html

If you use `configure --prefix=/usr/bin`, you'll end up with sudo installed in /usr/bin/bin/sudo. Instead, try

   ./configure --prefix=/usr
to use the /usr hierarchy (/usr/bin, /usr/sbin, /usr/share, etc...) instead of the /usr/local hierarchy.

Also, if you're able to run an executable in the current directory without specifying its location, as in configure instead of ./configure, then you have . (pwd) in your $PATH, which isn't recommended because a malicious executable might be in the directory you're in, and it might be named something like ls. Just listing the directory could have you owned.

You're absolutely right on all counts. You caught me writing that sloppily from memory. Thank you for the corrections!

Here's a workaround until Apple updates sudo, add the following to you /etc/sudoers file:

  Defaults timestamp_timeout=0

The user has to be an admin and have executed sudo previously for this to work. I hope that anybody who's smart enough to have access to this command (and admin membership) is equally qualified to parse scripts that may exploit this vulnerability...

Not at all a safe assumption. Most importantly, it's not that uncommon for even less experienced Mac users to copy and paste Terminal commands to solve one problem or another. A lot of those "Just type this!" solutions I've seen involve sudo somewhere.

But on top of that, maybe I don't understand your meaning here, but do you do a security audit on every line of every script that you ever run? Especially scripts that you run without sudo? I know that I don't.

"A lot of those "Just type this!" solutions I've seen involve sudo somewhere."

Not sure if you're alluding to this trick: http://thejh.net/misc/website-terminal-copy-paste

This particular exploit could be rather nasty when used in conjunction with the above.

Not even that. Lots of Mac help sites will include snippets of Bash code for the user to enter (say, something using rm to delete files the Finder is having trouble statting), and people will just enter those. You don't even need to do anything sneaky with the copy/paste process. Just offer some malicious code and expect the user to run it blindly since they wouldn't be coming to MacNoobHelp.com if they were capable of vetting for exploits.

Particularly installer scripts that are run by the trendy technique of

  curl -L http://www.example.com/some/cool/thing/install.sh | bash
Particularly risky if the protocol is not https. Even worse when the right-hand command is "sudo bash"

A few points:

- The default user created at setup of OSX is in the admin group.

- Certainly the 'has run sudo' is a bit of a restriction, but even running something like the Homebrew install script runs sudo. (Maybe 'users that run Homebrew without understanding sudo' is an even smaller restriction, but a few members of my research group live in exactly this intersection!)

- Do you habitually read every line of source code your computer would execute before you run that code?

I was unaware of being placed in the admin group by default. Is the admin group similar to the wheel group or is there also a wheel group for sudo access?

And yes, I very seldom run scripts copied from somebody else so when I do, I make sure I know what is being run. Granted, I'm a Linux and Windows user so the OSX philosophy might be different.

The admin group is what it's used for sudo by default.

You mean installing Homebrew itself? Because if you're running "sudo brew install foo" you're doing it wrong.

Yes. And nope, I'm not referring to 'sudo brew install'.

The main homebrew page says, 'run this ruby script'.

The ruby script is available at: https://raw.github.com/mxcl/homebrew/go

The script includes a sudo command.

To be fair, I hadn't read the script in detail when I wrote my post, just far enough to see there was a definition of a sudo function. On review, it looks like they either call it to chmod/chgrp HOMEBREW_PREFIX (sometimes), or run sudo to create the directories.

Fair enough. I think everyone agrees that the "download and execute a random gist" method of installation is not great.

I don't see any reason why it's worse than running a binary installer, and people seem to object to that a lot less for some reason.

Homebrew fails if you attempt to run it with sudo.

See my comment above. I'm not referring to running 'sudo homebrew ...', I'm talking about the installation, which has to run sudo to change some permissions in HOMEBREW_PREFIX.

Root can do anything. If that's a vulnerability than the entire system is a vulnerability.

Appears to be fixed in 10.8.5, the MSF posted doesn't work under 10.8.4 for me either.

Can someone explain why resetting the clock will give sudo access without requesting a password?

When you run sudo, a timestamp file is generated that sudo will then check on subsequent runs of the command allowing the user to continue to run privileged commands without having to type their password every time for a given amount of time (typically 5 minutes). Running `sudo -K` removes the timestamp file to force the user to re-enter their password on the next run of the command, but starting with version 1.6, `sudo -k`, which was an alias for `sudo -K` (I think), was changed to reset the timestamp file to the epoch (January 1st, 1970, 01:00).

This vulnerability allows a user that already has sudo ability to infinitely allow themselves the ability to run any command they already have privilege to run under the given system's sudo configuration without a password forever, because resetting the system clock to the epoch tricks sudo into thinking that sudo has just always been authenticated to run without a password.

This vulnerability does not allow users that already do not have any sudo privileges to obtain them, nor does it allow any users with sudo privileges the ability to run any command with sudo if they are restricted to certain commands.

This is a very old bug on UNIX-like systems. - I'm surprised it's still around on OS X (and surprised that this is news).

IIRC, it's because sudo -k checks whether the current time > time_at_which_you_entered_password + ttl[0]

By resetting this clock, you make the current time before this cutoff, therefore fooling the computer into thinking you don't need to enter a password.

[0] ie, how long it takes for your password to "expire" before requiring you to enter it again.

Does anyone know how they fixed this in sudo? I would be interested in knowing how they do a TTL without using the system time for comparison.

How much sense would it make to annotate a variable as being representative of a "present time" and then have the compiler insert a check that the variable must be greater than the time at which the file was compiled (plus or minus some fuzz to account for daylight savings and time zones)?

Repeat after me "timestamps should always be UTC. Time zones and DST should be left to the display layer".

In any case, as a security measure, preventing the clock from being set before the compile time is a bandaid for a bullet hole.

It would be a bandaid that could be circumvented by the same exploit using not 1970-01-01 but the date of latest OS/binary update release - that date would be >= compilation date, and <= today, so would work.

Setting the system clock in Mac OS X doesn't require root privileges?

Does anyone else here us EE mobile? When I try to access this story it says it's 'only suitable for over 18s'. Is there something dodgy in the comments?

No security that needs time should be based on an insecure clock. Is there any kind of network "verified time" facility using PKC?

You'd need interactive signatures to prevent replays of very old timestamps, which significantly hurts scalability of the signed timestamps. However, I suppose with a weaker trust model one could have a federated signed timestamp service, where you could get timestamps over TLS/SSL.

Well... this is dangerous...

Why not add:

sudo -K

to .bash_logout

1. Because that doesn't fix the vulnerability, only narrows the window in which the exploit works.

2. Because it breaks the "ttl" feature of sudo for people who log in and out frequently (e.g., create and destroy terminal windows).

3. Because .bash_logout is only executed when a login shell exits.

Perhaps a similar but more elaborate solution could work to better mitigate this, though.

This is probably good enough for most purposes if the user is somewhat informed.

Always use a new shell for sudo. Always exit that shell when done.

Unable to access this url from UAE :-(

Also unable to access it from a Virgin train in the UK: 'restricted' because the site is considered 'malicious or inappropriate'.

Can't help wondering if this is how things will be under the upcoming UK Internet 'safety' measures (assuming Cameron survives that long.)

This non-bug was discussed last year.

Are you sure about "last year"? I thought the bug was assigned CVE-2013-1775 and discussed in late Feb 2013.

"Last Year", in internet time maybe. Here's the original CVE:


Ha, so this is expected behavior?

doesn't work on 10.8.4 for me

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact