Używasz cURL z nazwą użytkownika i hasłem?


466

Chcę uzyskać dostęp do adresu URL, który wymaga nazwy użytkownika / hasła. Chciałbym spróbować uzyskać do niego dostęp za pomocą curl. Teraz robię coś takiego:

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

Dostaję błąd Chyba muszę podać nazwę użytkownika i hasło wraz z powyższym poleceniem.

Jak mogę to zrobić?

Odpowiedzi:


693

Użyj -uflagi, aby dołączyć nazwę użytkownika, a curl poprosi o podanie hasła:

curl -u username http://example.com

Możesz także dołączyć hasło do polecenia, ale wtedy twoje hasło będzie widoczne w historii bash:

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

109
Pamiętaj, że jeśli zrobisz to z konsoli, hasło pozostanie w historii, co jest ... złe. Powinieneś określić tylko -u użytkownik, a CURL poprosi o hasło w trybie bez echa.
— Cristian Vrabie,

25
@CristianVrabie Technicznie poprawne, ale niepoprawne, jeśli uruchamiasz go ze skryptu automatycznego, który nie zezwala na podpowiedzi. Byłby ciekawy rozwiązania tego problemu.
— Ligemer,

26
@OmarOthman, jeśli używasz curl ze skryptu, poświadczenia (oczywiście) nie znajdą się w twojej historii, ale będą widoczne w ps (1). fix:print -- '-u username:password' > somewhere && curl -K somewhere http://...
— tylko ktoś

7
@Jay Zmienne środowiskowe zostaną ocenione przed wykonaniem polecenia. Hasło będzie nadal widoczne na wyjściu ps.
— Robert Važan,

8
Nie chcę tu pochwalać, ale uważam, że moja odpowiedź ( stackoverflow.com/a/27894407/758174, tj. Używanie --netrc-file) jest bezpieczniejsza. Trzyma hasło poza historią, ps, twoim skryptem itp. Jest to jedyna forma, której używam we wszystkich moich skryptach i dla wszystkich uwierzytelnionych zastosowań curl.
— Pierre D,

252

Bezpieczniej jest robić:

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

... ponieważ przekazywanie zwykłego ciągu użytkownika / hasła w wierszu poleceń jest złym pomysłem.

Format pliku hasła to (zgodnie z man curl):

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

Uwaga:

  1. Nazwa maszyny nie może zawierać https://lub podobna! Tylko nazwa hosta.
  2. Słowa „ machine”, „ login” i „ password” to tylko słowa kluczowe; rzeczywiste informacje są po słowach kluczowych.

10
Tak, to utrzymuje hasło poza listą procesów i historią poleceń. Zdecydowanie lepszy sposób, aby to zrobić, i tylko trochę więcej pracy :)
— AC Capehart

8
To zdecydowanie powinna być zaakceptowana odpowiedź; hasła w wierszu poleceń są okropną praktyką. (I to jest powszechnie znany fakt.)
— ELLIOTTCABLE

6
Możesz także użyć flagi -K <file>lub --config <file>otrzymać flagi curl za pomocą pliku lub standardowego wejścia. (Ostrzeżenie: nie należy mylić z -klub --insecure!)
— Rufflewind 19.04.16

2
Ta metoda curl utrzymuje poświadczenia poza historią i statusem procesu, ale pozostawia nazwę użytkownika i hasło w postaci jawnego tekstu w pliku moje hasło, tworząc kolejny wektor ataku - gorszy niż posiadanie informacji w pliku historii: na przykład bash automatycznie ogranicza uprawnienia pliku historii. Podobny problem powstaje, gdy używa się zmiennych środowiskowych np. Ze skryptu do ustawiania nazwy użytkownika / hasła. Jeśli skrypt nie jest bezpieczny, nie ma też poświadczeń.
— Steven the Easy Amused

