mkpasswd -m sha-512 produces incorrect login

5,331

Solution 1

Okay, I locked down the issue. Since the output of mkpassword will result in $id$salt$hash, when you copy and paste this into a useradd command, bash will try and do variable replacement on the $. As such, those need to be escaped using \$id\$salt\$hash so that bash will not do variable replacement before adding the string to /etc/shadow.

mkpasswd -m sha-512 "my password" results in

$6$5AfGzrQ9u$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1

which can be copied and pasted into useradd making sure to replace each $ with \$.

useradd -m -s /bin/bash -p \$6\$5AfGzrQ9u\$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1

Solution 2

Why does this happen ?

The reason why it fails is because items with leading $ are treated as variable and are unquoted when you pass it to useradd.

The $6...,$1..., and $b... portions from your hash are treated as variable. Of course, the fault is with the shell - shells perform variable expansion (unless they're single-quoted ) before anything runs. And because those 3 variables don't exist in your environment they disappear from the string you pass to useradd.

Practical example:

Let's see what actual command runs after the shell finished performing all necessary expansions and substitutions and passed that to execve() system call. Compare:

$ strace -e execve useradd -p $abra$cadabra newuser                                                                                                                    
execve("/usr/sbin/useradd", ["useradd", "-p", "newuser"], [/* 82 vars */]) = 0

$ strace -e trace=execve useradd -p '$abra$cadabra' newuser                                                                                                            
execve("/usr/sbin/useradd", ["useradd", "-p", "$abra$cadabra", "newuser"], [/* 82 vars */]) = 0

In the first example $abra$cadabra ( which is where your hash would go) disappears from the command that actually gets to run by the system. In contrast, the single quoted $abra$cadabra in the second example appears on the list of arguments that do get passed to execve().

In other words, you generated correct hash, but shell passes completely different thing to useradd as argument, which ultimately is the command that system runs. In fact, let's just take your hash for instance and compare two cases of quoting and non-quoting:

$ strace -e execve echo $6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g                                                            
execve("/bin/echo", ["echo", "FuuSdKgVke.LYTfrlknm5cWx65g"], [/* 82 vars */]) = 0
FuuSdKgVke.LYTfrlknm5cWx65g
+++ exited with 0 +++

Notice that what system actually sees after the shell is done processing the variables is FuuSdKgVke.LYTfrlknm5cWx65g. But it will see the correct hash if you quote it:

$ strace -e execve echo '$6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g'                                                          
execve("/bin/echo", ["echo", "$6$1FuuSdKgVke$bc8doOVGZhzomoeaf"...], [/* 82 vars */]) = 0

What can be done ? What works ?

However, subshell works because there is no replacement occurring - there's no variables. And quoting also works for the same reason.

Here are a few methods:

  1. Command substitution:

    $ sudo -p ">" useradd -m -s /bin/bash -p $(mkpasswd --hash=SHA-512 "123" ) newusr        
    >
    $ su newusr
    Password: 
    newusr@ubuntu1604:/home/admin$ 
    
  2. Single-quoting(note that I've trimmed actual hash because it's too long and doesn't fit into formatting):

    $ sudo -p ">" mkpasswd --hash=SHA-512 "112"
    >
    GVhvDY$vhw89D2X0bd2REQWE
    $ sudo -p ">" useradd -m -s /bin/sh -p 'GVhvDY$vhw89D2X0bd2REQWE' newusr2
    > 
    $ su newusr2
    Password: 
    $ echo $USER
    newusr2
    
  3. Take output from mkpasswd's stdout stream and pass it via xargs with -I flag:

    $ mkpasswd -m sha-512 'password1' | sudo -p '>' xargs -I % useradd -p % newuser1 
    
  4. Append \ to every $ (which OP figured out themselves in their answer). Scriptable, too, as per George's comment.

    $ useradd -m -s /bin/bash -p \$6\$5AfGzrQ9u\$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1 newuser
    
Share:
5,331

Related videos on Youtube

Neurax
Author by

Neurax

Updated on September 18, 2022

Comments

  • Neurax
    Neurax over 1 year

    I'm running into trouble trying to set passwords for my new users.

    I found a tutorial indicating that mkpasswd -m sha-512 "my password here" would produce a salted and hashed password that can be used in combination with useradd -m -p "hashed and salted passwd" -s /bin/bash username, however when I tried this on a test user, I keep receiving Incorrect Login.

    I am running Ubuntu 16.04 and using mkpasswd from the whois package.

    What am I doing wrong here?


    Exact Steps

    1) apt update

    2) apt install whois

    3) mkpasswd -m sha-512 "my password here"

    produces: $6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g.

    4) useradd -m -p $6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g. -s /bin/bash testuser

    5) login testuser

    Prompts for password:

    6) type my password here

    Says: Login incorrect


    Would like to add that I tried the same thing with a password that has no spaces, and omitted the quotes from the mkpasswd command. Neither seemed to make a difference.

    I also tried to make the user without the -p flag (meaning don't add a password) and manually copied the salted/hashed password into /etc/shadow which produces the same results as above, Login incorrect.


    Even more interesting, if I use a subshell to put the value in, everything seems to work fine.

    useradd -m -p $(mkpasswd -m sha-512 "my password") -s /bin/bash test

    login test type: my password

    Logs in just fine!

    • George Udosen
      George Udosen over 6 years
      Can you provide the link to that tutorial as I don't see any -m option for that command unless I am missing something?
    • Sergiy Kolodyazhnyy
      Sergiy Kolodyazhnyy over 6 years
      @George Do you have whois package installed ? Check with apt-cache policy whois. The option is there.
    • George Udosen
      George Udosen over 6 years
      whois: Installed: 5.2.11 Candidate: 5.2.11 Version table: *** 5.2.11 500 500 http://ng.archive.ubuntu.com/ubuntu xenial/main amd64 Packages 100 /var/lib/dpkg/status I still don't get, excuse my inexperience
    • Sergiy Kolodyazhnyy
      Sergiy Kolodyazhnyy over 6 years
      @Neurax can you provide the exact steps you did ? How did you combine the two commands ? Both commands appear correct, so there must be something you did incorrectly
    • Neurax
      Neurax over 6 years
      I added my steps.
    • Neurax
      Neurax over 6 years
      @George not sure which command you're talking about, but, the -m flag in the mkpasswd command sets the method to use for the encryption, and in the useradd command, the -m flag specifies to create a home directory for the new user.
    • Videonauth
      Videonauth over 6 years
      I tried to create the actual has which represents the password my actual user has and compared it with the entry in /etc/shadow and in all tries of which mkpasswd always created a different output for the same string it never matched my actual password. And can you link that tutorial please.
    • Neurax
      Neurax over 6 years
      @Videonauth that's because each use of the mkpasswd utility will generate a different salt to use during encryption. If you specify which salt to use using the -s "11223344" option, you'll see it come out the same each time. unix.stackexchange.com/questions/187333/… you could grab the salt from your /etc/shadow entry and try it with that flag and you should get the same hash.
    • Neurax
      Neurax over 6 years
      I shouldn't have said tutorial. I meant the man pages for useradd and mkpasswd.
    • Videonauth
      Videonauth over 6 years
      Ok just took the salt from the shadow file and took my password string, and the results still don't match. However the part where the salt is matches, but the rest don't. Try it sudo grep "<main user>" /etc/shadow and mkpasswd -m sha-512 "<main-user-password>" -s <salt>
    • Neurax
      Neurax over 6 years
      Did you grab the proper salt? The $6 in the beginning isn't part of the salt. It's the 8 chars that follow the $6. I've done exactly what you said in your comment as a test and received the OPPOSITE results.
    • Videonauth
      Videonauth over 6 years
      Yep i did $6$<salt>$<hash> :)
    • Neurax
      Neurax over 6 years
      So then why does the subshell work?
  • Neurax
    Neurax over 6 years
    Haha, we were both working on this solution simultaneously. I snuck an answer in 5 minutes ahead. Good find brother, you can have the answer credit! You should definitely edit your solution to include the easy fix of escaping the $ with \$ for thoroughness.
  • Neurax
    Neurax over 6 years
    Looking through your solution, I can't really tell what you're doing with strace, and further, executing sudo -p ">" is confusing to anyone looking at this question. It doesn't have anything to do with the reason why the manual setting of the hash wasn't working. I'd remove that also.
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy over 6 years
    @Neurax I'll add explanation on strace and \$. As for sudo -p ">" it's just to hide my actual username ( although granted - it's already all across the internet anyway).
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy over 6 years
    @Neurax and there we go - edit done
  • George Udosen
    George Udosen over 6 years
    My system was playing tricks on me, and you could always do mkpasswd -m sha-512 "my password" | sed 's/\$/\\$/g' > out.txt to save yourself the replacement of $ with \$ :-)