Verwenden Sie cURL mit einem Benutzernamen und einem Passwort?


467

Ich möchte auf eine URL zugreifen, für die ein Benutzername / Passwort erforderlich ist. Ich würde gerne versuchen, mit Curl darauf zuzugreifen. Im Moment mache ich so etwas wie:

curl http://api.somesite.com/test/blah?something=123

Ich bekomme eine Fehlermeldung. Ich denke, ich muss einen Benutzernamen und ein Passwort zusammen mit dem obigen Befehl angeben.

Wie kann ich das machen?

Antworten:


694

Verwenden Sie das -uFlag, um einen Benutzernamen anzugeben, und curl fordert Sie zur Eingabe eines Kennworts auf:

curl -u username http://example.com

Sie können das Passwort auch in den Befehl aufnehmen, aber dann wird Ihr Passwort im Bash-Verlauf angezeigt:

curl -u username:password http://example.com

109
Beachten Sie, dass wenn Sie dies über die Konsole tun, das Kennwort im Verlauf verbleibt, was ... falsch ist. Sie sollten nur -u user angeben und CURL fragt Sie im No-Echo-Modus nach dem Passwort.
Cristian Vrabie

25
@CristianVrabie Technisch korrekt, aber falsch, wenn Sie es über ein automatisiertes Skript ausführen, das keine Eingabeaufforderungen zulässt. Wäre neugierig auf eine Lösung für dieses Problem.
Ligemer

26
@OmarOthman Wenn Sie Curl über ein Skript ausführen, werden die Anmeldeinformationen (offensichtlich) nicht in Ihrem Verlauf angezeigt, sie werden jedoch in ps (1) angezeigt. Fix:print -- '-u username:password' > somewhere && curl -K somewhere http://...
Nur jemand

7
@ Jay Umgebungsvariablen werden vor der Befehlsausführung ausgewertet. Das Passwort ist in der ps-Ausgabe weiterhin sichtbar.
Robert Važan

8
Um den Punkt nicht näher zu erläutern, aber ich glaube, dass meine Antwort ( stackoverflow.com/a/27894407/758174, dh mit --netrc-file) sicherer ist. Es hält das Passwort aus dem Verlauf, ps, Ihrem Skript usw. heraus. Dies ist die einzige Form, die ich in allen meinen Skripten und für alle authentifizierten Verwendungen von verwende curl.
Pierre D

254

Es ist sicherer zu tun:

curl --netrc-file my-password-file http://example.com

... da das Übergeben einer einfachen Benutzer- / Kennwortzeichenfolge in der Befehlszeile eine schlechte Idee ist.

Das Format der Passwortdatei ist (gemäß man curl):

machine <example.com> login <username> password <password>

Hinweis:

  1. Maschinenname darf nicht enthalten https://oder ähnlich sein! Nur der Hostname.
  2. Die Wörter ' machine', ' login' und ' password' sind nur Schlüsselwörter; Die eigentliche Information ist das Zeug nach diesen Schlüsselwörtern.

10
Ja, das hält das Passwort aus der Prozessliste und dem Befehlsverlauf heraus. Weitaus vorzuziehen, um dies zu tun, und nur ein wenig mehr Arbeit :)
AC Capehart

8
Dies sollte definitiv die akzeptierte Antwort sein; Passwörter in der Kommandozeile sind eine schreckliche Praxis. (Und das ist eine weithin bekannte Tatsache.)
ELLIOTTCABLE

6
Sie können das Flag auch verwenden -K <file>oder --config <file>Curl-Flags per Datei- oder Standardeingabe empfangen. (Warnung: nicht zu verwechseln mit -koder --insecure!)
Rufflewind