5
@SteventheEasilyAmused nie zgadzam się, że o wiele lepiej jest użyć tekstem jawnym .netrcplik z odpowiednio ścisłymi prawami, więc tylko Twój użytkownik może go czytać, niż inne mechanizmy (np args linii komend), które pozwalają innych użytkowników odczytać te informacje.
— Ken Williams

76

Lub ta sama rzecz, ale inna składnia

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

1
Używam tej składni, ponieważ może być używana w wielu innych sytuacjach. Jak z Windowsa cmd bez cURL i bez wGet, używając start "" "http://username:password@api.somesite.com/test/blah?something=123". Można go uruchomić z dowolnego miejsca. Dotyczy to także loginów ftp; D
— m3nda

8
Musisz użyć
— kodu

2
Wiem, że większość ludzi wie, aby nie wysyłać haseł (a nawet nazw użytkowników) w adresie URL, tak jak w tym przykładzie, ponieważ łatwo jest wąchać. Powiedziawszy to; Nie polecam tego, ale używam go tylko wtedy, gdy wiesz, co robisz.
— LosManos

1
Jest to archaiczny suuuuuper i nie należy go używać. To pochodzi z dni FTP: o
— Qix - MONICA BYŁ SZYBKO ZAKOŃCZONY

2
Niestety pozostawia to hasło widoczne na liście procesów.
— Mark Ribau,

63

Możesz również wysłać nazwę użytkownika, pisząc:

curl -u USERNAME http://server.example

Curl poprosi Cię o hasło, a hasło nie będzie widoczne na ekranie (lub jeśli będziesz musiał skopiować / wkleić polecenie).


27

Aby bezpiecznie przekazać hasło w skrypcie (tj. Zapobiec wyświetlaniu się go przy pomocy ps auxf lub logów), możesz to zrobić z flagą -K- (czytaj konfigurację ze standardowego wejścia) i heredoc:

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

2
Dzięki za odniesienie do --configopcji (-K) ... być może lepszym rozwiązaniem byłoby umieszczenie w pliku „--user user: password” i po prostu -K the fileposiadanie tylko jednej kopii hasła zamiast kopii w każdym skrypcie . Znacznie łatwiej zabezpieczyć pojedynczy plik.
— Chris Cogdon

1
Podobna opcja, gdzie tylko hasło znajduje się w pliku: cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-. Musiałem umieścić -K-przed adresem URL starego basha dla systemu macOS, YMMV.
— Mark Ribau,

12

Zwykle polecenie CURL określa się jako

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

jeśli nie masz hasła lub chcesz pominąć wiersz polecenia, aby poprosić o hasło, po prostu pozostaw pole hasła puste.

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


1
UWAGA: Hasło będzie widoczne w historii powłoki i liście procesów.
— Mark Ribau,


8

Aby hasło nie wyświetlało się w .bash_history:

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

6
W takim przypadku hasło nadal znajdzie się na liście procesów, np. Jest widoczne dla kogoś, kto robi to ps auxw |grep curlwe właściwym czasie. Podobnie hasło zostanie zarejestrowane, jeśli zostanie uruchomione przezsudo
— Adam Katz,

1
Dzięki tej metodzie hasło jest następnie obecne w pliku (.password-file), co może być bardziej niebezpieczne niż historia .bash. Zaletą tego jest to, że jest to tylko hasło - adres URL i nazwa użytkownika nie są wyciekane w pliku .password-file.
— Steven the Easy Amused


6

Inne odpowiedzi sugerują, że netrc określa nazwę użytkownika i hasło, w oparciu o to, co przeczytałem, zgadzam się. Oto kilka szczegółów składni:

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

Podobnie jak inne odpowiedzi, chciałbym podkreślić potrzebę zwrócenia uwagi na bezpieczeństwo w odniesieniu do tego pytania.

Chociaż nie jestem ekspertem, uważam te linki za wnikliwe:

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

Podsumowując:

