我有一个接受某些命令行参数的可执行文件。机器上的任何用户都可以通过执行ps(Unix)或procexp(Windows)来查找参数。其中一些参数就像密码一样。我知道我们不应该传递这样的密码。
在可执行文件的代码中是否有任何方法可以更改,以便执行ps / procexp的其他用户无法看到用于启动可执行文件的命令行参数?
我确信没有独立于平台的方法可以做到这一点,但即使每个平台都有特定的API来执行此操作,这将是一个很好的起点。我期待听到任何意见/建议或想法。
此致
灰
答案 0 :(得分:6)
你试图让一个不安全的解决方案更加安全。为什么不让它更安全?
快速入侵是将密码写入设置为受限权限的文件,并在被被调用的可执行文件读取后立即将其删除。如果文件写入磁盘,则仍然存在硬盘驱动器上仍存在这些位的风险。但是你可以通过使用ramdisk消除这个问题。
或者您可以为可执行文件提供私钥,并使用相应的公钥加密密码。这是一项更多的工作,但更安全。当然,你有密钥管理的问题。
答案 1 :(得分:3)
任何依赖于清除argv
输出中显示的ps
的方法都会出现竞争条件,因此无法保证安全。也就是说,在进程开始之后但是在它可以清除其公开可见的参数之前有一段时间。
如果您需要此功能(在命令行上传递密码,这是非常非常糟糕的想法),您应该使用一个强化内核,它允许您完全禁用命令行参数的读取,甚至完全禁用ps
功能。这样做的一种廉价方法(但它可能会破坏事情)只是卸载/proc
。
答案 2 :(得分:2)
您可以将密码写入读保护文件,然后从新的可执行文件中访问它,而不是将其作为参数传递。
ps
不是你唯一的敌人,因为meagar的评论显而易见。
答案 3 :(得分:2)
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;
}
答案 4 :(得分:2)
我认为基本答案可能是不在命令行上传递数据,而是使用RPC。 stdin是一个穷人的RPC,就像写入你随后删除的文件一样,并且有更复杂的方法。
在Windows上,例如,如果您真的担心安全问题,我建议您使用命名管道,如果需要,您可以对其应用安全权限并对数据进行加密。您也可以使用共享内存,以获得更便携的方法。
然而,任何RPC解决方案都需要修改通信的两端。试图通过修改操作系统来模糊数据以防止正常操作或依赖未记录的运行时行为,但在安全方面似乎是一个坏主意。
希望有所帮助。
答案 5 :(得分:1)
某些版本的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在Linux下的/proc/<pid>/cmdline
中一样。
答案 6 :(得分:0)
如果使用密码命令行,您可以重新执行程序并将信息传递给第二个实例并终止第一个实例,从而减少命令行信息的存在时间。
唯一的好办法就是不要让他们在命令行上传递信息。
答案 7 :(得分:0)
我通常从stdin读取所有敏感数据。例如,在Linux上的isql(Sybase SQL shell)中,我执行类似
的操作isql -U username <<EOD
password
select * from whatever
go