我需要隐藏我正在运行的程序的一些敏感参数,但我无权访问源代码。我也在共享服务器上运行它,所以我不能使用类似的东西,hidepid
因为我没有 sudo 权限。
以下是我尝试过的一些事情:
export SECRET=[my arguments]
,然后调用./program $SECRET
,但这似乎没有帮助。./program `cat secret.txt`
那里secret.txt
有我的论据,但全能的神ps
能够嗅出我的秘密。
有没有其他方法可以隐藏我的论点而不涉及管理员干预?
答案1
正如所解释的这里,Linux 将程序的参数放入程序的数据空间中,并保留一个指向该区域开头的指针。这是ps
等等用来查找和显示程序参数的方法。
由于数据位于程序的空间中,因此它可以对其进行操作。在不更改程序本身的情况下执行此操作涉及加载一个填充程序,其中包含一个main()
将在程序的真正主程序之前调用的函数。这个垫片可以将真实参数复制到新空间,然后覆盖原始参数,这样就ps
只能看到空值。
以下 C 代码执行此操作。
/* https://unix.stackexchange.com/a/403918/119298
* capture calls to a routine and replace with your code
* gcc -Wall -O2 -fpic -shared -ldl -o shim_main.so shim_main.c
* LD_PRELOAD=/.../shim_main.so theprogram theargs...
*/
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>
typedef int (*pfi)(int, char **, char **);
static pfi real_main;
/* copy argv to new location */
char **copyargs(int argc, char** argv){
char **newargv = malloc((argc+1)*sizeof(*argv));
char *from,*to;
int i,len;
for(i = 0; i<argc; i++){
from = argv[i];
len = strlen(from)+1;
to = malloc(len);
memcpy(to,from,len);
memset(from,'\0',len); /* zap old argv space */
newargv[i] = to;
argv[i] = 0;
}
newargv[argc] = 0;
return newargv;
}
static int mymain(int argc, char** argv, char** env) {
fprintf(stderr, "main argc %d\n", argc);
return real_main(argc, copyargs(argc,argv), env);
}
int __libc_start_main(pfi main, int argc,
char **ubp_av, void (*init) (void),
void (*fini)(void),
void (*rtld_fini)(void), void (*stack_end)){
static int (*real___libc_start_main)() = NULL;
if (!real___libc_start_main) {
char *error;
real___libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
}
real_main = main;
return real___libc_start_main(mymain, argc, ubp_av, init, fini,
rtld_fini, stack_end);
}
无法干预main()
,但可以干预标准 C 库函数__libc_start_main
,该函数会继续调用 main。shim_main.c
按照开头注释中的说明编译此文件,然后按所示运行它。我printf
在代码中留下了 a ,以便您检查它是否确实被调用。例如,运行
LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100
然后执行 a ps
,您将看到显示空白命令和参数。
命令参数还有很短的时间才可见。为了避免这种情况,您可以更改填充程序以从文件中读取您的秘密并将其添加到传递给程序的参数中。
答案2
答案3
hidepid
如果您需要向程序传递参数才能使其正常工作,那么如果您不能在 procfs 上使用,那么无论您做什么,您都将不走运。
既然您提到这是一个 bash 脚本,您应该已经拥有可用的源代码,因为 bash 不是编译语言。
如果做不到这一点,你可能能够使用 或 类似的方式重写进程的命令行,并在进程启动后gdb
使用argc
/ ,但是:argv
- 这是不安全的,因为您在更改程序参数之前仍然会首先公开它们
- 这是相当老套的,即使你可以让它工作,我也不建议依赖它
我真的只是建议获取源代码,或者与供应商联系以修改代码。在 POSIX 操作系统中的命令行上提供机密与安全操作不兼容。
答案4
你可能会做的是
export SECRET=somesecretstuff
然后,假设您正在用 C 编写./program
(或者其他人这样做,并且可以为您更改或改进它),请使用获取环境(3)在那个程序中,也许是
char* secret= getenv("SECRET");
之后,您只需在同一个 shell 中export
运行即可。./program
或者可以将环境变量名称传递给它(通过运行./program --secret-var=SECRET
等...)
ps
不会泄露你的秘密,但是过程(5)仍然可以提供很多信息(至少对于同一用户的其他进程)。
也可以看看这帮助设计一种更好的传递程序参数的方法。
看这个答案更好地解释通配符和 shell 的作用。
也许您program
有其他一些方法来获取数据(或使用进程间通信比普通的程序参数更明智(如果要处理敏感信息,它当然应该这样做)。阅读其文档。或者您可能正在滥用该程序(该程序无意处理秘密数据)。
隐藏秘密数据确实很困难。不通过程序参数传递它是不够的。