it-swarm.com.de

Wie schützt Curl ein Passwort vor dem Erscheinen in der ps-Ausgabe?

Ich habe vor einiger Zeit bemerkt, dass Benutzernamen und Passwörter, die curl als Befehlszeilenargumente zugewiesen wurden, nicht in der Ausgabe von ps angezeigt werden (obwohl sie natürlich in Ihrem Bash-Verlauf erscheinen können).

Sie erscheinen ebenfalls nicht in /proc/PID/cmdline.

(Die Länge des kombinierten Argumentes für Benutzername/Passwort kann jedoch abgeleitet werden.)

Demonstration unten:

[[email protected] ~]# nc -l 80 &
[1] 3342
[[email protected] ~]# curl -u iamsam:samiam localhost &
[2] 3343
[[email protected] ~]# 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
[[email protected] ~]# jobs
[1]+  Stopped                 nc -l 80
[2]-  Running                 curl -u iamsam:samiam localhost &
[[email protected] ~]# 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
[[email protected] ~]# 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
[[email protected] ~]# 

Wie wird dieser Effekt erzielt? Befindet er sich irgendwo im Quellcode von curl? (Ich nehme an, es ist eine curl Funktion, keine ps Funktion? Oder ist es eine Art Kernelfunktion?)


Außerdem: kann dies von außerhalb des Quellcodes einer ausführbaren Binärdatei erreicht werden? z. mithilfe von Shell-Befehlen, wahrscheinlich kombiniert mit Root-Berechtigungen?

Mit anderen Worten, könnte ich irgendwie ein Argument davon abhalten, in der Ausgabe von /proc Oder ps zu erscheinen (dasselbe, glaube ich), das ich an eine beliebige beliebige Shell-Befehl? (Ich würde vermuten, dass die Antwort darauf "Nein" ist, aber es scheint sich zu lohnen, diese zusätzliche halbe Frage aufzunehmen.)

71
Wildcard

Wenn der Kernel einen Prozess ausführt, kopiert er die Befehlszeilenargumente in den zum Prozess gehörenden Lese-/Schreibspeicher (auf dem Stapel, zumindest unter Linux). Der Prozess kann wie jeder andere Speicher in diesen Speicher schreiben. Wenn ps das Argument anzeigt, liest es alles zurück, 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 von ps besagt dies

Es ist nicht angegeben, ob die dargestellte Zeichenfolge eine Version der Argumentliste ist, wie sie beim Start an den Befehl übergeben wurde, oder eine Version der Argumente, wie sie möglicherweise von der Anwendung geändert wurden. Anwendungen können nicht davon abhängen, dass sie ihre Argumentliste ändern können und dass sich diese Änderung in der Ausgabe von ps widerspiegelt.

Der Grund dafür ist, dass die meisten Unix-Varianten die Änderung widerspiegeln, POSIX-Implementierungen auf anderen Betriebssystemtypen jedoch möglicherweise nicht.

Diese Funktion ist nur begrenzt verwendbar, 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 ps die Argumente abruft, nicht ändern kann und den Bereich nicht über seine ursprüngliche Größe hinaus erweitern kann. Die Länge kann effektiv verringert werden, indem am Ende Null-Bytes eingefügt werden, da Argumente nullterminierte Zeichenfolgen im C-Stil sind (dies ist nicht von einer Reihe leerer Argumente am Ende zu unterscheiden).

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 werden nur sehen, dass sie die Befehlszeilenargumente aus dem proc filesystem in /proc/PID/cmdline Liest. . Der Code, der den Inhalt dieser Datei generiert, befindet sich im Kernel in proc_pid_cmdline_read In fs/proc/base.c . Der Teil des Prozessspeichers (Zugriff mit access_remote_vm) Wechselt von der Adresse mm->arg_start Zu mm->arg_end. Diese Adressen werden zu Beginn des Prozesses im Kernel aufgezeichnet und können danach nicht mehr geändert werden.

Einige Dämonen verwenden diese Fähigkeit, um ihren Status widerzuspiegeln, z. Sie ändern ihren argv[1] in einen String wie starting oder available oder exiting. Viele Unix-Varianten haben dazu die Funktion setproctitle . Einige Programme verwenden diese Funktion, um vertrauliche Daten auszublenden. Beachten Sie, dass dies nur begrenzt von Nutzen ist, da die Befehlszeilenargumente beim Starten des Prozesses sichtbar sind.

Die meisten Hochsprachen 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.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int i;
    system("ps -p $PPID -o args=");
    for (i = 0; i < argc; i++)
    {
        memset(argv[i], '0' + (i % 10), strlen(argv[i]));
    }
    system("ps -p $PPID -o args=");
    return 0;
}

Beispielausgabe:

./a.out hello world
0000000 11111 22222

Sie können die Modifikation argv im Curl-Quellcode sehen. Curl definiert ein Funktion cleanarg in src/tool_paramhlp.c , mit dem ein Argument mit memset in alle Leerzeichen geändert wird. In src/tool_getparam.c Wird diese Funktion einige Male verwendet, z. durch Redigieren des Benutzerkennworts . Da die Funktion vom Parameter-Parsing aufgerufen wird, geschieht dies früh in einem Curl-Aufruf. Wenn Sie jedoch die Befehlszeile ausgeben, bevor dies geschieht, werden weiterhin alle Kennwörter angezeigt.

Da die Argumente im eigenen Speicher des Prozesses gespeichert sind, können sie nur mithilfe eines Debuggers von außen geändert werden.

Die anderen Antworten beantworten die Frage allgemein gut. Um spezifisch zu antworten " Wie wird dieser Effekt erreicht ? Befindet er sich irgendwo im Quellcode von curl ? ":

Im Abschnitt zum Parsen von Argumenten des Curl-Quellcodes wird die Option -u Wie folgt behandelt:

    case 'u':
      /* user:password  */
      GetStr(&config->userpwd, nextarg);
      cleanarg(nextarg);
      break;

Und die Funktion cleanarg() ist definiert wie folgt:

void cleanarg(char *str)
{
#ifdef HAVE_WRITABLE_ARGV
  /* now that GetStr has copied the contents of nextarg, wipe the next
   * argument out so that the username:password isn't displayed in the
   * system process list */
  if(str) {
    size_t len = strlen(str);
    memset(str, ' ', len);
  }
#else
  (void)str;
#endif
}

Wir können also explizit sehen, dass das Argument Benutzername: Passwort in argv mit Leerzeichen überschrieben wird, wie in den anderen Antworten beschrieben.

14
Digital Trauma

Ein Prozess kann seine Parameter nicht nur lesen, sondern auch schreiben.

Ich bin kein Entwickler, daher bin ich mit diesem Zeug nicht vertraut, aber es kann von außen mit einem Ansatz möglich sein, der der Änderung von Umgebungsparametern ähnelt:

https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables

3
Hauke Laging