2
Diese Curl-Methode hält Anmeldeinformationen aus dem Verlauf und dem Prozessstatus heraus, belässt jedoch Benutzername und Kennwort im Klartext in der my-password-Datei und erstellt einen weiteren Angriffsvektor - schlimmer als Informationen in der Verlaufsdatei: bash beispielsweise schränkt Berechtigungen automatisch ein der Verlaufsdatei. Ein ähnliches Problem tritt auf, wenn Umgebungsvariablen mit z. B. einem Skript zum Festlegen des Benutzernamens / Kennworts verwendet werden. Wenn das Skript nicht sicher ist, sind auch die Anmeldeinformationen nicht sicher.
Steven der leicht amüsierte

5
@SteventheEasilyAmused Ich bin anderer Meinung, es ist viel besser, eine Klartextdatei .netrcmit entsprechend strengen Berechtigungen zu verwenden, damit nur Ihr Benutzer sie lesen kann, als andere Mechanismen (z. B. Befehlszeilenargumente), mit denen andere Benutzer die Informationen lesen können.
Ken Williams

76

Oder das Gleiche, aber eine andere Syntax

curl http://username:password@api.somesite.com/test/blah?something=123

1
Ich benutze diese Syntax, weil sie in viel mehr Situationen verwendet werden kann. Wie von einem Windows-Cmd ohne cURL und ohne wGet start "" "http://username:password@api.somesite.com/test/blah?something=123". Es kann von überall gestartet werden.
Dies

8
Sie müssen den Benutzernamen und das Passwort
per

2
Ich weiß, dass die meisten Leute wissen, dass sie keine Passwörter (oder sogar Benutzernamen) in der URL wie in diesem Beispiel senden sollen, da es leicht zu schnüffeln ist. Nachdem das gesagt worden ist; Ich empfehle es nicht, sondern nur, wenn Sie wissen, was Sie tun.
LosManos

1
Dies ist suuuuuper archaisch und sollte nicht verwendet werden. Dies ist aus den FTP-Tagen: o
Qix - MONICA wurde am

2
Leider bleibt das Passwort in der Prozessliste sichtbar.
Mark Ribau

63

Sie können den Benutzernamen auch einfach schriftlich senden:

curl -u USERNAME http://server.example

Curl fragt Sie dann nach dem Passwort und das Passwort wird nicht auf dem Bildschirm angezeigt (oder wenn Sie den Befehl kopieren / einfügen müssen).


27

Um das Passwort in einem Skript sicher zu übergeben (dh zu verhindern, dass es mit ps auxf oder logs angezeigt wird), können Sie dies mit dem -K-Flag (Konfiguration von stdin lesen) und einem Heredoc tun:

curl --url url -K- <<< "--user user:password"

2
Vielen Dank für den Verweis auf die --configOption (-K) ... möglicherweise wäre eine bessere Lösung, "--user user: password" in eine Datei einzufügen und einfach -K the fileso, dass Sie nur eine Kopie des Passworts haben, statt einer Kopie in jedem Skript . Es ist viel einfacher, eine einzelne Datei zu sichern.
Chris Cogdon

1
Ähnliche Option, bei der nur das Passwort in der Datei enthalten ist : cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-. Ich musste -K-die URL für die alte MacOS-Bash YMMV vorlegen.
Mark Ribau

12

Normalerweise wird der Befehl CURL als bezeichnet

curl https://example.com\?param\=ParamValue -u USERNAME:PASSWORD

Wenn Sie kein Passwort haben oder die Eingabeaufforderung überspringen möchten, um ein Passwort anzufordern, lassen Sie einfach den Passwortabschnitt leer.

dh curl https://example.com\?param\=ParamValue -u USERNAME:


1
HINWEIS: Das Kennwort wird im Shell-Verlauf und in der Prozessliste angezeigt.
Mark Ribau

