Por que isso acontece?
O motivo pelo qual ele falha é porque os itens com $
iniciais são tratados como variáveis e não são citados quando você os passa para useradd
.
As porções ...
, ...
e $b...
do seu hash são tratadas como variáveis. Naturalmente, a falha é com os shell - shells executam uma expansão variável (a menos que eles estejam entre aspas simples) antes que algo seja executado. E como essas 3 variáveis não existem em seu ambiente, elas desaparecem da string que você passa para useradd
.
Exemplo prático:
Vamos ver o comando real executado após o shell terminar de executar todas as expansões e substituições necessárias e passar isso para execve()
system call. Comparar:
$ 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
No primeiro exemplo $abra$cadabra
(que é onde o hash iria) desaparece do comando que realmente é executado pelo sistema. Por outro lado, o único citado $abra$cadabra
no segundo exemplo aparece na lista de argumentos transmitidos para execve()
.
Em outras palavras, você gerou o hash correto, mas o shell passa uma coisa completamente diferente para useradd
como argumento, que é o comando que o sistema executa. De fato, vamos pegar seu hash por exemplo e comparar dois casos de cotação e não-citação:
$ strace -e execve echo FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g
execve("/bin/echo", ["echo", "FuuSdKgVke.LYTfrlknm5cWx65g"], [/* 82 vars */]) = 0
FuuSdKgVke.LYTfrlknm5cWx65g
+++ exited with 0 +++
Observe que o que o sistema realmente vê após o shell é processado, as variáveis são FuuSdKgVke.LYTfrlknm5cWx65g
. Mas ele verá o hash correto se você citá-lo:
$ strace -e execve echo 'FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g'
execve("/bin/echo", ["echo", "FuuSdKgVke$bc8doOVGZhzomoeaf"...], [/* 82 vars */]) = 0
O que pode ser feito? O que funciona?
No entanto, o subshell funciona porque não há substituição ocorrendo - não há variáveis. E as citações também funcionam pelo mesmo motivo.
Aqui estão alguns métodos:
-
Substituição de comandos:
$ sudo -p ">" useradd -m -s /bin/bash -p $(mkpasswd --hash=SHA-512 "123" ) newusr
>
$ su newusr
Password:
newusr@ubuntu1604:/home/admin$
-
Aspas simples (observe que apareci o hash real porque é muito longo e não cabe na formatação):
$ 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
-
Pegue a saída do mkpasswd
' stdout
stream e passe-a via xargs
com -I
flag:
$ mkpasswd -m sha-512 'password1' | sudo -p '>' xargs -I % useradd -p % newuser1
-
Anexe o \
a cada $
(que o OP descobriu na sua resposta ). Scriptable, também, como por comentário de George . / p>
$ useradd -m -s /bin/bash -p $6$5AfGzrQ9u$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1 newuser