Vor einiger Zeit ist mir aufgefallen, dass Benutzernamen und Kennwörter, die curl
als Befehlszeilenargumente angegeben wurden, nicht in der ps
Ausgabe erscheinen (obwohl sie natürlich in Ihrem Bash-Verlauf erscheinen können).
Sie erscheinen ebenfalls nicht in /proc/PID/cmdline
.
(Die Länge des kombinierten Benutzernamen / Passwort-Arguments kann jedoch abgeleitet werden.)
Demonstration unten:
[root@localhost ~]# nc -l 80 &
[1] 3342
[root@localhost ~]# curl -u iamsam:samiam localhost &
[2] 3343
[root@localhost ~]# GET / HTTP/1.1
Authorization: Basic aWFtc2FtOnNhbWlhbQ==
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: localhost
Accept: */*
[1]+ Stopped nc -l 80
[root@localhost ~]# jobs
[1]+ Stopped nc -l 80
[2]- Running curl -u iamsam:samiam localhost &
[root@localhost ~]# ps -ef | grep curl
root 3343 3258 0 22:37 pts/1 00:00:00 curl -u localhost
root 3347 3258 0 22:38 pts/1 00:00:00 grep curl
[root@localhost ~]# od -xa /proc/3343/cmdline
0000000 7563 6c72 2d00 0075 2020 2020 2020 2020
c u r l nul - u nul sp sp sp sp sp sp sp sp
0000020 2020 2020 0020 6f6c 6163 686c 736f 0074
sp sp sp sp sp nul l o c a l h o s t nul
0000040
[root@localhost ~]#
Wie wird dieser Effekt erzielt? Liegt es irgendwo im Quellcode von curl
? (Ich nehme an, es ist eine curl
Funktion, keine ps
Funktion? Oder ist es eine Art Kernel-Funktion?)
Außerdem: Kann dies von außerhalb des Quellcodes einer ausführbaren Binärdatei erreicht werden? ZB durch die Verwendung von Shell-Befehlen, wahrscheinlich kombiniert mit Root-Berechtigungen?
Mit anderen Worten, könnte ich ein Argument , das ich an einen beliebigen Shell-Befehl weitergegeben habe, irgendwie davor verbergen, in /proc
oder in der ps
Ausgabe zu erscheinen (ich glaube dasselbe) ? (Ich denke, die Antwort auf diese Frage ist "Nein", aber es scheint sich zu lohnen, diese zusätzliche halbe Frage einzuschließen.)
environ
direkt, um auf Umgebungsvariablen zuzugreifen? - Fazit: Die Argumentliste befindet sich wie die Liste der Umgebungsvariablen im Lese- / Schreibspeicher des Benutzerprozesses und kann vom Benutzerprozess geändert werden.grep
Musters zu einer Zeichenklasse. ZBps -ef | grep '[c]url'
curl
passtcurl
aber[c]url
nicht übereinstimmt[c]url
. Wenn Sie weitere Informationen benötigen, stellen Sie eine neue Frage und ich würde gerne antworten.Antworten:
Wenn der Kernel einen Prozess ausführt, kopiert er die Befehlszeilenargumente in den zum Prozess gehörenden Lese- / Schreibspeicher (auf dem Stack, zumindest unter Linux). Der Prozess kann wie jeder andere Speicher in diesen Speicher schreiben. Wenn
ps
das Argument angezeigt wird, wird alles zurückgelesen, was an dieser bestimmten Adresse im Speicher des Prozesses gespeichert ist. Die meisten Programme behalten die ursprünglichen Argumente bei, aber es ist möglich, sie zu ändern. Die POSIX-Beschreibung vonps
gibt an, dassDer Grund dafür ist, dass die meisten Unix-Varianten die Änderung widerspiegeln, POSIX-Implementierungen auf anderen Betriebssystemen jedoch möglicherweise nicht.
Diese Funktion ist von begrenztem Nutzen, da der Prozess keine willkürlichen Änderungen vornehmen kann. Zumindest kann die Gesamtlänge der Argumente nicht erhöht werden, da das Programm die Position, an der die Argumente abgerufen werden, nicht ändern
ps
und den Bereich nicht über seine ursprüngliche Größe hinaus erweitern kann. Die Länge kann effektiv durch Setzen von Null-Bytes am Ende verringert werden, da Argumente C-terminierte Zeichenfolgen sind (dies ist nicht zu unterscheiden, wenn am Ende eine Reihe leerer Argumente stehen).Wenn Sie wirklich graben möchten, können Sie sich die Quelle einer Open-Source-Implementierung ansehen. Unter Linux ist die Quelle von
ps
nicht interessant. Sie sehen lediglich , dass sie die Befehlszeilenargumente aus dem proc-Dateisystem in liest . Der Code, der den Inhalt dieser Datei generiert, befindet sich im Kernel in in . Der Teil des Speichers des Prozesses (auf den mit zugegriffen wird ) geht von der Adresse zu ; Diese Adressen werden beim Start des Prozesses im Kernel aufgezeichnet und können danach nicht mehr geändert werden./proc/PID/cmdline
proc_pid_cmdline_read
fs/proc/base.c
access_remote_vm
mm->arg_start
mm->arg_end
Einige Daemons verwenden diese Fähigkeit, um ihren Status widerzuspiegeln, z. B. ändern sie ihren Status
argv[1]
in einen String wiestarting
oderavailable
oderexiting
. Viele Unix-Varianten haben dazu einesetproctitle
Funktion. Einige Programme verwenden diese Funktion, um vertrauliche Daten zu verbergen. Beachten Sie, dass dies von begrenztem Nutzen ist, da die Befehlszeilenargumente sichtbar sind, während der Prozess gestartet wird.Die meisten höheren Sprachen kopieren die Argumente in Zeichenfolgenobjekte und bieten keine Möglichkeit, den ursprünglichen Speicher zu ändern. Hier ist ein C-Programm, das diese Fähigkeit demonstriert, indem
argv
Elemente direkt geändert werden.Beispielausgabe:
Sie können
argv
Änderungen im Curl-Quellcode sehen. Curl definiert eine Funktion,cleanarg
mitsrc/tool_paramhlp.c
der ein Argument in alle Leerzeichen geändert wirdmemset
. Insrc/tool_getparam.c
dieser Funktion wird durch Schwärzen der einige Male, zum Beispiel verwendet , Benutzer - Passwort . Da die Funktion über das Parameter-Parsing aufgerufen wird, geschieht dies zu Beginn eines Curl-Aufrufs. Wenn Sie jedoch die Befehlszeile davor sichern, werden weiterhin alle Kennwörter angezeigt.Da die Argumente im eigenen Speicher des Prozesses gespeichert sind, können sie nur mit einem Debugger von außen geändert werden.
quelle
ps
Berichtsargumente aus diesem Teil des Kernelspeichers und ignorieren Sie alle Änderungen, die im Lese- / Schreibspeicher von Prozessen vorgenommen wurden? Aber (wenn ich es richtig verstanden habe?) Machen die meisten UNIX-Varianten nicht einmal die ersteren, so dass Sie eineps
Implementierung nicht ohne Kernel-Modifikationen machen können, da die ursprünglichen Daten nirgendwo aufbewahrt werden?argv
Einträgen geändert werden (Sie können ihn nicht festlegenargv[i]
, aber Sie können ihnargv[i][0]
durchschreibenargv[i][strlen(argv[i])]
), sodass sich eine Kopie im Speicher des Prozesses befinden muss.ps
Ausgabe sehen viele leere Argumente so aus, als gäbe es nichts, aber ja, es macht einen Unterschied, ob Sie überprüfen, wie viele Leerzeichen vorhanden sind, und von wo aus Sie direkter beobachten können/proc/PID/cmdline
.Die anderen Antworten beantworten die Frage allgemein. Um konkret zu antworten: " Wie wird dieser Effekt erzielt? Befindet er sich irgendwo im Quellcode von curl? ":
Im Argument-Parsing-Abschnitt des Curl-Quellcodes wird die
-u
Option wie folgt behandelt:Und die
cleanarg()
Funktion ist wie folgt definiert :Wir können also explizit sehen, dass das Argument Benutzername: Kennwort in
argv
mit Leerzeichen überschrieben wird, wie in den anderen Antworten beschrieben.quelle
cleanarg
explizit angibt, dass es das tut, was die Frage stellt!Ein Prozess kann seine Parameter nicht nur lesen, sondern auch schreiben.
Ich bin kein Entwickler, daher bin ich mit diesen Dingen nicht vertraut, aber es kann von außen mit einem Ansatz möglich sein, der dem Ändern von Umgebungsparametern ähnelt:
https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables
quelle
bash -c 'awk 1 /proc/$$/cmdline; set -- something; awk 1 /proc/$$/cmdline'
zeigt, dass sich das Festlegen der Parameter zumindest in der Shell davon unterscheidet, das zu ändern, was der Kernel als Prozessparameter sieht.