Sử dụng cURL với tên người dùng và mật khẩu?


468

Tôi muốn truy cập một URL yêu cầu tên người dùng / mật khẩu. Tôi muốn thử truy cập nó với curl. Ngay bây giờ tôi đang làm một cái gì đó như:

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

Tôi nhận được một lỗi. Tôi đoán tôi cần chỉ định tên người dùng và mật khẩu cùng với lệnh trên.

Làm thế nào tôi có thể làm điều đó?

Câu trả lời:


695

Sử dụng -ucờ để bao gồm tên người dùng và curl sẽ nhắc nhập mật khẩu:

curl -u username http://example.com

Bạn cũng có thể bao gồm mật khẩu trong lệnh, nhưng sau đó mật khẩu của bạn sẽ hiển thị trong lịch sử bash:

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

109
Lưu ý rằng nếu bạn làm điều này từ bảng điều khiển, mật khẩu sẽ vẫn còn trong lịch sử ... sai. Bạn nên chỉ định người dùng -u và CURL sẽ hỏi bạn mật khẩu ở chế độ không có tiếng vang.
Cristian Vrabie

25
@CristianVrabie Chính xác về mặt kỹ thuật, nhưng không chính xác nếu bạn đang chạy nó từ một tập lệnh tự động không cho phép nhắc nhở. Sẽ tò mò về một giải pháp cho vấn đề đó.
Ligemer

26
@OmarOthman nếu bạn đang chạy curl từ một tập lệnh, thông tin đăng nhập (rõ ràng) sẽ không kết thúc trong lịch sử của bạn, nhưng chúng sẽ hiển thị trong ps (1). sửa chữa:print -- '-u username:password' > somewhere && curl -K somewhere http://...
chỉ ai đó

7
Các biến môi trường @Jay sẽ được đánh giá trước khi thực hiện lệnh. Mật khẩu sẽ vẫn hiển thị trong đầu ra ps.
Robert Važan

8
Không tin vào quan điểm nhưng tôi tin rằng câu trả lời của tôi ( stackoverflow.com/a/27894407/758174 tức là sử dụng --netrc-file) an toàn hơn. Nó giữ mật khẩu ngoài lịch sử, ps, tập lệnh của bạn, v.v ... Đó là hình thức duy nhất tôi sử dụng trong tất cả các tập lệnh của mình và cho tất cả các cách sử dụng được xác thực curl.
Pierre D

255

An toàn hơn để làm:

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

... khi chuyển một chuỗi người dùng / mật khẩu đơn giản trên dòng lệnh, là một ý tưởng tồi.

Định dạng của tệp mật khẩu là (theo man curl):

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

Ghi chú:

  1. Tên máy không được bao gồm https://hoặc tương tự! Chỉ là tên máy chủ.
  2. Các từ ' machine', ' login' và ' password' chỉ là từ khóa; thông tin thực tế là những thứ sau những từ khóa đó.

10
Vâng, điều đó giữ mật khẩu ra khỏi danh sách quá trình và lịch sử lệnh. Cách tốt hơn để làm điều này, và chỉ một chút công việc :)
AC Capehart

8
Đây chắc chắn phải là câu trả lời được chấp nhận; mật khẩu trên dòng lệnh là một thực tế khủng khiếp. (Và đây là một thực tế được biết đến rộng rãi.)
ELLIOTTCABLE

6
Bạn cũng có thể sử dụng cờ -K <file>hoặc --config <file>để nhận cờ cuộn qua tệp hoặc đầu vào tiêu chuẩn. (Cảnh báo: không được nhầm lẫn với -khoặc --insecure!)
Rufflewind

2
Phương pháp curl này giữ thông tin đăng nhập khỏi lịch sử và trạng thái xử lý, nhưng để lại tên người dùng và mật khẩu trong tệp văn bản của tôi tạo một vectơ tấn công khác - tệ hơn là có thông tin trong tệp lịch sử: bash, ví dụ, tự động hạn chế quyền của tập tin lịch sử. Một vấn đề tương tự phát sinh nếu sử dụng các biến môi trường với ví dụ tập lệnh để đặt tên người dùng / mật khẩu. Nếu tập lệnh không an toàn, thì thông tin cũng không.
Steven dễ dàng thích thú

