我有一个脚本,在其自身内部启动一个带有参数的命令,这是一个秘密.例如:
#!/bin/bash
command-name secret
Run Code Online (Sandbox Code Playgroud)
在运行命令时,我可以通读ps -ef | grep command-name
哪个是秘密.
有没有办法以通过ps -ef
命令行参数混淆的方式隐藏秘密?
Vas*_*kov 11
首先,您不能隐藏命令行参数.他们仍然会通过可见ps aux
,并cat /proc/$YOUR_PROCESS_PID/cmdline
在启动程序(该程序有机会做运行时更改参数之前)的时间.好消息是,通过使用替代方案,您仍然可以拥有秘密:
使用环境变量.如果您的程序可以读取它们,请执行以下操作
mySecret='hello-neo' myCommand
Run Code Online (Sandbox Code Playgroud)使用标准输入:
mySecret='hello-neo' printenv mySecret | myCommand
Run Code Online (Sandbox Code Playgroud)使用临时文件描述符:
myCommand <( mySecret='hello-neo' printenv mySecret )
Run Code Online (Sandbox Code Playgroud)在最后一种情况下,您的程序将启动myCommand /dev/fd/67
,其中内容/dev/fd/67
是您的秘密(hello-neo
在此示例中).
在上述所有方法中,要小心将命令保留在bash命令history(~/.bash_history
)中.您可以通过从脚本(文件)运行命令或通过每次交互式提示自己输入密码来避免这种情况:
read mySecret
myCommand # approach 2
printenv mySecret | myCommand # approach 3
myCommand <( printenv mySecret ) # approach 4
Run Code Online (Sandbox Code Playgroud)
如果秘密在执行之间没有变化,请使用特殊配置文件".appsecrets"
.将文件的权限设置为所有者只读.在文件内部为秘密设置环境变量.该文件需要位于运行该命令的用户的主目录中.
#!/bin/bash
#filename: .appsecrets
set SECRET=polkalover
Run Code Online (Sandbox Code Playgroud)
加载配置文件,以便设置环境变量.
. ~/.appsecrets
Run Code Online (Sandbox Code Playgroud)
我见过的事情:
1)
echo $SECRET | command
如果命令提示输入密码来自stdin,并且'echo'是shell的内置函数,则可以正常工作.我们正在使用Korn.
2)
password=$ENV{"SECRET"};
如果您能控制代码,则可以工作(例如,在perl或C++中)
3)
. ./.app.config #sets the environment variables
isql -host [host] -user [user] -password <<SECRET
${SQLPASSWORD}
SECRET
如果命令可以从std-in接受秘密,则可以正常工作.一个限制是<<
字符串必须是给予命令的最后一个参数.如果在-password之后必须出现非可选的arg,这可能会很麻烦
这种方法的好处是你可以安排它,这样秘密就可以隐藏在生产中.在生产中使用相同的文件名,但它将位于生产中运行命令的帐户的主目录中.然后,您可以像访问root帐户一样锁定对机密的访问权限.只有某些人可以"su"到prod帐户来查看或维护这个秘密,而开发人员仍然可以运行该程序,因为他们在自己的主目录中使用自己的".appsecret"文件.
您可以使用此方法为任意数量的应用程序存储安全信息,只要它们为其秘密使用不同的环境变量名称即可.
(错误的
方法)我看到DBA使用的一种旧方法是将SYBASE设置为"/opt/././././././././././././././././././././././././././././././././././sybase/bin"
.所以他们的命令行很长,ps截断了它.但是在linux中我认为你可以从/ proc中嗅出完整的命令行.
隐瞒你的秘密论据的唯一方法ps
就是不要把这个秘密作为论据.一种方法是将秘密放在一个文件中,并重定向文件描述符3以读取文件,然后删除该文件:
echo secret > x.$$
command 3<x.$$
rm -f x.$$
Run Code Online (Sandbox Code Playgroud)
目前尚不完全清楚这是一种拯救秘密的安全方式; echo命令是一个内置的shell,所以它不应该出现在'ps'输出中(任何外观都会稍纵即逝).很久以前,echo
不是内置的 - 事实上,在MacOS X上,/bin/echo
即使它是内置的所有炮弹,仍然有一个内置.
当然,这假设您拥有源command
并可以修改它以从预先打开的文件描述符而不是命令行参数中读取秘密.如果您无法修改命令,那么您将完全陷入困境 - "ps"列表将显示该信息.
如果你是命令所有者,你可以获得另一个技巧:你可以捕获参数(秘密),将它写入管道或文件(立即取消链接),然后重新执行命令而不使用secret参数; 第二次调用知道,由于秘密不存在,它应该在第一次调用隐藏秘密的任何地方查找.第二次调用(减去秘密)是在处理隐藏秘密所需的微小间隔之后出现在'ps'输出中的内容.不如从头开始设置秘密通道.但这些表明了你必须走的长度.
从程序内部切换一个参数 - 例如用零覆盖 - 不会隐藏'ps'中的参数.
我在另一个帖子上看到的。这是Linux下最简单的方法。
这会修改所有其他程序看到的命令行的内存部分。
strncpy(argv[1], "randomtrash", strlen(argv[1]));
Run Code Online (Sandbox Code Playgroud)
您还可以更改进程的名称,但仅限于从命令行读取时。像这样的程序top
将显示真实的进程名称:
strncpy(argv[0], "New process name", strlen(argv[0]));
Run Code Online (Sandbox Code Playgroud)
不要忘记复制最大strlen(argv[0])
字节数,因为可能没有分配更多空间。
我认为参数只能在我们修改的内存部分中找到,所以我认为这很有魅力。如果有人对此有所了解,请发表评论。
VasyaNovikov注意:在程序调用之后但在开始执行您描述的更改之前,仍然可以拦截密码。