10
curl -X GET -u username:password  {{ http://www.example.com/filename.txt }} -O

1
HINWEIS: Das Kennwort wird im Shell-Verlauf und in der Prozessliste angezeigt.
Mark Ribau

8

Damit das Passwort nicht in Ihrem .bash_history:

curl -u user:$(cat .password-file) http://example-domain.tld

6
In diesem Fall landet das Passwort weiterhin in der Prozessliste, z. B. ist es für jemanden sichtbar, ps auxw |grep curlder es zur richtigen Zeit tut . Ebenso wird das Passwort protokolliert, wenn es übersudo
Adam Katz

1
Bei dieser Methode liegt das Kennwort dann in einer Datei (.password-file) vor, die möglicherweise unsicherer ist als der .bash-Verlauf. Das Gute daran ist, dass es nur das Passwort ist - die URL und der Benutzername werden nicht in der .password-Datei durchgesickert.
Steven der leicht amüsierte

7

ziemlich einfach, mach das folgende:

curl -X GET/POST/PUT <URL> -u username:password

Es gibt keine Sicherheitsanforderung für die Frage
Victor Polo De Gyves Montero

1
HINWEIS: Passwort würde in Shell-Verlauf und Prozessliste sichtbar sein
Mark Ribau

6

Andere Antworten haben netrc vorgeschlagen, Benutzername und Passwort anzugeben, basierend auf dem, was ich gelesen habe. Ich stimme zu. Hier sind einige Syntaxdetails:

https://ec.haxx.se/usingcurl-netrc.html

Wie bei anderen Antworten möchte ich die Notwendigkeit hervorheben, bei dieser Frage auf die Sicherheit zu achten.

Obwohl ich kein Experte bin, fand ich diese Links aufschlussreich:

https://ec.haxx.se/cmdline-passwords.html

Zusammenfassen:

Die Verwendung der verschlüsselten Versionen der Protokolle (HTTPS vs HTTP) (FTPS vs FTP) kann dazu beitragen, Netzwerklecks zu vermeiden.

Die Verwendung von netrc kann dazu beitragen, Befehlszeilenlecks zu vermeiden.

Um noch einen Schritt weiter zu gehen, können Sie die netrc-Dateien anscheinend auch mit gpg verschlüsseln

https://brandur.org/fragments/gpg-curl

Damit werden Ihre Anmeldeinformationen nicht als Klartext "in Ruhe" (gespeichert).


5

Der einfachste und einfachste Weg wäre, Umgebungsvariablen zum Speichern / Abrufen Ihrer Anmeldeinformationen zu verwenden. So ein Curl-Befehl wie:

curl -Lk -XGET -u "${API_USER}:${API_HASH}" -b cookies.txt -c cookies.txt -- "http://api.somesite.com/test/blah?something=123"

Würde dann Ihre erholsame API aufrufen und den http- WWW_AuthenticationHeader mit den Base64-codierten Werten von API_USERund übergeben API_HASH. Das -Lknur weist curl an, http 30x-Weiterleitungen zu folgen und unsichere tls-Behandlung zu verwenden (dh SSL-Fehler zu ignorieren). Während das Double --nur Bash-Syntax ist, stoppt Sugar die Verarbeitung von Befehlszeilenflags. Darüber hinaus behandeln die Flags -b cookies.txtund -c cookies.txtCookies mit dem -bSenden von Cookies und dem -clokalen Speichern von Cookies.

Das Handbuch enthält weitere Beispiele für Authentifizierungsmethoden .


1
Denken Sie daran, dass die Verwendung von "-Lk" Sie für Man-in-the-Middle-Angriffe (MITM) öffnen kann. Seien Sie daher bei dieser Option vorsichtig.
GuyPaddock

4
Dies funktioniert nicht ... da bash diese Variablen für Sie erweitert, wird die Erweiterung in der Prozessliste angezeigt.
Chris Cogdon


4

Der sicherste Weg, Anmeldeinformationen an Curl zu übergeben, besteht darin, sie zum Einfügen aufzufordern. Dies geschieht, wenn der Benutzername wie zuvor vorgeschlagen übergeben wird ( -u USERNAME).

Aber was ist, wenn Sie den Benutzernamen nicht so weitergeben können? Beispielsweise muss der Benutzername möglicherweise Teil der URL sein und nur das Kennwort muss Teil einer JSON-Nutzlast sein.

tl; dr: So verwenden Sie Curl in diesem Fall sicher:

read -p "Username: " U; read -sp "Password: " P; curl --request POST -d "{\"password\":\"${P}\"}" https://example.com/login/${U}; unset P U

read fordert in der Befehlszeile zur Eingabe von Benutzername und Kennwort auf und speichert die übermittelten Werte in zwei Variablen, die in nachfolgenden Befehlen referenziert und schließlich deaktiviert werden können.

Ich werde näher darauf eingehen, warum die anderen Lösungen nicht ideal sind.

Warum sind Umgebungsvariablen unsicher?

  1. Der Zugriffs- und Belichtungsmodus des Inhalts einer Umgebungsvariablen kann nicht verfolgt werden (ps -eww), da die Umgebung einem Prozess implizit zur Verfügung steht
  2. Oft greifen Apps auf die gesamte Umgebung zu und protokollieren sie zu Debugging- oder Überwachungszwecken (manchmal in Protokolldateien im Klartext auf der Festplatte, insbesondere nach dem Absturz einer App).
  3. Umgebungsvariablen werden an untergeordnete Prozesse weitergegeben (wodurch das Prinzip der geringsten Berechtigung verletzt wird).
  4. Ihre Wartung ist ein Problem: Neue Ingenieure wissen nicht, dass sie vorhanden sind, und kennen die Anforderungen in ihrer Umgebung nicht - z. B., um sie nicht an Unterprozesse weiterzugeben -, da sie nicht erzwungen oder dokumentiert werden.

Warum ist es unsicher, es direkt in einen Befehl in der Befehlszeile einzugeben, da Ihr Geheimnis dann für jeden anderen Benutzer sichtbar ist, der ausgeführt wird, ps -auxda hier die Befehle aufgelistet sind, die für jeden aktuell ausgeführten Prozess gesendet wurden. Auch weil Ihr Geheimnis dann in der Bash-Historie landet (sobald die Shell endet).

Warum ist es unsicher, es in eine lokale Datei aufzunehmen ? Eine strikte POSIX-Zugriffsbeschränkung für die Datei kann das Risiko in diesem Szenario verringern. Es handelt sich jedoch immer noch um eine Datei in Ihrem Dateisystem, die im Ruhezustand unverschlüsselt ist.


2
Es scheint, dass diese Methode immer noch das Passwort in der Prozessliste anzeigen würde?
Mark Ribau

4

Ich hatte das gleiche Bedürfnis in Bash (Ubuntu 16.04 LTS) und die in den Antworten angegebenen Befehle funktionierten in meinem Fall nicht. Ich musste verwenden:

curl -X POST -F 'username="$USER"' -F 'password="$PASS"' "http://api.somesite.com/test/blah?something=123"

Doppelte Anführungszeichen in den -FArgumenten sind nur erforderlich, wenn Sie Variablen verwenden. Daher ist die Verwendung über die Befehlszeile ... -F 'username=myuser' ...in Ordnung.

Relevanter Sicherheitshinweis: Wie Herr Mark Ribau in Kommentaren zeigt, zeigt dieser Befehl das Passwort (Variable $ PASS, erweitert) in der Prozessliste an!


1
Sieht so aus, als würde immer noch der Wert von $ PASS in der Prozessliste angezeigt?
Mark Ribau

Ja, leider schon.
Marco

1

Wenn Sie sich auf einem System mit Gnome-Schlüsselbund-App befinden, können Sie das Kennwort nicht mit gkeyring.py extrahieren, um das Kennwort aus dem Schlüsselbund zu extrahieren:

server=server.example.com
file=path/to/my/file
user=my_user_name
pass=$(gkeyring.py -k login -tnetwork -p user=$user,server=$server -1)

curl -u $user:$pass ftps://$server/$file -O

1
HINWEIS: Das Passwort wird in der Prozessliste angezeigt. (Und Geschichte, wenn dies nicht Teil eines Drehbuchs ist.)
Mark Ribau

1

Dies ist VIEL mehr als das OP verlangt, aber da dies ein Top-Ergebnis für die sichere Weitergabe von Passwörtern ist curl, füge ich diese Lösungen hier für andere hinzu, die hier ankommen und danach suchen.


HINWEIS: Der Befehl -sarg for readist nicht POSIX und daher nicht überall verfügbar. Daher wird er im Folgenden nicht verwendet. Wir werden stty -echound stty echostattdessen verwenden.

HINWEIS: Alle unten aufgeführten Bash-Variablen können stattdessen in einer Funktion als lokale deklariert werden, anstatt sie zu deaktivieren.

HINWEIS: perlist ziemlich allgemein auf allen Systemen verfügbar Ich habe versucht , weil es eine Abhängigkeit für viele Dinge zu sein, während rubyund pythonnicht ist, so verwendet perlhier. Wenn Sie können garantieren , ruby/ pythonwo Sie dies tun, können Sie die ersetzen perlBefehl mit ihren Äquivalent.

HINWEIS: Getestet in bash3.2.57 unter macOS 10.14.4. Für andere Shells / Installationen ist möglicherweise eine kleine Übersetzung erforderlich.


Fordern Sie einen Benutzer sicher auf, ein (wiederverwendbares) Kennwort an curl zu übergeben. Besonders nützlich, wenn Sie Curl mehrmals aufrufen müssen.

Wo echoist für moderne Muscheln ein eingebauter (Check via which echo):

url='https://example.com'
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
read pass
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input
echo ${pass} | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-
unset username
unset pass

Bei älteren Shells, wo echoist so etwas /bin/echo(wo was auch immer es in der Prozessliste
wiedergibt ): DIESE VERSION KANN DAS PASSWORT NICHT WIEDERVERWENDEN , siehe stattdessen weiter unten.

url='https://example.com'
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
perl -e '
    my $val=<STDIN>;
    chomp $val;
    print STDERR "\n";  # we need to move the line ahead, but not send a newline down the pipe
    print $val;
' | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-
stty echo   # re-enable echoing user input
unset username



Wenn Sie das Kennwort vorübergehend in einer Datei speichern müssen, um es vor dem Löschen für mehrere Befehle wiederzuverwenden (z. B. weil Sie Funktionen zur Wiederverwendung von Code verwenden und den Code nicht wiederholen möchten und nicht können Geben Sie den Wert per Echo weiter. (Ja, diese sind in dieser Form etwas erfunden und funktionieren nicht in verschiedenen Bibliotheken. Ich habe versucht, sie auf den Mindestcode zu reduzieren, der zum Anzeigen erforderlich ist.)

Wenn Echo eingebaut ist (dies ist besonders erfunden, da Echo eingebaut ist, aber der Vollständigkeit halber bereitgestellt wird):

url='https://example.com'
filepath="$(mktemp)"  # random path, only readable by current user
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
read pass
echo "${pass}" > "${filepath}"
unset pass
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input

cat "${filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-

rm "${filepath}"  # don't forget to delete the file when done!!
unset username

Wenn Echo so etwas wie /bin/echo:

url='https://example.com'
filepath="$(mktemp)"  # random path, only readable by current user
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
$(perl -e '
    my $val=<STDIN>;
    chomp $val;
    open(my $fh, ">", $ARGV[0]) or die "Could not open file \"$ARGV[0]\" $\!";
    print $fh $val;
    close $fh;
' "$filepath")
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input

cat "${filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-

rm "${filepath}"  # don't forget to delete the file when done!!
unset username
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.