5
@SteventheEasilyAmuse Tôi không đồng ý, tốt hơn hết là sử dụng .netrctệp Cleartext với các quyền nghiêm ngặt phù hợp, vì vậy chỉ người dùng của bạn mới có thể đọc nó, hơn các cơ chế khác (ví dụ như dòng lệnh) cho phép người dùng khác đọc thông tin.
Ken Williams

77

Hoặc cùng một điều nhưng cú pháp khác nhau

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

1
Tôi sử dụng cú pháp đó, bởi vì có thể được sử dụng trong rất nhiều tình huống. Giống như từ một cmd Windows không có cURL và không có wGet, sử dụng start "" "http://username:password@api.somesite.com/test/blah?something=123". Nó có thể được phóng từ bất cứ đâu. Điều đó cũng áp dụng cho thông tin đăng nhập ftp; D
m3nda

9
Bạn cần mã hóa URL tên người dùng và mật khẩu để sử dụng các ký tự vui nhộn
diachedelic

2
Tôi biết rằng hầu hết mọi người biết không gửi mật khẩu (hoặc thậm chí tên người dùng) trong URL như ví dụ này vì nó rất dễ đánh hơi. Với những gì đã nói; Tôi không khuyến khích nó nhưng chỉ sử dụng khi bạn biết những gì bạn đang làm.
LosManos

1
Đây là suuuuuper cổ xưa và không nên được sử dụng. Đây là từ những ngày FTP: o
Qix - MONICA bị ngược đãi

2
Thật không may, điều này để lại mật khẩu hiển thị trong danh sách quá trình.
Đánh dấu Ribau

63

Bạn cũng có thể chỉ cần gửi tên người dùng bằng cách viết:

curl -u USERNAME http://server.example

Curl sau đó sẽ hỏi bạn mật khẩu và mật khẩu sẽ không hiển thị trên màn hình (hoặc nếu bạn cần sao chép / dán lệnh).


28

Để truyền mật khẩu một cách an toàn trong tập lệnh (nghĩa là ngăn nó hiển thị với ps auxf hoặc nhật ký), bạn có thể thực hiện với cờ -K- (đọc cấu hình từ stdin) và một di sản:

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

2
Cảm ơn bạn đã tham khảo --configtùy chọn (-K) ... có thể một giải pháp tốt hơn sẽ là đưa "--user user: password" vào một tệp và đơn giản là -K the filebạn chỉ có một bản sao của mật khẩu thay vì một bản sao trong mỗi tập lệnh . Dễ dàng hơn nhiều để bảo mật một tập tin duy nhất.
Chris Cogdon

1
Tùy chọn tương tự, trong đó chỉ có mật khẩu trong tệp : cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-. Tôi đã phải đặt -K-trước url cho bash macOS cũ, YMMV.
Đánh dấu Ribau

12

Thông thường lệnh CURL gọi là

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

nếu bạn không có bất kỳ mật khẩu nào hoặc muốn bỏ qua dấu nhắc lệnh để yêu cầu mật khẩu, hãy để trống phần mật khẩu.

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


1
LƯU Ý: Mật khẩu sẽ hiển thị trong lịch sử shell và danh sách quy trình.
Đánh dấu Ribau


8

Để cho mật khẩu ít nhất không bật lên trong .bash_history:

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

6
Trong trường hợp này, mật khẩu vẫn sẽ kết thúc trong danh sách quy trình, ví dụ như nó được hiển thị cho ai đó thực hiện ps auxw |grep curlđúng lúc. Tương tự, mật khẩu sẽ được ghi lại nếu chạy quasudo
Adam Katz

1
Với phương pháp này, mật khẩu sẽ xuất hiện trong một tệp (.password-file) có thể không an toàn hơn lịch sử .bash. Phần tốt về điều này, đó chỉ là mật khẩu - URL và tên người dùng không bị rò rỉ trong tệp .password-file.
Steven dễ dàng thích thú


6

Các câu trả lời khác đã đề nghị netrc chỉ định tên người dùng và mật khẩu, dựa trên những gì tôi đã đọc, tôi đồng ý. Dưới đây là một số chi tiết cú pháp:

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

Giống như các câu trả lời khác, tôi muốn nhấn mạnh sự cần thiết phải chú ý đến bảo mật liên quan đến câu hỏi này.

