如何将密码传递给子进程?

如何将密码传递给子进程?

众所周知,在命令行上传递密码(到从我的程序启动的子进程)是不安全的(因为即使其他用户使用 ps 命令也可以看到它)。可以将其作为环境变量传递吗?

我还能用什么来通过它? (环境变量除外)最简单的解决方案似乎是使用管道,但这个最简单的解决方案并不容易。

我用 Perl 编程。

答案1

进程参数对所有用户可见,但环境仅对同一用户可见(至少在 Linux 上,并且我认为在每个现代 UNIX 变体上)。因此通过环境变量传递密码是安全的。如果有人可以读取您的环境变量,他们就可以像您一样执行进程,所以游戏就结束了。

环境内容存在间接泄漏的风险,例如,如果您运行ps调查某些内容并意外地将结果(包括机密环境变量)复制粘贴到公共场所。另一个风险是,您将环境变量传递给不需要它的程序(包括需要密码的进程的子进程),并且该程序公开其环境变量,因为它不希望它们是机密的。这些二次泄漏风险的严重程度取决于具有密码的进程的作用(它运行多长时间?它是否运行子进程?)。

通过将密码传递到非设计用于窃听的通道(例如管道),可以更轻松地确保密码不会意外泄露。这在发送端很容易做到。例如,如果您在 shell 变量中有密码,您可以这样做

echo "$password" | theprogram

iftheprogram期望在其标准输入上输入密码。请注意,这是安全的,因为echo它是内置的;使用外部命令并不安全,因为参数会在ps输出中公开。达到相同效果的另一种方法是使用此处文档:

theprogram <<EOF
$password
EOF

某些需要密码的程序可以被告知从特定的文件描述符中读取密码。如果您需要标准输入用于其他用途,则可以使用标准输入以外的文件描述符。例如,使用gpg

get-encrypted-data | gpg --passphrase-fd 3 --decrypt … 3<<EOP >decrypted-data
$password
EOP

如果无法告诉程序从文件描述符中读取,但可以告诉程序从文件中读取,则可以使用“/dev/fd/3”等文件名来告诉程序从文件描述符中读取。

theprogram --password-from-file=/dev/fd/3 3<<EOF
$password
EOF

在 ksh、bash 或 zsh 中,您可以通过进程替换更简洁地完成此操作。

theprogram --password-from-file=<(echo "$password")

答案2

而不是直接通过参数或环境变量传递密码

#!/bin/bash
#filename: passwd_receiver
echo "The password is: $1"

使用相同的参数或环境变量来传递文件名:

#!/bin/bash
#filename: passwd_receiver
echo "The password is: $(< "$1")"

然后你可以通过受权限保护的常规文件(尽管这不会保护您免受同一用户下运行的其他进程的影响),或者/dev/stdin管道它位于(据我所知,它将保护您免受同一用户下运行的其他进程的影响):

 echo PASSWORD | ./passwd_receiver /dev/stdin 

如果你/dev/stdin在这里使用,那就是必须它是一个管道。如果它是终端,则同一用户下运行的其他进程可以读取它。

如果您已经需要将其用于/dev/stdin其他用途,则可以使用流程替代如果您使用的是支持它的外壳,这本质上相当于使用管道:

./passwd_receiver <(echo PASSWORD)

命名管道 (FIFO) 可能看起来相同,但它们是可拦截的。

这些解决方案是不完全安全两者都可以,但只要您不在频繁交换的内存受限系统上,它们可能就足够接近了。

理想情况下,您会将这些文件(管道也是一个文件)读入标记为的内存中时钟锁(2)作为不可交换的,这是密码处理程序(例如 gnupg)通常所做的事情。

笔记:

  1. 理论上,传递文件描述符数字与文件传递文件名一样好,但文件名更实用,因为<()给你一个文件名,而不是文件描述符编号(并且coprocs 给你标记的文件描述符FD_CLOEXEC,这使得这些文件描述符在此上下文中无法使用)。


  2. /proc/sys/kernel/yama/ptrace_scope如果您使用的是设置为 的Linux 系统0,那么据我所知,没有万无一失的方法可以保护您免受同一用户下运行的其他进程的影响(它们可以使用 ptrace 附加到您的进程并读取您的内存)

  3. 如果您只需要让密码远离在不同(非 root)用户下运行的进程,那么参数、环境变量、管道和受权限保护的文件都可以。

答案3

不,环境变量也很容易被读取,并泄漏到子进程。使用管道传递它。

答案4

如果没有其他合适的选择,请考虑 Linux 密钥保留服务(内核密钥环)。

开始于:安全/keys.txt。可以在父进程和子进程之间克隆默认密钥环之一。

这不是最简单的解决方案,但它确实存在并且似乎得到了维护和使用(去年的 Android 错误也涉及到它。)

我不知道它的“政治”地位,但我有类似的需求,并开始研究 Guile 绑定。没有遇到过预先存在的 Perl 支持。

相关内容