Usi cURL con un nome utente e una password?


468

Voglio accedere a un URL che richiede un nome utente / password. Vorrei provare ad accedervi con il ricciolo. In questo momento sto facendo qualcosa del tipo:

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

Ho ricevuto un errore Suppongo di dover specificare un nome utente e una password insieme al comando sopra.

Come lo posso fare?

Risposte:


695

Usa il -uflag per includere un nome utente e curl richiederà una password:

curl -u username http://example.com

Puoi anche includere la password nel comando, ma la tua password sarà visibile nella cronologia di bash:

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

109
Nota che se lo fai dalla console la password rimarrà nella cronologia che è ... sbagliata. Dovresti specificare solo -u utente e CURL ti chiederà la password in modalità no-echo.
Cristian Vrabie,

25
@CristianVrabie Tecnicamente corretto, ma errato se lo si esegue da uno script automatico che non consente i prompt. Sarebbe curioso di trovare una soluzione a quel problema.
Ligemer,

26
@OmarOthman se stai eseguendo il ricciolo da uno script, le credenziali (ovviamente) non finiranno nella tua storia, ma saranno visibili in ps (1). correzione:print -- '-u username:password' > somewhere && curl -K somewhere http://...
solo qualcuno

7
Le variabili di ambiente @Jay verranno valutate prima dell'esecuzione del comando. La password sarà ancora visibile nell'output ps.
Robert Važan,

8
Non per confermare il punto, ma credo che la mia risposta ( stackoverflow.com/a/27894407/758174, ovvero l'utilizzo --netrc-file) sia più sicura. Mantiene la password fuori dalla cronologia, ps, il tuo script, ecc. Questa è l'unica forma che uso in tutti i miei script e per tutti gli usi autenticati di curl.
Pierre D,

255

È più sicuro fare:

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

... come passare una semplice stringa utente / password sulla riga di comando, è una cattiva idea.

Il formato del file della password è (come da man curl):

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

Nota:

  1. Il nome della macchina non deve includere https://o simile! Solo il nome host.
  2. Le parole ' machine', ' login' e ' password' sono solo parole chiave; le informazioni reali sono le cose dopo quelle parole chiave.

10
Sì, ciò mantiene la password fuori dall'elenco dei processi e dalla cronologia dei comandi. Modo molto preferibile per farlo, e solo un po 'più di lavoro :)
AC Capehart

8
Questa dovrebbe essere sicuramente la risposta accettata; le password sulla riga di comando sono una pratica orribile. (E questo è un fatto ampiamente noto.)
ELLIOTTCABLE

6
È inoltre possibile utilizzare il flag -K <file>o --config <file>per ricevere i flag di arricciatura tramite file o input standard. (Attenzione: da non confondere con -ko --insecure!)
Rufflewind

2
Questo metodo di arricciatura mantiene le credenziali fuori dalla cronologia e dallo stato del processo, ma lascia nome utente e password in chiaro nel file my-password creando un altro vettore di attacco - peggio che avere informazioni nel file cronologico: bash, ad esempio, limita automaticamente le autorizzazioni del file cronologico. Un problema simile si presenta se si utilizzano variabili di ambiente con ad esempio uno script per impostare nome utente / password. Se lo script non è sicuro, non lo sono nemmeno le credenziali.
Steven the Easy Amused

5
@SteventheEasilyAmused Non sono d'accordo, è molto meglio usare un .netrcfile di testo in chiaro con autorizzazioni appropriatamente rigorose, quindi solo il tuo utente può leggerlo, rispetto ad altri meccanismi (ad esempio argomenti della riga di comando) che consentono ad altri utenti di leggere le informazioni.
Ken Williams,

77

O la stessa cosa ma una sintassi diversa

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

1
Uso quella sintassi, perché può essere usata in molte altre situazioni. Come da un cmd di Windows senza cURL e senza wGet, usando start "" "http://username:password@api.somesite.com/test/blah?something=123". Può essere lanciato da qualsiasi luogo. Ciò vale anche per gli accessi ftp; D
m3nda

9
È necessario codificare l'URL con nome utente e password per utilizzare caratteri divertenti
diachedelic il

2
So che la maggior parte delle persone sa di non inviare password (o persino nomi utente) nell'URL come in questo esempio in quanto è facile da annusare. Detto questo; Non lo consiglio, ma lo uso solo quando sai cosa stai facendo.
LosManos,

1
Questo è suuuuper arcaico e non dovrebbe essere usato. Questo è dai giorni FTP: o
Qix - MONICA È STATA MISTREATA il

2
Sfortunatamente, questo lascia la password visibile nell'elenco dei processi.
Mark Ribau,

63

Puoi anche semplicemente inviare il nome utente scrivendo:

curl -u USERNAME http://server.example

