修改命令行参数,使其在 ps 输出中不可见。

3
我有一个可执行文件,接受特定的命令行参数。机器上的任何用户都可以通过ps(Unix)或procexp(Windows)找到这些参数。其中一些参数是密码之类的敏感信息。我知道我们不应该像这样传递密码。
在可执行文件的代码中是否有任何方法可以更改,以便其他用户无法看到用于启动可执行文件的命令行参数?
我确定没有平台独立的方法来做到这一点,但即使有针对每个平台的特定API也将是一个很好的起点。期待您的评论/建议或想法。
问候,
Ash

8
希望你已经将~/.bash_history符号链接到了/dev/null... - user229044
1
找了一会儿,但是https://dev59.com/d1DTa4cB1Zd3GeqPKp5i建议在某些平台上,您可以修改由`argc []`指向的字符串的内容。 - torak
虽然我不建议这样做,但在Windows上,你可以覆盖从GetCommandLine()返回的缓冲区。 - Luke
8个回答

6
您正在尝试让一个不安全的解决方案变得稍微更加安全。为什么不直接使其更加安全呢?
一种快速的解决方法是将密码写入一个权限受限的文件中,并在调用可执行文件读取该文件后立即将其删除。如果文件被写入磁盘,您仍然存在硬盘上的位数的风险。但是,您可以通过使用 RAM 磁盘来消除这个问题。
或者,您可以为可执行文件提供一个私钥,并使用相应的公钥加密密码。这需要更多的工作,但更加安全。然后,当然您还需要解决密钥管理的问题。

3
任何依赖于清除 ps 输出中显示的 argv 的方法都会存在竞争条件,因此无法保证安全。也就是说,在进程启动后但在其可以清除公开可见参数之前存在一段时间间隔。
如果您需要此功能(在命令行中传递密码,这是一个非常非常糟糕的想法),则应使用允许您完全禁用读取命令行参数甚至完全禁用 ps 功能的强化内核。其中一种简单的方法(但可能会破坏某些内容)是卸载 /proc

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;
}

2
你可以将密码写入受读保护的文件中,然后从新的可执行文件中访问它,而不是将其作为参数传递。 正如 meagar 的评论所示,ps 并不是你唯一的敌人。

2
我认为基本的解决方案可能是不要通过命令行传递数据,而是使用RPC。stdin是一个简易的RPC,写入文件并删除也是如此,还有更复杂的方法。
例如,在Windows上,如果你真的关心安全问题,我建议使用命名管道,你可以对其应用安全权限并加密数据,如果你需要的话。你可能也可以使用共享内存,这是一种更便携的方法。
然而,任何RPC解决方案都需要修改通信的两端。试图通过修改操作系统来混淆数据,或依赖于未记录的运行时行为,从安全角度来看似乎是一个不好的主意。
希望这能帮到你。

1

某些版本的init会覆盖它们的命令行,以便在ps列表中显示为init

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可以设计成这样工作。顺便说一句,我还没有测试它是否有效,但我读到过必须是实际内存中的参数,仅复制指针数组到这些参数是行不通的。

通过命令行(或环境变量,因为在Linux下这些变量可以在/proc/<pid>/environ中访问,就像argv在/proc/<pid>/cmdline中一样),传递敏感信息仍然是一种错误的做法。


环境对我来说看起来更安全:cat: /proc/1/environ: 权限被拒绝 - SamB

0

如果使用密码命令行,您可以让程序重新执行并将信息传递给第二个实例并终止第一个实例,从而减少命令行信息存在的时间。

唯一的好答案是不要让他们通过命令行传递信息。


0
我通常从标准输入读取所有敏感数据。例如,在Linux上的isql(Sybase SQL shell)中,我会做类似的操作。
isql -U username <<EOD
password
select * from whatever
go

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