我有一个接受某些命令行参数的可执行文件。机器上的任何用户都可以通过执行 ps (Unix) 或 procexp (Windows) 找到参数。其中一些参数是密码之类的东西。我知道我们不应该这样传递密码。
可执行文件的代码中是否有任何方法可以更改,以便执行 ps/procexp 的其他用户看不到用于启动可执行文件的命令行参数?
我确信没有平台独立的方法可以做到这一点,但即使每个平台都有特定的 API 来做到这一点,这也是一个很好的起点。我期待听到任何评论/建议或想法。
问候,
灰
您正在尝试使不安全的解决方案更加安全。为什么不让它更安全呢?
一个快速的破解方法是将密码写入设置为受限权限的文件,并在被调用的可执行文件读取后立即将其删除。如果将文件写入磁盘,您仍然面临硬盘驱动器上仍然存在这些位的风险。但是你可以通过使用 ramdisk 来消除这个问题。
或者您可以给可执行文件一个私钥,并使用相应的公钥加密密码。这需要更多的工作,但更安全。然后当然你有密钥管理的问题。
任何依赖于清除输出中argv
显示的方法ps
都会有竞争条件,因此它不安全。也就是说,在流程开始之后但在它可以清除其公开可见的参数之前有一段时间。
如果您需要此功能(在命令行上传递密码,这是一个非常非常糟糕的主意),您应该使用硬化内核,它允许您完全禁用读取命令行参数,甚至ps
完全禁用功能。一种便宜的方法(但它可能会破坏事情)就是 unmounting /proc
。
您可以将密码写入受读保护的文件,然后从新的可执行文件访问它,而不是将其作为参数传递。
ps
不是你唯一的敌人,从 meagar 的评论中可以明显看出。
这个init
例子给了我分段错误
然而,这个有效:
int main(int argc, char *argv[])
{
char * argv0 = argv[0];
int i;
size_t len;
for (i = 0; i <argc; ++i)
{
len = strlen(argv[i]);
memset(argv[i], 0, len);
}
strcpy(argv0, "Hey, can you see me?");
for (;;);
return 0;
}
我认为基本的答案可能是不在命令行上传递数据,而是使用 RPC。stdin 是穷人的 RPC,就像写入文件然后删除一样,还有更复杂的方法。
例如,在 Windows 上,如果您真的关心安全性,我建议您使用命名管道,如果您愿意,您可以对其应用安全权限并加密数据。您可能还可以使用共享内存,以获得更便携的方法。
然而,显然,任何 RPC 解决方案都需要修改通信的双方。不过,试图通过修改操作系统以防止正常操作或依赖未记录的运行时行为来混淆数据,这在安全方面似乎是个坏主意。
希望有帮助。
某些版本会init
覆盖其命令行,以便它们显示为init
列表ps
。
int main(int argc, char * argv[]) {
// process the arguments or make a copy of them
// and then
char * argv0 = argv[0];
while (*argv++) {
size_t len = strlen(*argv);
memset(*argv, 0, len);
}
strcpy(argv0, "init");
我很惊讶地看到这种类型的东西被使用,并且 *nix 可以设计成可以工作的方式。顺便说一句,我还没有测试它是否有效,但我确实读到它必须是参数所在的实际内存,并且仅将指针数组复制到这些参数是行不通的。
/proc/<pid>/environ
通过命令行(或环境变量,因为它们可以像 argv 在/proc/<pid>/cmdline
Linux 下一样访问)传递敏感信息仍然是一种破碎的方式。
如果使用密码命令行,您可以让程序重新执行自身并将信息传递给第二个实例并杀死第一个实例,从而减少命令行信息出现的时间。
唯一好的答案是不要让他们在命令行上传递信息。
我通常从标准输入读取所有敏感数据。例如,在 Linux 上的 isql (Sybase SQL shell) 中,我执行类似的操作
isql -U username <<EOD
password
select * from whatever
go