Korzystanie z zaszyfrowanych wersji protokołów (HTTPS vs HTTP) (FTPS vs FTP) może pomóc uniknąć wycieku sieci.

Korzystanie z netrc może pomóc uniknąć wycieku z wiersza poleceń.

Aby pójść o krok dalej, wydaje się, że możesz także szyfrować pliki netrc za pomocą gpg

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

Dzięki temu twoje poświadczenia nie są „w spoczynku” (przechowywane) jako zwykły tekst.


5

Najprościej i najprościej najbezpieczniej byłoby użyć zmiennych środowiskowych do przechowywania / odzyskiwania danych uwierzytelniających. Zatem polecenie zwijania, takie jak:

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

Następnie wywołałby Twój spokojny interfejs API i przekazał WWW_Authenticationnagłówek http z zakodowanymi wartościami Base64 wartości API_USERi API_HASH. Po -Lkprostu mówi curl, aby śledził przekierowania http 30x i używał niepewnej obsługi tls (tj. Ignorował błędy ssl). Podczas gdy double --to tylko bash cukier składniowy, aby zatrzymać przetwarzanie flag wiersza poleceń. Ponadto flagi -b cookies.txti -c cookies.txtobsługują pliki cookie z -bwysyłaniem plików cookie i -clokalnym przechowywaniem plików cookie.

Podręcznik zawiera więcej przykładów metod uwierzytelniania .


1
Pamiętaj, że użycie „-Lk” może otworzyć cię na ataki typu man-in-the-middle (MITM), więc zachowaj ostrożność przy tej opcji.
— GuyPaddock,

4
To nie działa ... ponieważ bash rozszerza te zmienne, rozwinięcie pojawia się na liście procesów.
— Chris Cogdon


4

Najbezpieczniejszym sposobem przekazywania poświadczeń do zwijania jest monit o ich wprowadzenie. Tak się dzieje po przekazaniu nazwy użytkownika, jak sugerowano wcześniej ( -u USERNAME).

Ale co jeśli nie możesz przekazać nazwy użytkownika w ten sposób? Na przykład nazwa użytkownika może być częścią adresu URL, a tylko hasło należy do ładunku Json.

tl; dr: Oto jak bezpiecznie używać curl w tym przypadku:

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

read wyświetli monit o podanie zarówno nazwy użytkownika, jak i hasła z wiersza poleceń, i zapisze przesłane wartości w dwóch zmiennych, które mogą być odniesieniami w kolejnych poleceniach, a na końcu zostaną cofnięte.

Omówię, dlaczego inne rozwiązania nie są idealne.

Dlaczego zmienne środowiskowe są niebezpieczne?

  1. Tryb dostępu i ekspozycji zawartości zmiennej środowiskowej nie może być śledzony (ps -eww), ponieważ środowisko jest domyślnie dostępne dla procesu
  2. Często aplikacje przechwytują całe środowisko i logują je w celu debugowania lub monitorowania (czasami w postaci plików tekstowych na dysku, zwłaszcza po awarii aplikacji)
  3. Zmienne środowiskowe są przekazywane do procesów potomnych (dlatego łamanie zasady najmniejszych uprawnień)
  4. Utrzymanie ich jest problemem: nowi inżynierowie nie wiedzą, że tam są, i nie są świadomi wymagań wokół nich - np. Nie przekazują ich do podprocesów - ponieważ nie są one egzekwowane ani dokumentowane.

Dlaczego wpisywanie go bezpośrednio w wierszu polecenia jest niebezpieczne, ponieważ Twój sekret jest następnie widoczny dla każdego innego uruchomionego użytkownika, ps -auxponieważ zawiera listę poleceń przesłanych dla każdego aktualnie uruchomionego procesu. Także dlatego, że twoja secrte kończy się w historii bash (po zakończeniu powłoki).

