Menggunakan cURL dengan nama pengguna dan kata sandi?

468

Saya ingin mengakses URL yang memerlukan nama pengguna / kata sandi. Saya ingin mencoba mengaksesnya dengan ikal. Saat ini saya sedang melakukan sesuatu seperti:

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

Saya mendapatkan kesalahan. Saya kira saya perlu menentukan nama pengguna dan kata sandi bersama dengan perintah di atas.

Bagaimana saya bisa melakukan itu?

pengguna246114
sumber

Jawaban:

695

Gunakan -ubendera untuk memasukkan nama pengguna, dan curl akan meminta kata sandi:

curl -u username http://example.com

Anda juga dapat memasukkan kata sandi dalam perintah, tetapi kata sandi Anda akan terlihat di bash history:

curl -u username:password http://example.com
Finbarr
sumber
109
Perhatikan bahwa jika Anda melakukan ini dari konsol, kata sandi akan tetap berada dalam riwayat yang ... salah. Anda harus menentukan pengguna saja dan CURL akan meminta kata sandi dalam mode tanpa gema.
Cristian Vrabie
25
@CristianVrabie Secara teknis benar, tetapi salah jika Anda menjalankannya dari skrip otomatis yang tidak mengizinkan prompt. Ingin tahu tentang solusi untuk masalah itu.
Ligemer
26
@OmarOthman jika Anda menjalankan ikal dari skrip, kredensial (jelas) tidak akan berakhir dalam riwayat Anda, tetapi mereka akan terlihat dalam ps (1). memperbaiki:print -- '-u username:password' > somewhere && curl -K somewhere http://...
hanya seseorang
7
Variabel @Jay Environment akan dievaluasi sebelum eksekusi perintah. Kata sandi akan tetap terlihat di keluaran ps.
Robert Važan
8
Bukan untuk mempermasalahkan intinya tetapi saya yakin jawaban saya ( yaitu stackoverflow.com/a/27894407/758174 yaitu menggunakan --netrc-file) lebih aman. Itu membuat kata sandi dari sejarah, ps, skrip Anda, dll. Itu adalah satu-satunya bentuk yang saya gunakan di semua skrip saya dan untuk semua penggunaan terotentikasi curl.
Pierre D
255

Lebih aman untuk dilakukan:

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

... sebagai melewatkan string pengguna / kata sandi biasa pada baris perintah, adalah ide yang buruk.

Format file kata sandi adalah (sesuai per man curl):

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

catatan:

  1. Nama mesin tidak boleh termasuk https://atau serupa! Hanya nama hostnya.
  2. Kata-kata ' machine', ' login', dan ' password' hanyalah kata kunci; informasi aktual adalah barang setelah kata kunci tersebut.
Pierre D
sumber
10
Ya, itu menjaga kata sandi dari daftar proses dan sejarah perintah. Jauh lebih disukai cara untuk melakukan ini, dan hanya sedikit lebih banyak kerja :)
AC Capehart
8
Ini seharusnya menjadi jawaban yang diterima; kata sandi pada baris perintah adalah praktik yang mengerikan. (Dan ini adalah fakta yang dikenal luas.)
DAPAT DITERIMA
6
Anda juga dapat menggunakan flag -K <file>atau --config <file>untuk menerima flag curl melalui file atau input standar. (Peringatan: jangan bingung dengan -katau --insecure!)
Rufflewind
2
Metode curl ini menjaga kredensial dari riwayat dan status proses, tetapi membiarkan nama pengguna dan kata sandi dalam teks yang jelas di file my-password membuat vektor serangan lain - lebih buruk daripada memiliki info dalam file riwayat: bash, misalnya, secara otomatis membatasi izin dari file histori. Masalah serupa muncul jika menggunakan variabel lingkungan dengan misalnya skrip untuk mengatur nama pengguna / kata sandi. Jika skrip tidak aman, kredensial juga tidak.
Steven the Easily Amused
5
@SteventheEasilyAmused Saya tidak setuju, jauh lebih baik menggunakan .netrcfile cleartext dengan izin yang tepat, sehingga hanya pengguna Anda yang dapat membacanya, daripada mekanisme lain (mis. Argumen baris perintah) yang memungkinkan pengguna lain membaca informasi.
Ken Williams
77

