已知在命令行上(从我的程序启动的子进程中)传递密码是不安全的(因为即使使用ps命令的其他用户也可以看到密码)。可以将其作为环境变量传递吗?
我还能通过什么?(除了环境变量),最简单的解决方案似乎是使用管道,但是这种最简单的解决方案并不容易。
我在Perl中编程。
已知在命令行上(从我的程序启动的子进程中)传递密码是不安全的(因为即使使用ps命令的其他用户也可以看到密码)。可以将其作为环境变量传递吗?
我还能通过什么?(除了环境变量),最简单的解决方案似乎是使用管道,但是这种最简单的解决方案并不容易。
我在Perl中编程。
Answers:
进程参数对所有用户可见,但环境仅对同一用户可见(至少在Linux上,并且我认为在每个现代的unix变体上)。因此,通过环境变量传递密码是安全的。如果有人可以读取您的环境变量,那么他们就可以像您一样执行流程,因此已经过去了。
环境的内容可能会存在间接泄漏的风险,例如,如果您ps
尝试调查某些内容,并且在公共场所意外地将结果(包括机密环境变量)粘贴-粘贴。另一个风险是,您将环境变量传递给不需要它的程序(包括需要密码的进程的子进程),并且该程序公开了它的环境变量,因为它不希望它们是机密的。这些二次泄漏的风险有多严重取决于密码处理的过程(运行多长时间?运行子流程吗?)。
通过使密码通过未设计为窃听的通道(例如管道),可以更轻松地确保密码不会意外泄漏。在发送方这很容易做到。例如,如果您在shell变量中输入了密码,则只需执行
echo "$password" | theprogram
如果theprogram
期望在其标准输入上输入密码。注意,这是安全的,因为echo
它是内置的。使用外部命令并不安全,因为该参数将在ps
输出中公开。获得相同效果的另一种方法是使用here文档:
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")
/usr/ucb/ps
setuid为root,因此可以读取和显示其他进程的环境变量-在Solaris 10中已将其删除,因此上述“其他现代Unix变体”的答案适用于2005年及以后的Solaris发行版。
而不是直接通过参数或环境变量传递密码
#!/bin/bash
#filename: passwd_receiver
echo "The password is: $1"
使用相同的参数或环境变量传递文件名:
#!/bin/bash
#filename: passwd_receiver
echo "The password is: $(< "$1")"
然后,你可以通过其中一个许可保护的常规文件(尽管这不会保护你从同一个用户下运行的其他进程),或/dev/stdin
和管它(这AFAIK会保护你从同一个用户下运行的其他进程):
echo PASSWORD | ./passwd_receiver /dev/stdin
如果在此使用/dev/stdin
,则必须是管道。如果是终端,则同一用户下运行的其他进程将可以读取它。
如果您已经需要将其/dev/stdin
用于其他用途,则可以在支持它的shell上使用进程替换,这实际上等效于使用管道:
./passwd_receiver <(echo PASSWORD)
命名管道(FIFO)看起来可能相同,但是可以被拦截。
这些解决方案也不是完全安全的,但是只要您不在内存频繁交换的内存受限系统上,它们可能就足够接近了。
理想情况下,您会将这些文件(管道也是文件)读入标记为mlock(2)的不可交换内存中,这就是gnupg等密码处理程序通常会执行的操作。
笔记:
从理论上讲,传递文件描述符号与传递文件名一样好,但文件名更实用,因为<()
给您提供文件名,而不是文件描述符号(并且coproc
s为您提供标记为FD_CLOEXEC的文件描述符,这使这些文件描述符在这种情况下不可用)。
如果您使用的Linux系统
/proc/sys/kernel/yama/ptrace_scope
设置为0
,则为AFAIK,则没有防弹方法可以保护自己免受同一用户下运行的其他进程的侵害(他们可以使用ptrace附加到您的进程并读取您的内存)
如果只需要使密码远离在不同(非root)用户下运行的进程,则参数,环境变量,管道和受权限保护的文件都可以。
不,环境变量也很容易读取,并泄漏给子进程。使用管道将其传递。
ps
和/proc
可以看到它。
ptrace()
无论如何都可以只是目标并读取其内存。
如果没有其他合适的方法,请考虑使用Linux密钥保留服务(内核密钥环)。
从以下位置开始:security / keys.txt。可以在父进程和子进程之间克隆默认密钥环之一。
它不是最简单的解决方案,但是它已经存在并且似乎可以维护和使用(去年它也牵涉到一个Android错误中。)
我不知道它的“政治”地位,但我有类似的需求,并开始从事Guile装订工作。尚未遇到过Perl支持。