실행 중인 프로그램의 일부 민감한 매개변수를 숨겨야 하는데 소스 코드에 액세스할 수 없습니다. 저도 공유서버에서 실행중인데 hidepid
sudo 권한이 없어서 그런건 못쓰겠습니다 .
제가 시도한 몇 가지 사항은 다음과 같습니다.
export SECRET=[my arguments]
, 그리고 전화를 걸었지만./program $SECRET
도움이 되지 않는 것 같습니다../program `cat secret.txt`
내 주장은 거기에 있지만secret.txt
전능하신 하나님은ps
내 비밀을 알아내실 수 있습니다.
관리자 개입 없이 내 주장을 숨길 수 있는 다른 방법이 있습니까?
답변1
설명대로여기, Linux는 프로그램의 매개변수를 프로그램의 데이터 공간에 넣고 해당 영역의 시작 부분에 대한 포인터를 유지합니다. 이는 ps
다른 사람들이 프로그램 매개변수를 찾아 표시하는 데 사용하는 방법입니다.
데이터는 프로그램 공간에 있으므로 이를 조작할 수 있습니다. 프로그램 자체를 변경하지 않고 이를 수행하려면 main()
프로그램의 실제 메인 루틴 이전에 호출될 함수가 포함된 shim을 로드해야 합니다. 이 심은 실제 매개변수를 새 공간에 복사한 다음, ps
null 값만 보이도록 원래 매개변수를 덮어씁니다.
다음 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을 호출하는 main()
표준 C 라이브러리 함수를 방해할 수는 있습니다 . 시작 주석에 설명된 대로 이 파일을 컴파일한 다음 표시된 대로 실행합니다. 실제로 호출되었는지 확인할 수 있도록 코드에 를 남겼습니다 . 예를 들어 다음을 실행합니다.__libc_start_main
shim_main.c
printf
LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100
그런 다음 a를 실행하면 ps
빈 명령과 매개변수가 표시됩니다.
명령 매개변수가 표시되기까지는 아직 시간이 조금 걸립니다. 이를 방지하려면 shim을 변경하여 파일에서 비밀을 읽고 이를 프로그램에 전달된 매개변수에 추가할 수 있습니다.
답변2
답변3
hidepid
프로그램이 작동하도록 하기 위해 인수를 프로그램에 전달해야 하는 경우, procfs에서 이를 사용할 수 없다면 무엇을 하든 운이 없는 것입니다.
이것이 bash 스크립트라고 언급하셨으므로, bash는 컴파일된 언어가 아니기 때문에 이미 사용 가능한 소스 코드가 있어야 합니다.
만약 당신이 이것을 할 수 없다면, 당신은가능한또는 이와 유사한 것을 사용하여 프로세스의 명령줄을 다시 작성할 수 있고 프로세스가 시작된 후에 /를 gdb
사용할 수 있지만 다음과 같습니다.argc
argv
- 프로그램 매개변수를 변경하기 전에 먼저 노출되기 때문에 이는 안전하지 않습니다.
- 이것은 꽤 오래된 학교이므로 작동하게 할 수 있다고 해도 이에 의존하는 것은 권장하지 않습니다.
소스 코드를 구하거나 공급업체에 문의하여 코드를 수정하는 것이 좋습니다. POSIX 운영 체제의 명령줄에서 비밀을 제공하는 것은 보안 작업과 호환되지 않습니다.
답변4
당신이 할 수 있는 일은
export SECRET=somesecretstuff
그런 다음, 당신이 C로 작성하고 있다고 가정하거나 ./program
(또는 다른 사람이 C로 작성하고 있으며 이를 변경하거나 개선할 수 있다고 가정) 다음을 사용하십시오.환경 가져오기(3)그 프로그램에서는 아마도
char* secret= getenv("SECRET");
그런 다음 동일한 쉘에서 실행하면 됩니다 export
. ./program
또는 환경 변수 이름을 전달할 수 있습니다(실행 ./program --secret-var=SECRET
등을 통해).
ps
비밀을 밝히진 않겠지만공정(5)여전히 많은 정보를 제공합니다(적어도 동일한 사용자의 다른 프로세스에 대해서는).
당신은 또한 볼 수 있습니다이것프로그램 매개변수를 전달하는 더 나은 방법을 고안하는 데 도움을 주십시오.
바라보다이 답변와일드카드와 쉘의 기능에 대한 더 나은 설명.
program
어쩌면 데이터를 얻는 다른 방법이 있을 수도 있습니다 .프로세스 간 통신일반 프로그램 인수보다 더 합리적입니다(민감한 정보를 다루는 경우 반드시 그렇게 해야 합니다). 해당 문서를 읽어보세요. 또는 프로그램을 남용할 수도 있습니다(프로그램은 비밀 데이터를 처리하기 위한 것이 아닙니다).
비밀 데이터를 숨기는 것은 정말 어렵습니다. 프로그램 매개변수를 통해 전달하는 것만으로는 충분하지 않습니다.