Curl ti chiederà quindi la password e la password non sarà visibile sullo schermo (o se devi copiare / incollare il comando).


28

Per passare in modo sicuro la password in uno script (cioè impedirgli di apparire con ps auxf o log) puoi farlo con il flag -K- (leggi la configurazione da stdin) e un heredoc:

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

2
Grazie per il riferimento --configall'opzione (-K) ... forse una soluzione migliore sarebbe quella di inserire "--user user: password" in un file e semplicemente in -K the filemodo da avere una sola copia della password piuttosto che una copia in ogni script . Molto più facile proteggere un singolo file.
Chris Cogdon,

1
Un'opzione simile, in cui solo la password si trova nel file: cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-. Ho dovuto inserire -K-l'URL per il vecchio macOS bash, YMMV.
Mark Ribau,

12

Di solito il comando CURL si riferisce a come

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

se non si dispone di alcuna password o si desidera saltare il prompt dei comandi per richiedere la password, lasciare vuota la sezione della password.

vale a dire curl https://example.com\?param\=ParamValue -u USERNAME:


1
NOTA: la password sarebbe visibile nella cronologia della shell e nell'elenco dei processi.
Mark Ribau,

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

1
NOTA: la password sarebbe visibile nella cronologia della shell e nell'elenco dei processi.
Mark Ribau,

8

Per consentire alla password di non apparire nel tuo .bash_history:

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

6
In questo caso, la password finirà comunque nell'elenco dei processi, ad esempio è visibile a qualcuno che lo fa ps auxw |grep curlal momento giusto. Allo stesso modo, la password verrà registrata se eseguita tramitesudo
Adam Katz il

1
Con questo metodo la password è quindi presente in un file (.password-file) che potrebbe essere più insicuro della cronologia .bash. La parte buona di questo, è che è solo la password - l'URL e il nome utente non sono trapelati nel file .password.
Steven the Easy Amused

7

abbastanza facile, fai quanto segue:

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

Non c'è alcun requisito di sicurezza in merito alla domanda
Victor Polo De Gyves Montero,

1
NOTA: la password sarebbe visibile nella cronologia della shell e nell'elenco dei processi
Mark Ribau,

6

Altre risposte hanno suggerito netrc di specificare username e password, in base a ciò che ho letto, sono d'accordo. Ecco alcuni dettagli sulla sintassi:

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

Come altre risposte, vorrei sottolineare la necessità di prestare attenzione alla sicurezza riguardo a questa domanda.

Anche se non sono un esperto, ho trovato questi collegamenti penetranti:

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

Riassumere:

L'uso delle versioni crittografate dei protocolli (HTTPS vs HTTP) (FTPS vs FTP) può aiutare a evitare perdite di rete.

L'uso di netrc può aiutare a evitare perdite dalla riga di comando.

Per fare un ulteriore passo, sembra che puoi anche crittografare i file netrc usando gpg

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

Con questo le tue credenziali non sono "a riposo" (memorizzate) come testo normale.


5

Il modo più semplice e sicuro sarebbe usare le variabili di ambiente per archiviare / recuperare le tue credenziali. Quindi un comando di arricciatura come:

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

Chiamerebbe quindi l'API riposante e passerebbe l' WWW_Authenticationintestazione http con i valori codificati Base64 di API_USERe API_HASH. Il -Lkjust dice a curl di seguire i reindirizzamenti http 30x e di utilizzare la gestione tls non sicura (ovvero ignorare gli errori ssl). Mentre il doppio --è solo bash zucchero della sintassi per interrompere l'elaborazione dei flag della riga di comando. Inoltre, i flag -b cookies.txte -c cookies.txtgestiscono i cookie con l' -binvio di cookie e la -cmemorizzazione di cookie a livello locale.

Il manuale contiene altri esempi di metodi di autenticazione .


1
Ricorda che l'uso di "-Lk" può aprirti agli attacchi man-in-the-middle (MITM), quindi fai attenzione con quell'opzione.
GuyPaddock,

4
Questo non funziona ... poiché bash espande queste variabili per te, l'espansione appare nell'elenco dei processi.
Chris Cogdon,


4

Il modo più sicuro di passare le credenziali per arricciarle deve essere richiesto di inserirle. Questo è ciò che accade quando si passa il nome utente come suggerito in precedenza ( -u USERNAME).

E se non riesci a passare il nome utente in quel modo? Ad esempio, potrebbe essere necessario che il nome utente faccia parte dell'URL e che solo la password faccia parte di un payload json.

tl; dr: ecco come usare l'arricciatura in sicurezza in questo caso:

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

read richiederà sia il nome utente che la password dalla riga di comando e memorizzerà i valori inviati in due variabili che possono essere riferimenti nei comandi successivi e infine non impostati.