Mặc dù tôi không phải là một chuyên gia, tôi thấy những liên kết này sâu sắc:

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

Để tóm tắt:

Sử dụng các phiên bản được mã hóa của các giao thức (HTTPS vs HTTP) (FTPS vs FTP) có thể giúp tránh Rò rỉ Mạng.

Sử dụng netrc có thể giúp tránh rò rỉ dòng lệnh.

Để tiến thêm một bước, có vẻ như bạn cũng có thể mã hóa các tệp netrc bằng gpg

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

Với điều này, thông tin của bạn không phải là "nghỉ ngơi" (được lưu trữ) dưới dạng văn bản thuần túy.


5

Đơn giản và đơn giản là cách an toàn nhất sẽ là sử dụng các biến môi trường để lưu trữ / truy xuất thông tin đăng nhập của bạn. Do đó, một lệnh curl như:

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

Sau đó sẽ gọi api nghỉ ngơi của bạn và vượt qua WWW_Authenticationtiêu đề http với các giá trị được mã hóa Base64 của API_USERAPI_HASH. Việc này -Lkchỉ cho curl theo dõi chuyển hướng http 30x và sử dụng xử lý tls không an toàn (tức là bỏ qua lỗi ssl). Trong khi double --chỉ là bash cú pháp đường để dừng xử lý cờ dòng lệnh. Hơn nữa, cờ -b cookies.txt-c cookies.txtxử lý cookie bằng -bcách gửi cookie và -clưu trữ cookie cục bộ.

Hướng dẫn có nhiều ví dụ về các phương thức xác thực .


1
Hãy nhớ rằng việc sử dụng "-Lk" có thể mở ra cho bạn các cuộc tấn công trung gian (MITM), vì vậy hãy thận trọng với tùy chọn đó.
GuyPaddock

4
Điều này không hoạt động ... vì bash mở rộng các biến đó cho bạn, phần mở rộng xuất hiện trong danh sách quy trình.
Chris Cogdon


4

Cách an toàn nhất để chuyển thông tin đăng nhập để cuộn tròn là được nhắc chèn chúng. Đây là những gì xảy ra khi chuyển tên người dùng như được đề xuất trước đó ( -u USERNAME).

Nhưng nếu bạn không thể vượt qua tên người dùng theo cách đó thì sao? Ví dụ, tên người dùng có thể cần phải là một phần của url và chỉ mật khẩu là một phần của tải trọng json.

tl; dr: Đây là cách sử dụng curl an toàn trong trường hợp này:

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

read sẽ nhắc cho cả tên người dùng và mật khẩu từ dòng lệnh và lưu trữ các giá trị được gửi trong hai biến có thể được tham chiếu trong các lệnh tiếp theo và cuối cùng không được đặt.

Tôi sẽ giải thích lý do tại sao các giải pháp khác không lý tưởng.

Tại sao các biến môi trường không an toàn

  1. Không thể theo dõi chế độ truy cập và phơi bày nội dung của biến môi trường (ps -eww) vì môi trường hoàn toàn có sẵn cho một quy trình
  2. Thông thường các ứng dụng lấy toàn bộ môi trường và ghi nhật ký cho mục đích gỡ lỗi hoặc giám sát (đôi khi trên tệp nhật ký rõ ràng trên đĩa, đặc biệt là sau khi ứng dụng gặp sự cố)
  3. Các biến môi trường được truyền lại cho các tiến trình con (do đó phá vỡ nguyên tắc đặc quyền tối thiểu)
  4. Duy trì chúng là một vấn đề: các kỹ sư mới không biết họ đang ở đó và không nhận thức được các yêu cầu xung quanh họ - ví dụ: không chuyển chúng cho các quy trình phụ - vì chúng không được thi hành hoặc ghi lại.

Tại sao không an toàn khi nhập trực tiếp vào lệnh trên dòng lệnh Vì bí mật của bạn cuối cùng sẽ được hiển thị bởi bất kỳ người dùng nào khác đang chạy ps -auxvì liệt kê các lệnh được gửi cho mỗi quy trình hiện đang chạy. Cũng bởi vì secrte của bạn sau đó kết thúc trong lịch sử bash (một khi shell kết thúc).

