为什么会发生这种情况?

为什么会发生这种情况?

我在尝试为新用户设置密码时遇到了麻烦。

我发现一个教程表明mkpasswd -m sha-512 "my password here"会生成一个加盐和散列的密码,可以与结合使用useradd -m -p "hashed and salted passwd" -s /bin/bash username,但是当我在测试用户上尝试此操作时,我一直收到Incorrect Login

我正在运行 Ubuntu 16.04 并mkpasswdwhois软件包中使用它。

我在这里做错了什么?


具体步骤

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

可以做什么?有什么用?

但是,subshel​​l 可以工作,因为没有发生替换 - 没有变量。出于同样的原因,引用也可以工作。

以下是几种方法:

  1. 命令替换:

    $ sudo -p ">" useradd -m -s /bin/bash -p $(mkpasswd --hash=SHA-512 "123" ) newusr        
    >
    $ su newusr
    Password: 
    newusr@ubuntu1604:/home/admin$ 
    
  2. 单引号(请注意,我已修剪实际哈希,因为它太长并且不适合格式):

    $ 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. mkpasswd从流中获取输出stdoutxargs通过-I标志传递它:

    $ mkpasswd -m sha-512 'password1' | sudo -p '>' xargs -I % useradd -p % newuser1 
    
  4. 附加\到每个$(OP自己想出了他们的答案)。 也可以编写脚本,乔治的评论

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

相关内容