Spiegherò perché le altre soluzioni non sono ideali.

Perché le variabili d'ambiente non sono sicure

  1. La modalità di accesso ed esposizione del contenuto di una variabile d'ambiente non può essere tracciata (ps -eww) poiché l'ambiente è implicitamente disponibile per un processo
  2. Spesso le app catturano l'intero ambiente e lo registrano per scopi di debug o monitoraggio (a volte su file di registro in chiaro sul disco, specialmente dopo il crash di un'app)
  3. Le variabili di ambiente vengono trasmesse ai processi figlio (infrangendo quindi il principio del privilegio minimo)
  4. Il loro mantenimento è un problema: i nuovi ingegneri non sanno di essere lì e non sono consapevoli dei requisiti che li circondano - ad esempio, di non passarli a sottoprocessi - poiché non sono applicati o documentati.

Perché non è sicuro digitarlo direttamente in un comando dalla riga di comando Perché il tuo segreto finisce per essere visibile da qualsiasi altro utente in esecuzione ps -auxpoiché elenca i comandi inviati per ogni processo attualmente in esecuzione. Anche perché il tuo secrte finisce nella storia di bash (una volta terminata la shell).

Perché non è sicuro includerlo in un file locale Restrizioni di accesso POSIX rigorose al file possono mitigare il rischio in questo scenario. Tuttavia, è ancora un file sul tuo file system, non crittografato a riposo.


2
Sembra che questo metodo mostrerebbe ancora la password nell'elenco dei processi?
Mark Ribau,

4

Ho avuto la stessa necessità in bash (Ubuntu 16.04 LTS) e i comandi forniti nelle risposte non hanno funzionato nel mio caso. Ho dovuto usare:

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

Le virgolette doppie negli -Fargomenti sono necessarie solo se si utilizzano variabili, quindi dalla riga di comando ... -F 'username=myuser' ...andrà bene.

Avviso di sicurezza pertinente: come sottolinea Mark Ribau nei commenti questo comando mostra la password (variabile $ PASS, espansa) nella lista dei processi !


1
Sembra che questo mostri ancora il valore di $ PASS nell'elenco dei processi?
Mark Ribau,

Sì, sfortunatamente lo fa.
Marco,

1

Se utilizzi un sistema con l'app di portachiavi Gnome, una soluzione che evita di esporre direttamente la password consiste nell'utilizzare gkeyring.py per estrarre la password dal portachiavi:

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
NOTA: la password sarebbe visibile nell'elenco dei processi. (E la storia se questo non fa parte di una sceneggiatura.)
Mark Ribau,

1

Questo è MOLTO più di quanto richiesto dall'OP, ma poiché si tratta di un risultato eccezionale per il passaggio sicuro delle password curl, sto aggiungendo queste soluzioni qui per gli altri che arrivano qui a cercarlo.


NOTA: -sarg per readcomando non è POSIX, quindi non è disponibile ovunque, quindi non verrà utilizzato di seguito. Useremo stty -echoe stty echoinvece.

NOTA: tutte le variabili bash di seguito potrebbero invece essere dichiarate come locali se in una funzione, piuttosto che essere disabilitate.

NOTA: perlè abbastanza generalmente disponibile su tutti i sistemi che ho provato perché è una dipendenza per molte cose, mentre rubye pythonnon lo sono, quindi uso perlqui. Se puoi garantire ruby/ pythondove lo stai facendo, puoi sostituire il perlcomando con il loro equivalente.

NOTA: testato in bash3.2.57 su macOS 10.14.4. Potrebbe essere necessaria una piccola traduzione per altre shell / installazioni.


Richiedere in modo sicuro a un utente che una password (riutilizzabile) passi all'arricciatura. Particolarmente utile se è necessario chiamare più volte l'arricciatura.

Per le shell moderne, dove echoè integrato (controllare tramite 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

Per le shell più vecchie, dove si echotrova qualcosa di simile /bin/echo(dove qualsiasi cosa si trovi nella lista dei processi):
QUESTA VERSIONE NON PU RE RIUTILIZZARE LA PASSWORD , vedere invece in basso.

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



Se ti capita di dover archiviare temporaneamente la password in un file, riutilizzarla per più comandi prima di cancellarla (ad esempio perché stai utilizzando le funzioni per il riutilizzo del codice e non vuoi ripetere il codice e non puoi passare il valore in giro tramite eco). (Sì, questi sono un po 'forzati guardando in questa forma non essendo funzioni in diverse librerie; ho cercato di ridurli al codice minimo necessario per mostrarlo.)

Quando l'eco è incorporato (questo è particolarmente elaborato, poiché l'eco è incorporato, ma fornito per completezza):

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

Quando l'eco è qualcosa di simile /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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.