Shell脚本命令行参数的密码安全性

7

如果我将密码作为命令行参数使用,那么在使用ps命令的系统上,密码会变成公共信息。

但是,如果我在bash shell脚本中执行以下操作:

...
{ somecommand -p mypassword }
...

这个进程还会在进程列表中显示吗?还是说它是安全的?

  • 子进程呢:(...)?不安全对吧?
  • 协同进程?
4个回答

8

命令行始终可见(即使只是通过/proc可见)。

因此,唯一真正的解决方案是:不要让其可见。您可以将其提供在stdin上或专用的fd上:

./my_secured_process some parameters 3<<< "b@dP2ssword"

使用类似以下脚本(简单为先):
#!/bin/bash
cat 0<&3

现在你需要关注的是:

  • 中间人攻击(欺骗脚本窃听密码,例如通过篡改PATH)
  • bash历史记录会在命令行中保留您的密码(例如查看bash的HISTIGNORE)
  • 包含密码重定向的脚本的安全性
  • 使用的tty的安全性;键盘记录器;……正如您所看到的,我们现在已经降到了“一般安全原则”的层面

(此示例只会将错误密码转储到stdout)


3 是打错了吗?应该只是 <<< 吗?如果不是,那么 3 代表什么意思? - q0rban
好的,我明白了。那是参数的编号吗?我认为应该是2而不是3。第一个参数应该是0,第二个是1,第三个是2。这正确吗? - q0rban
1
不是。<<<的意思是:将此文本流传输到stdin。3<<<的意思是:将此文本流传输到文件描述符3。正如演示脚本所示,您可以从脚本中读取fd 3。这是一种安全性通过混淆,因为stdin/stdout/stderr是唯一的标准(通常)shell管道文件描述符。 - sehe
坦白地说,这并没有什么实际作用,因为输入最终仍然会被发送到cat(在示例中)的标准输入(文件描述符0)... 但至少不会出现在pstop/proc/...的命令行中。 - sehe
4
据说,在bash中,"here-strings"被实现为已删除的临时文件。如果这意味着它们可能会到磁盘上,那就是另一个安全问题。最好使用进程替换(像这里一样): ./my_secured_process some parameters 3< <(printf '%s\n' b@dP2ssword) - tanius

4

3
被调用的程序可以通过简单地覆盖 argv 来更改其命令行,例如:
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
    int arglen = argv[argc-1]+strlen(argv[argc-1])+1 - argv[0];
    memset(argv[0], arglen, 0);
    strncpy(argv[0], "secret-program", arglen-1);
    sleep(100);
}

测试:

$ ./a.out mySuperPassword & 
$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
me       20398 18872  0 11:26 pts/3    00:00:00 bash
me       20633 20398  0 11:34 pts/3    00:00:00 secret-program
me       20645 20398  0 11:34 pts/3    00:00:00 ps -f
$

更新:我知道这并不完全安全,可能会导致竞争条件,但是许多从命令行接受密码的程序都使用此技巧。


0

唯一的逃避被显示在进程列表中的方法是,如果您在纯Bash函数中重新实现要调用的程序的整个功能。函数调用不是单独的进程。虽然通常这是不可行的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接