Atau hal yang sama tetapi sintaks yang berbeda

curl http://username:[email protected]/test/blah?something=123
Daniel Magnusson
sumber
1
Saya menggunakan sintaks itu, karena dapat digunakan dalam banyak situasi. Suka dari Windows cmd tanpa cURL dan tanpa wGet, menggunakan start "" "http://username:[email protected]/test/blah?something=123". Itu bisa diluncurkan dari mana saja. Itu juga berlaku untuk login ftp; D
m3nda
9
Anda harus menyandikan URL nama pengguna & kata sandi untuk menggunakan karakter lucu
diachedelic
2
Saya tahu bahwa kebanyakan orang tahu untuk tidak mengirim kata sandi (atau bahkan nama pengguna) di URL seperti contoh ini karena mudah untuk mengendus. Dengan mengatakan itu; Saya tidak merekomendasikannya tetapi gunakan hanya ketika Anda tahu apa yang Anda lakukan.
LosManos
1
Ini suuuuuper kuno dan tidak boleh digunakan. Ini berasal dari hari-hari FTP: o
Qix - MONICA DISEBUTKAN
2
Sayangnya, ini membuat kata sandi terlihat di daftar proses.
Mark Ribau
63

Anda juga dapat mengirim nama pengguna dengan menulis:

curl -u USERNAME http://server.example

Curl kemudian akan meminta kata sandi Anda, dan kata sandi tersebut tidak akan terlihat di layar (atau jika Anda perlu menyalin / menempelkan perintah).

Kristian
sumber
28

Untuk meneruskan kata sandi dalam skrip (mis. Mencegahnya agar tidak muncul dengan ps aux atau log), Anda dapat melakukannya dengan flag -K (baca config from stdin) dan heredoc:

curl --url url -K- <<< "--user user:password"
Matt Fleming
sumber
2
Terima kasih atas referensi ke --configopsi (-K) ... mungkin solusi yang lebih baik adalah dengan memasukkan "--user user: password" ke dalam file dan sederhananya -K the filesehingga Anda hanya memiliki satu salinan kata sandi daripada salinan di setiap skrip . Jauh lebih mudah untuk mengamankan satu file.
Chris Cogdon
1
Pilihan yang sama, di mana hanya password adalah dalam file: cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-. Saya harus meletakkan -K-sebelum url untuk macOS bash lama, YMMV.
Mark Ribau
12

Biasanya perintah CURL disebut sebagai

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

jika Anda tidak memiliki kata sandi atau ingin melewatkan prompt perintah untuk meminta kata sandi, biarkan bagian kata sandi kosong.

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

Touseef Murtaza
sumber
1
CATATAN: Kata sandi akan terlihat dalam riwayat shell dan daftar proses.
Mark Ribau
10
curl -X GET -u username:password  {{ http://www.example.com/filename.txt }} -O
pengguna128364
sumber
1
CATATAN: Kata sandi akan terlihat dalam riwayat shell dan daftar proses.
Mark Ribau
8

Untuk membiarkan kata sandi paling tidak muncul di Anda .bash_history:

curl -u user:$(cat .password-file) http://example-domain.tld
sja
sumber
6
Dalam hal ini, kata sandi masih akan berakhir dalam daftar proses, misalnya terlihat oleh seseorang yang melakukan ps auxw |grep curlpada waktu yang tepat. Demikian pula, kata sandi akan dicatat jika dijalankan melaluisudo
Adam Katz
1
Dengan metode ini, kata sandi akan ditampilkan dalam file (.password-file) yang mungkin lebih tidak aman daripada riwayat .bash. Bagian yang baik tentang ini, adalah bahwa itu hanya kata sandi - URL dan nama pengguna tidak bocor dalam file .password.
Steven the Easily Amused
7

cukup mudah, lakukan di bawah ini:

curl -X GET/POST/PUT <URL> -u username:password
Preyas
sumber
Tidak ada persyaratan keamanan pada pertanyaan
Victor Polo De Gyves Montero
1
CATATAN: Kata sandi akan terlihat dalam riwayat shell dan daftar proses
Mark Ribau
6

Jawaban lain menyarankan netrc untuk menentukan nama pengguna dan kata sandi, berdasarkan apa yang saya baca, saya setuju. Berikut ini beberapa detail sintaks:

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

Seperti jawaban lain, saya ingin menekankan perlunya memperhatikan keamanan terkait pertanyaan ini.

Meskipun saya bukan ahli, saya menemukan tautan ini berwawasan luas:

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

Untuk meringkas:

Menggunakan versi terenkripsi protokol (HTTPS vs HTTP) (FTPS vs FTP) dapat membantu menghindari Kebocoran Jaringan.

Menggunakan netrc dapat membantu menghindari Kebocoran Baris Perintah.

Untuk melangkah lebih jauh, tampaknya Anda juga dapat mengenkripsi file netrc menggunakan gpg

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

Dengan ini kredensial Anda tidak "diam" (disimpan) sebagai teks biasa.

Brian Davis
sumber
5

Jelas dan sederhananya cara yang paling aman adalah dengan menggunakan variabel lingkungan untuk menyimpan / mengambil kredensial Anda. Dengan demikian perintah curl seperti:

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

Kemudian akan memanggil api tenang Anda dan lulus WWW_Authenticationheader http dengan nilai-nilai Base64 yang dikodekan dari API_USERdan API_HASH. The -Lkhanya memberitahu curl untuk mengikuti http 30x pengalihan dan menggunakan tls tidak aman penanganan (yaitu mengabaikan kesalahan ssl). Sedangkan --dobelnya hanya bash sintaksis gula untuk berhenti memproses flag command line. Lebih lanjut, -b cookies.txtdan -c cookies.txtflag menangani cookie dengan -bmengirimkan cookie dan -cmenyimpan cookie secara lokal.

Manual ini memiliki lebih banyak contoh metode otentikasi .

Dwight Spencer
sumber
1
Ingatlah bahwa menggunakan "-Lk" dapat membuka Anda terhadap serangan man-in-the-middle (MITM), jadi gunakan hati-hati dengan opsi itu.
GuyPaddock
4
Ini tidak berfungsi ... karena bash memperluas variabel-variabel itu untuk Anda, ekspansi muncul dalam daftar proses.
Chris Cogdon
4

Cara teraman untuk meneruskan kredensial ke curl adalah diminta memasukkannya. Inilah yang terjadi ketika melewati nama pengguna seperti yang disarankan sebelumnya ( -u USERNAME).

Tetapi bagaimana jika Anda tidak dapat melewatkan nama pengguna dengan cara itu? Misalnya nama pengguna mungkin perlu menjadi bagian dari url dan hanya kata sandi yang menjadi bagian dari payload json.

tl; dr: Ini adalah cara menggunakan curl dengan aman dalam hal ini:

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

read akan meminta nama pengguna dan kata sandi dari baris perintah, dan menyimpan nilai yang dikirimkan dalam dua variabel yang dapat menjadi referensi dalam perintah berikutnya dan akhirnya tidak disetel.

Saya akan menguraikan mengapa solusi lain tidak ideal.

Mengapa variabel lingkungan tidak aman

  1. Mode akses dan eksposur dari konten variabel lingkungan, tidak dapat dilacak (ps-baru) karena lingkungan secara implisit tersedia untuk suatu proses
  2. Seringkali aplikasi mengambil seluruh lingkungan dan mencatatnya untuk tujuan debugging atau pemantauan (kadang-kadang pada file log plaintext pada disk, terutama setelah aplikasi mogok)
  3. Variabel lingkungan diturunkan ke proses anak (karena itu melanggar prinsip privilege paling rendah)
  4. Menjaga mereka adalah masalah: insinyur baru tidak tahu mereka ada di sana, dan tidak mengetahui persyaratan di sekitar mereka - misalnya, tidak meneruskannya ke sub-proses - karena mereka tidak ditegakkan atau didokumentasikan.

Mengapa tidak aman untuk mengetikkannya ke perintah pada baris perintah secara langsung Karena rahasia Anda kemudian terlihat oleh pengguna lain yang berjalan ps -auxkarena daftar perintah yang dikirimkan untuk setiap proses yang sedang berjalan. Juga karena rahasia Anda kemudian berakhir dalam sejarah bash (setelah shell berakhir).

Mengapa tidak aman untuk memasukkannya dalam file lokal Pembatasan akses POSIX yang ketat pada file dapat mengurangi risiko dalam skenario ini. Namun, ini masih berupa file di sistem file Anda, tidak dienkripsi saat istirahat.

iammyr
sumber
2
Tampaknya metode ini masih akan menampilkan kata sandi dalam daftar proses?
Mark Ribau
4

Saya memiliki kebutuhan yang sama di bash (Ubuntu 16.04 LTS) dan perintah yang diberikan dalam jawaban gagal berfungsi dalam kasus saya. Saya harus menggunakan:

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

Kutipan ganda dalam -Fargumen hanya diperlukan jika Anda menggunakan variabel, sehingga dari baris perintah ... -F 'username=myuser' ...akan baik-baik saja.

Pemberitahuan Keamanan yang Relevan: seperti yang ditunjukkan oleh Mr. Mark Ribau dalam komentar, perintah ini menunjukkan kata sandi (variabel $ PASS, diperluas) di daftar proses!

Marco
sumber
1
Sepertinya ini masih menunjukkan nilai $ LULUS dalam daftar proses?
Mark Ribau
Ya, sayangnya itu terjadi.
Marco
1

Jika Anda menggunakan sistem yang memiliki aplikasi keyring Gnome, solusi yang menghindari pemaparan kata sandi secara langsung adalah dengan menggunakan gkeyring.py untuk mengekstrak kata sandi dari keyring:

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
Eliot Blennerhassett
sumber
1
CATATAN: Kata sandi akan terlihat dalam daftar proses. (Dan sejarah jika ini bukan bagian dari naskah.)
Mark Ribau
1

Ini JAUH lebih banyak daripada yang diminta OP, tetapi karena ini adalah hasil teratas untuk meneruskan kata sandi dengan aman curl, saya menambahkan solusi ini di sini untuk orang lain yang datang ke sini mencarinya.


CATATAN: -sarg untuk readperintah bukan POSIX, jadi tidak tersedia di mana-mana, jadi tidak akan digunakan di bawah ini. Kami akan menggunakan stty -echodan stty echosebagai gantinya.

CATATAN: Semua variabel bash di bawah ini dapat dinyatakan sebagai lokal jika dalam suatu fungsi, bukannya tidak disetel.

CATATAN: perlcukup umum tersedia pada semua sistem yang saya coba karena itu menjadi ketergantungan untuk banyak hal, sedangkan rubydan pythontidak, jadi gunakan di perlsini. Jika Anda dapat menjamin ruby/ di pythonmana Anda melakukan ini, Anda dapat mengganti perlperintah dengan padanannya.

CATATAN: Diuji dalam bash3.2.57 pada macOS 10.14.4. Beberapa terjemahan kecil mungkin diperlukan untuk shell / instalasi lain.


Aman meminta pengguna untuk kata sandi (dapat digunakan kembali) untuk diteruskan ke ikal. Sangat berguna jika Anda perlu memanggil ikal beberapa kali.

Untuk shell modern, di mana echobuilt-in (periksa 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

Untuk cangkang yang lebih tua, di mana echoada sesuatu seperti /bin/echo(di mana apa pun itu gema dapat dilihat dalam daftar proses):
VERSI INI TIDAK BISA MENGGUNAKAN KATA SANDI , sebaliknya melihat lebih rendah ke bawah.

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



Jika Anda perlu menyimpan kata sandi sementara untuk suatu file, untuk menggunakannya kembali untuk beberapa perintah sebelum menghapusnya (katakan karena Anda menggunakan fungsi untuk menggunakan kembali kode dan tidak ingin mengulang kode dan tidak bisa meneruskan nilai sekitar melalui gema). (Ya, ini sedikit dibuat-buat mencari dalam bentuk ini tidak menjadi fungsi di perpustakaan yang berbeda; Saya mencoba menguranginya ke kode minimum yang diperlukan untuk menunjukkannya.)

Ketika gema built-in (ini dibuat khusus, karena gema adalah built-in, tetapi disediakan untuk kelengkapan):

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

Ketika gema adalah sesuatu seperti /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
Mark Ribau
sumber