Wie hier erklärt, fügt Linux die Argumente eines Programms in den Datenraum des Programms ein und hält einen Zeiger auf den Anfang dieses Bereichs. Dies wird von ps
verwendet und so weiter, um die Programmargumente zu finden und anzuzeigen.
Da sich die Daten im Raum des Programms befinden, kann es sie manipulieren. Um dies zu tun, ohne das Programm selbst zu ändern, muss ein Shim mit einem main()
geladen werden Funktion, die vor dem eigentlichen Main des Programms aufgerufen wird. Dieses Shim kann die echten Argumente in ein neues Leerzeichen kopieren und dann die ursprünglichen Argumente überschreiben, sodass ps
werden nur Nullen angezeigt.
Der folgende C-Code tut dies.
/* 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);
}
Es ist nicht möglich, auf main()
einzugreifen , aber Sie können in die Standard-C-Bibliotheksfunktion __libc_start_main
eingreifen , die weiter main aufruft. Kompilieren Sie diese Datei shim_main.c
wie im Kommentar zu Beginn angegeben, und führen Sie es wie gezeigt aus. Ich habe eine printf
hinterlassen im Code, damit Sie überprüfen, ob es tatsächlich aufgerufen wird. Führen Sie beispielsweise
LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100
dann mach ps
und Sie werden sehen, dass ein leerer Befehl und Argumente angezeigt werden.
Es ist noch eine kurze Zeit, in der die Befehlsargumente sichtbar sein können. Um dies zu vermeiden, könnten Sie beispielsweise den Shim so ändern, dass er Ihr Geheimnis aus einer Datei liest und es den an das Programm übergebenen Argumenten hinzufügt.
-
Lesen Sie die Dokumentation der Befehlszeilenschnittstelle der betreffenden Anwendung. Es kann durchaus eine Option geben, das Geheimnis aus einer Datei anstatt direkt als Argument bereitzustellen.
-
Wenn dies fehlschlägt, reichen Sie einen Fehlerbericht gegen die Anwendung ein, mit der Begründung, dass es keinen sicheren Weg gibt, ihr ein Geheimnis zu übermitteln.
-
Sie können die Lösung in meuhs Antwort jederzeit vorsichtig (!) an Ihre spezifischen Bedürfnisse anpassen. Achten Sie besonders auf Stéphanes Kommentar und seine Folgemaßnahmen.
Wenn Sie Argumente an das Programm übergeben müssen, damit es funktioniert, werden Sie Pech haben, egal was Sie tun, wenn Sie hidepid
nicht verwenden können auf procfs.
Da Sie erwähnt haben, dass dies ein Bash-Skript ist, sollten Sie bereits den Quellcode zur Verfügung haben, da Bash keine kompilierte Sprache ist.
Andernfalls können Sie in der Lage sein, die Befehlszeile des Prozesses mit gdb
umzuschreiben oder ähnliches und mit argc
herumspielen /argv
sobald es schon gestartet ist, aber:
- Dies ist nicht sicher, da Sie Ihre Programmargumente immer noch anfangs offenlegen, bevor Sie sie ändern
- Das ist ziemlich hackig, selbst wenn Sie es zum Laufen bringen könnten, würde ich nicht empfehlen, sich darauf zu verlassen
Ich würde wirklich nur empfehlen, den Quellcode zu besorgen oder mit dem Anbieter zu sprechen, um den Code ändern zu lassen. Das Bereitstellen von Geheimnissen auf der Befehlszeile in einem POSIX-Betriebssystem ist mit dem sicheren Betrieb nicht kompatibel.