2

I'm trying to remove all default user passwords across a bunch of servers with ansible. Firstly, I'd like to output the name of every user whose current password is foobar. How can I achieve this?

My first intent was to get the hash from /etc/shadow and grep for it, but this won't work because of salting.

Do I need to calculate my own hashes for this and compare them? Or is there a faster and easier approach?

1
  • 1
    The reason why password hashes are saluted is to prevent this exact search. This is supposed to be difficult. Any solution will require re-hashing guesses (like foobar) for every users. Jun 3, 2019 at 10:59

4 Answers 4

5

There's a specialized tool for password weakness check: John the Ripper available and probably packaged in all common Unix & Linux flavours.

Here's an example of usage on Debian GNU/Linux 9 (unshadow comes along john). Some care should be taken when manipulating password files, this is just a PoC. Note that the john command could be run remotely (and thus not installed anywhere else than a dedicated system) as long as it's provided suitable password files.

Setup (including setting password foobar to account test):

# echo test:foobar | chpasswd
# grep ^test: /etc/shadow
test:$6$84SIejUB$qM5UulJEIiwjOc4PWXYupWoyU/jMP0rKA8cM1g8CEOgxMlC.x4ndbbdRq438rjKb.6UwCoTqzvgxoi0h51Kpm1:18050:0:99999:7:::
# unshadow /etc/passwd /etc/shadow > /root/workpasswd
# echo foobar > /tmp/wordlist

Test for forbidden/default passwords:

# john -wordlist:/tmp/wordlist /root/workpasswd
Created directory: /root/.john
Loaded 3 password hashes with 3 different salts (crypt, generic crypt(3) [?/64])
Press 'q' or Ctrl-C to abort, almost any other key for status
foobar           (test)
1g 0:00:00:00 100% 5.882g/s 5.882p/s 17.64c/s 17.64C/s foobar
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Result:

# john -show /root/workpasswd 
test:foobar:1001:1001:,,,:/home/test:/bin/bash

1 password hash cracked, 2 left

Cleanup:

# rm -r /root/workpasswd /root/.john /tmp/wordlist
3

Can you try logging in as each user? e.g.

echo "foobar" | su username

You would need to temporarily disable the TTY check.

2

So here is a little C snippet that checks for the existing users password:

Save the following snippet in a file called: checkpass.c

#include <pwd.h>
#include <shadow.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <crypt.h>

static int pwcheck (char *user, char *passwd)
{
    struct passwd *pw;
    struct spwd *spwd;
    char *epasswd, *cpasswd;
    char *tty;

    if ((pw = getpwnam(user)) == NULL) {
        return 1;
    }
     /*
     * XXX If no passwd, let them login without one.
     */
    if (pw->pw_passwd[0] == '\0') {
        return 0;
    }
    spwd = getspnam(user);
    cpasswd = (spwd ? spwd->sp_pwdp : pw->pw_passwd);

    epasswd = crypt(passwd, cpasswd);
    if (epasswd == NULL) {
        return 2;
    }
    if (strcmp (epasswd, cpasswd)) {
        return 1;
    }

    return 0;
}

int main (int argc, char *argv[])
{
    if (argc < 3) return 4;
    return pwcheck (argv[1], argv[2]);
}

Compile the above code using:

gcc -o checkpass checkpass.c -lcrypt

Now from the command line just run the following:

while IFS=: read -r user _; do
  if ./checkpass "$user" foobar; then
    printf 'The ollowing user %s has the password set to foobar\n' "$user";
  fi;
done </etc/passwd

It's maybe a long shot but should work!

1

Because I'm not a fan of installing extra software and don't want to mess around with sudoers, what I ended up doing was

sshpass -p foobar ssh -o PreferredAuthentications=keyboard-interactive,password -o PubkeyAuthentication=no user@host

and afterwards check the exit code in Ansible. If the password was correct the exit code will be 0, otherwise 5.

This will obviously only work if password authentication is allowed in your SSH server config.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .