我在尝试为新用户设置密码时遇到了麻烦。
我发现一个教程表明mkpasswd -m sha-512 "my password here"
会生成一个加盐和散列的密码,可以与结合使用useradd -m -p "hashed and salted passwd" -s /bin/bash username
,但是当我在测试用户上尝试此操作时,我一直收到Incorrect Login
。
我正在运行 Ubuntu 16.04 并mkpasswd
从whois
软件包中使用它。
我在这里做错了什么?
具体步骤
1)apt update
2)apt install whois
3)mkpasswd -m sha-512 "my password here"
生成:$6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g.
4)useradd -m -p $6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g. -s /bin/bash testuser
5)login testuser
提示输入密码:
6)在这里输入我的密码
说:Login incorrect
补充一下,我尝试了同样的方法,密码中没有空格,并且省略了mkpasswd
命令中的引号。这两种方法似乎都没有什么区别。
我还尝试让用户不使用 -p 标志(意味着不添加密码)并手动复制加盐/散列的密码,但/etc/shadow
产生与上述相同的结果,登录不正确。
更有趣的是,如果我使用子 shell 来输入值,一切似乎都正常工作。
useradd -m -p $(mkpasswd -m sha-512 "my password") -s /bin/bash test
login test
类型:my password
登录成功!
答案1
好的,我锁定了这个问题。由于 的输出mkpassword
将导致$id$salt$hash
,当您将其复制并粘贴到useradd
命令中时,bash 将尝试对 进行变量替换$
。因此,需要使用 对其进行转义,\$id\$salt\$hash
以便 bash 在将字符串添加到 之前不会进行变量替换/etc/shadow
。
mkpasswd -m sha-512 "my password"
结果是
$6$5AfGzrQ9u$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1
可以将其复制并粘贴到其中,useradd
确保用 替换$
每个\$
。
useradd -m -s /bin/bash -p \$6\$5AfGzrQ9u\$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1
答案2
为什么会发生这种情况?
失败的原因是,$
当您将其传递给时,带有前导的项目被视为变量并且不会被引用useradd
。
哈希中的$6...
、$1...
和$b...
部分被视为变量。当然,问题出在 shell 上 - shell 在运行任何内容之前会执行变量扩展(除非它们是单引号)。而且由于这 3 个变量不存在于您的环境中,因此它们会从您传递给 的字符串中消失useradd
。
实例:
让我们看看实际的命令在 shell 完成所有必要的扩展和替换并将其传递给execve()
系统调用后运行。比较:
$ 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
在第一个示例中$abra$cadabra
,(这是哈希所在的位置)从系统实际运行的命令中消失。相反,$abra$cadabra
第二个示例中的单引号出现在传递给的参数列表中execve()
。
换句话说,你生成了正确的哈希,但 shell 将完全不同的东西传递给useradd
参数,最终是系统运行的命令。事实上,让我们以你的哈希为例,比较一下引用和非引用的两种情况:
$ strace -e execve echo $6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g
execve("/bin/echo", ["echo", "FuuSdKgVke.LYTfrlknm5cWx65g"], [/* 82 vars */]) = 0
FuuSdKgVke.LYTfrlknm5cWx65g
+++ exited with 0 +++
请注意,在 shell 处理完变量后,系统实际看到的是FuuSdKgVke.LYTfrlknm5cWx65g
。但如果你引用它,它将看到正确的哈希值:
$ strace -e execve echo '$6$1FuuSdKgVke$bc8doOVGZhzomoeafvcQnpYhAxfR4aWdAuYvbxSHw6ZCFZ4NC5j9C762kmvs4Pc66bv4.LYTfrlknm5cWx65g'
execve("/bin/echo", ["echo", "$6$1FuuSdKgVke$bc8doOVGZhzomoeaf"...], [/* 82 vars */]) = 0
可以做什么?有什么用?
但是,subshell 可以工作,因为没有发生替换 - 没有变量。出于同样的原因,引用也可以工作。
以下是几种方法:
命令替换:
$ sudo -p ">" useradd -m -s /bin/bash -p $(mkpasswd --hash=SHA-512 "123" ) newusr > $ su newusr Password: newusr@ubuntu1604:/home/admin$
单引号(请注意,我已修剪实际哈希,因为它太长并且不适合格式):
$ 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
mkpasswd
从流中获取输出stdout
并xargs
通过-I
标志传递它:$ mkpasswd -m sha-512 'password1' | sudo -p '>' xargs -I % useradd -p % newuser1
附加
\
到每个$
(OP自己想出了他们的答案)。 也可以编写脚本,乔治的评论。$ useradd -m -s /bin/bash -p \$6\$5AfGzrQ9u\$r6Q7Vt6h8f2rr4TuW4ZA22m6/eoQh9ciwUuMDtVBX31tR3Tb0o9EB1eBdZ2L9mvT.pX3dIEfxipMoQ0LtTR3V1 newuser