Tại sao không an toàn khi đưa nó vào tệp cục bộ Hạn chế truy cập POSIX nghiêm ngặt trên tệp có thể giảm thiểu rủi ro trong kịch bản này. Tuy nhiên, nó vẫn là một tệp trên hệ thống tệp của bạn, không được mã hóa khi nghỉ ngơi.


2
Có vẻ như phương pháp này vẫn sẽ hiển thị mật khẩu trong danh sách quy trình?
Đánh dấu Ribau

4

Tôi có cùng nhu cầu trong bash (Ubuntu 16.04 LTS) và các lệnh được cung cấp trong các câu trả lời không hoạt động trong trường hợp của tôi. Tôi đã phải sử dụng:

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

Dấu ngoặc kép trong các -Fđối số chỉ cần thiết nếu bạn đang sử dụng các biến, do đó từ dòng lệnh ... -F 'username=myuser' ...sẽ ổn.

Thông báo bảo mật có liên quan: như ông Mark Ribau chỉ ra trong các bình luận, lệnh này hiển thị mật khẩu (biến $ PASS, được mở rộng) trong danh sách quy trình!


1
Hình như điều này vẫn hiển thị giá trị của $ PASS trong danh sách quy trình?
Đánh dấu Ribau

Vâng, không may là nó.
Marco

1

Nếu bạn đang sử dụng hệ thống khóa ứng dụng Gnome, một giải pháp tránh lộ mật khẩu trực tiếp là sử dụng gkeyring.py để trích xuất mật khẩu từ khóa:

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
LƯU Ý: Mật khẩu sẽ hiển thị trong danh sách quy trình. (Và lịch sử nếu đây không phải là một phần của kịch bản.)
Mark Ribau

1

Đây là RẤT NHIỀU so với OP yêu cầu, nhưng vì đây là kết quả hàng đầu để chuyển mật khẩu an toàn đến curl, tôi đang thêm các giải pháp này vào đây cho những người khác đến đây để tìm kiếm.


LƯU Ý: -sarg cho readlệnh không phải là POSIX và do đó không có sẵn ở mọi nơi, vì vậy nó sẽ không được sử dụng bên dưới. Chúng tôi sẽ sử dụng stty -echostty echothay vào đó.

LƯU Ý: Thay vào đó, tất cả các biến bash bên dưới có thể được khai báo là cục bộ nếu trong một hàm, thay vì bỏ đặt.

LƯU Ý: perlthường khá khả dụng trên tất cả các hệ thống mà tôi đã thử do nó phụ thuộc vào nhiều thứ, trong khi rubypythonkhông, vì vậy sử dụng perlở đây. Nếu bạn có thể đảm bảo ruby/ pythonnơi bạn đang làm điều này, bạn có thể thay thế perllệnh bằng tương đương của chúng.

LƯU Ý: Đã thử nghiệm trong bash3.2.57 trên macOS 10.14.4. Một số bản dịch nhỏ có thể được yêu cầu cho các shell / cài đặt khác.


An toàn nhắc người dùng nhập mật khẩu (có thể sử dụng lại) để chuyển sang cuộn tròn. Đặc biệt hữu ích nếu bạn cần gọi curl nhiều lần.

Đối với hệ vỏ hiện đại, nơi tích echohợp (kiểm tra qua 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

Đối với các vỏ cũ hơn, nơi echogiống như /bin/echo(nơi mà bất kỳ âm vang nào có thể được nhìn thấy trong danh sách quy trình):
PHIÊN BẢN NÀY KHÔNG THỂ SỬ DỤNG PASSWORD , thay vào đó, hãy xem phía dưới.

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



Nếu bạn tình cờ cần lưu trữ mật khẩu tạm thời vào một tệp, hãy sử dụng lại nó cho nhiều lệnh trước khi xóa nó (giả sử vì bạn đang sử dụng các hàm để sử dụng lại mã và không muốn lặp lại mã và không thể lặp lại mã truyền giá trị xung quanh thông qua tiếng vang). (Vâng, đây là một chút giả định trong hình thức này không phải là chức năng trong các thư viện khác nhau; tôi đã cố gắng giảm chúng xuống mã tối thiểu cần thiết để hiển thị nó.)

Khi echo được tích hợp sẵn (điều này đặc biệt được tạo ra, vì echo là một tích hợp, nhưng được cung cấp cho sự hoàn chỉnh):

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

Khi tiếng vang là một cái gì đó như /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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.