Any existing but disabled account (an account with no shadow hash) will be upgraded to an account with a shadowhash. Normally this is fine, because it is an in-memory upgrade that allows the authentication code to run.
And then, because of a brain-dead if check, whatever password the user attempted to use is saved as the shadowhash for that account, permanently enabling the account with the password that was being tried. In this case, that means a blank password.
This allows a subsequent authentication with that same password to succeed. This accounts for the initial need to repeat the login multiple times.
I don't think it is intended to be an in-memory upgrade but rather move the hash on disk into shadow with a new hash method. The only way to change the hash method is to create a new hash from the provided password after verifying that it matches the previous hash.
The if statement seems designed to make sure that the password matches the currently stored password before doing anything, so the question is why does it not do that. Either the function returns that it does match for some reason or the return value is tested incorrectly. Currently the article doesn't say but maybe at some point the author will track that down :).
Then the question is why it happened, which would be easier to speculate on knowing what precisely is wrong.
Not behind a Mac at the moment, but I wonder if this means you can also enable a set of other standard disabled Unix accounts on a Mac?
That will worsen the impact even more, I'd say. Being able to enable disabled accounts my (locally or remotely) authenticating to a Mac system is very bad, even if those accounts are not root.
I pulled the list from /etc/passwd and have tried a bunch, but none worked. The root trick worked on this machine, so I know it's vulnerable. I have not tried them all.
The vast majority of those usernames start with an underscore. Not sure if that matters. The trick didn't work for "daemon" and "nobody" either, though.
I think there has to be some special weirdness about how root is disabled on Macs. It's the only account with its own "Enable.." line in the Directory Utility menu, for example.
So at first blush this seems limited to root, but I'm not going to hold myself out as a macOS expert. Just someone with a Mac I don't mind trying to bork.
Yes, the exploit works (or worked, now that the patch is out) against any passwordless system account. You won’t get the same feedback as it won’t unlock the prefpane, but they will have the password set, allowing you to change the shell and log in.
I haven't read through all 1000 comments on the other thread, so apologies if it's been covered somewhere else, but... Does anyone know if this can be exploited programmatically to bypass the need for 'sudo'. For example, could malware use this to elevate itself to root once it's running as a low-privileged user on the system?
From the comments on that, it seems like you need to do the exploit in the UI first. According the the analysis of the bug, "Upon receiving a mach XPC message, opendirectoryd invokes..." but what happens on the client end of the XPC message isn't mentioned. I'm just wondering if a low privileged user can initiate that programmatically, and whether they could do it from code that doesn't need to be signed, like a shell script.
I would think Apple would have released an update by now... but nothing yet. Can tell us something about the complexity of the code they need to change. Anybody an idea about how quickly they could release security updates?
I know this is super-urgent to fix, but they've got to make sure the fix doesn't cause other problems. You can't do that in 20 hours. And how long did it take to go up the chain?
Imagine the even bigger fallout if the fix accidentally ended up locking everyone out of the machines, essentially losing all data on anyone with an encrypted drive.
After reading this description of the problem and other users' comments about insufficient testing and how hard it would be to discover this particular case, I must say I'm baffled.
As the blog post shows, the account creation is done on the first click, not the second. The second just logs you in.
A trivial test in this case would have been, try to log in with a non-existing account (or an account with the wrong password) and make sure no state has changed afterwards. No new users, no changed passwords, everything as it was. Unit testing 101.
Using a sane set of enums is just a bit more typing yet so much clearer in intent. Even if it's just Success or Failure instead of a bool or int. Still not bullet proof but seeing `return Success` where it fails and checking for `if (bla == Success)` makes it a lot easier to find the problems.
Nice play-by-play analysis of the problem; thanks! Apple's authentication is not simple nor clearly documented (at least not where I could easily find it), I learned a lot following along.
If we're to expect everybody to test the reflow of text on mobile devices, why can't we expect mobile users to put in a little elbow grease themselves when reading on a comically tiny device?
This is the remnant of a previous OSX feature, that is you could go into single user mode, type passwd root, then create a password, then login with root / password. I guess there's a lesson here about complexity.
The article doesn't seem to say that according to my reading. The article says it is about verifying the legacy password when upgrading to a new-format password hash.
I should note that single user mode / passwd root thing has been around for quite some time, so remember kids, the only security is physical security...
It is expected behaviour that on unix-like systems booting in single user mode leaves you with /bin/sh as init or something very much alike, and, obviously, being root. This is no different than booting a live{cd,usb} and at that point you're a mount/chroot/passwd away from resetting the password. Unless the disk is encrypted of course.
Any existing but disabled account (an account with no shadow hash) will be upgraded to an account with a shadowhash. Normally this is fine, because it is an in-memory upgrade that allows the authentication code to run.
And then, because of a brain-dead if check, whatever password the user attempted to use is saved as the shadowhash for that account, permanently enabling the account with the password that was being tried. In this case, that means a blank password.
This allows a subsequent authentication with that same password to succeed. This accounts for the initial need to repeat the login multiple times.