Dlaczego umieszczenie go w pliku lokalnym jest niebezpieczne Ścisłe ograniczenie dostępu do pliku POSIX może zmniejszyć ryzyko w tym scenariuszu. Jest to jednak nadal plik w systemie plików, niezakodowany w spoczynku.


2
Wydaje się, że ta metoda nadal pokazywałaby hasło na liście procesów?
— Mark Ribau,

4

Miałem taką samą potrzebę w bash (Ubuntu 16.04 LTS), a polecenia podane w odpowiedziach nie działały w moim przypadku. Musiałem użyć:

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

Podwójne cudzysłowy w -Fargumentach są potrzebne tylko wtedy, gdy używasz zmiennych, więc z wiersza poleceń ... -F 'username=myuser' ...będzie dobrze.

Ważne informacje dotyczące bezpieczeństwa: jak wskazuje Mark Ribau w komentarzach, polecenie to pokazuje hasło (zmienna $ PASS, rozwinięta) na liście procesów!


1
Wygląda na to, że nadal pokazuje wartość $ PASS na liście procesów?
— Mark Ribau,

Tak, niestety tak jest.
— Marco

1

Jeśli korzystasz z systemu z aplikacją kluczy Gnome, rozwiązaniem, które pozwala uniknąć bezpośredniego ujawnienia hasła, jest użycie pliku gkeyring.py w celu wyodrębnienia hasła z klucza :

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
UWAGA: Hasło będzie widoczne na liście procesów. (I historia, jeśli nie jest to część scenariusza.)
— Mark Ribau,

1

To DUŻO więcej, niż wymagał PO, ale ponieważ jest to najlepszy wynik dla bezpiecznego przekazywania haseł curl, dodam te rozwiązania tutaj dla innych, którzy przyjeżdżają tutaj, szukając tego.


UWAGA: -sarg dla readpolecenia nie jest POSIX, więc nie jest dostępny wszędzie, więc nie będzie używany poniżej. Użyjemy stty -echoi stty echozamiast tego.

UWAGA: Wszystkie poniższe zmienne bash mogą być zadeklarowane jako lokalne, jeśli są w funkcji, a nie są rozbrojone.

UWAGA: perljest dość ogólnie dostępny na wszystkich systemach, które wypróbowałem, ponieważ jest zależny od wielu rzeczy, podczas gdy rubyi pythonnie są, więc używaj perltutaj. Jeśli możesz zagwarantować ruby/ pythongdzie to robisz, możesz zastąpić perlpolecenie ich odpowiednikiem.

UWAGA: Przetestowano w bash3.2.57 na macOS 10.14.4. Niektóre małe tłumaczenia mogą być wymagane w przypadku innych powłok / instalacji.


Bezpiecznie poproś użytkownika o podanie hasła (wielokrotnego użytku) w celu zwijania. Jest to szczególnie przydatne, jeśli trzeba wywoływać curl wiele razy.

W przypadku nowoczesnych powłok, w których echojest wbudowany (sprawdź przez 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

Dla starszych powłok, gdzie echojest coś takiego /bin/echo(gdzie cokolwiek echo można zobaczyć na liście procesów):
TA WERSJA NIE MOŻE PONOWNIE UŻYĆ HASŁA , patrz niżej.

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



Jeśli potrzebujesz tymczasowo zapisać hasło do pliku, użyj go ponownie dla wielu poleceń przed jego wyczyszczeniem (powiedz, ponieważ używasz funkcji do ponownego użycia kodu i nie chcesz powtarzać kodu i nie możesz przekazać wartość przez echo). (Tak, są nieco wymyślone, patrząc w tej formie, nie będąc funkcjami w różnych bibliotekach; Próbowałem zredukować je do minimalnego kodu potrzebnego do jego wyświetlenia.)

Gdy echo jest wbudowane (jest to szczególnie wymyślone, ponieważ echo jest wbudowane, ale zapewnia kompletność):

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

Kiedy echo jest jak /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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.