Cách an toàn để truyền mật khẩu cho> 1 chương trình trong bash


21

Tôi đang viết một bashkịch bản và cần hỏi người dùng mật khẩu của mình và chuyển nó đến openssl. Mặc dù opensslcó thể tự đọc mật khẩu, tôi cần hai lần chạy chương trình và không muốn hỏi người dùng hai lần. Đây là kịch bản:

cp file{,.old}
read -sp 'Enter password. ' PASS; echo
export PASS

# decode | edit | encode
openssl enc -d -aes-256-cbc -k "$PASS" -in file.old | \
  sed ... | openssl enc -e -aes-256-cbc -k "$PASS" -out file

unset PASS

Điều này không an toàn vì mật khẩu có sẵn dễ dàng bằng cách nhìn vào dòng lệnh; ai đó có thể đọc nó bằng cách sử dụng ps, ví dụ.

opensslcó thể đọc mật khẩu từ một biến môi trường, vì vậy tôi có thể thay thế -k "$PASS"bằng -pass env:PASS, nhưng nó vẫn không an toàn; các biến môi trường của bất kỳ quá trình có thể được đọc tự do (một lần nữa, pscó thể làm điều đó).

Vì vậy, làm thế nào tôi có thể chuyển mật khẩu một cách an toàn cho hai openssltrường hợp?


có thể sử dụng kết hợp GnuPG và PinEntry tại đây gnupg.org/related_software/pinentry/index.en.html
Nikhil Mulley

"Các biến môi trường của bất kỳ quá trình nào cũng có thể được đọc tự do" - điều này không hoàn toàn chính xác. psđọc môi trường của một tiến trình từ /proc/<pid>/environ, nhưng tệp này có 0600quyền, vì vậy chỉ có root và người dùng đang chạy tiến trình mới có thể đọc môi trường của tiến trình. Tôi muốn nói rằng điều đó khá an toàn.
Martin von Wittich

Câu trả lời:


16

Truyền mật khẩu trên một bộ mô tả tệp riêng biệt từ đầu vào (hai lần, một lần để mã hóa và một lần để giải mã). Không xuất khẩu PASSra môi trường.

read -sp 'Enter password. ' PASS
printf '%s\n' "$PASS" |
openssl enc -d -aes-256-cbc -kfile /dev/stdin -in file.old |
sed ... | {
  printf '%s\n' "$PASS" |
  openssl enc -e -aes-256-cbc -kfile /dev/stdin -in /dev/fd/3 -out file;
} 3<&0

Nếu hệ thống của bạn không có /dev/fd, bạn có thể sử dụng -passđối số để nói opensslđể đọc cụm mật khẩu từ một mô tả tệp mở.

printf '%s\n' "$PASS" | {
  printf '%s\n' "$PASS" |
  openssl enc -d -aes-256-cbc -pass fd:0 -in file.old |
  tr a-z A-Z | tee /dev/tty | {
  openssl enc -e -aes-256-cbc -pass fd:3 -out file; }
} 3<&0

Theo tôi hiểu từ câu trả lời khác của bạn , trong bashphiên bản với env:PASScũng an toàn.

printf '%s\n' "$PASS"không an toàn Ai đó có thể đọc dòng lệnh pschẳng hạn.

6
@ user14284 Không, và không. env:PASSkhông an toàn vì mật khẩu sẽ xuất hiện trong môi trường của opensslquy trình ( mật khẩu sẽ không xuất hiện trong môi trường của bashquy trình, nhưng điều đó là không đủ). Sử dụng printflà an toàn vì đó là một bash tích hợp.
Gilles 'SO- ngừng trở nên xấu xa'

echo là một bash được tích hợp sẵn, vậy một lệnh echo đơn giản có an toàn không? echo $PASS | openssl .... Nó sẽ không xuất hiện trong danh sách ps. Nơi duy nhất bạn có thể vượt qua sẽ là trong bộ nhớ quá trình bash. Tôi nghĩ ?
gaoithe

1
@gaoithe Có, echosẽ an toàn vì lý do tương tự printflà an toàn (và printfsẽ không an toàn trong vỏ không được tích hợp sẵn). Lý do tôi sử dụng printfvà không phải echoechocó thể mang lại dấu gạch chéo ngược (tùy thuộc vào các tùy chọn bash).
Gilles 'SO- ngừng trở thành ác quỷ'

8

Sử dụng Bash có thể được thực hiện mà không cần sử dụng bằng printf '%s\n' "$PASS"cách liên kết một chuỗi được gọi là ở đây với các bộ mô tả tệp bằng lệnh Bash dựng sẵn exec.

Để biết thêm thông tin, xem: Bảo mật mật khẩu tập lệnh Shell của các tham số dòng lệnh .

(

# sample code to edit password-protected file with openssl
# user should have to enter password only once
# password should not become visible using the ps command

echo hello > tmp.file

#env -i bash --norc   # clean up environment
set +o history
unset PASS || exit 1

read -sp 'Enter password. ' PASS; echo

# encrypt file and protect it by given password
exec 3<<<"$PASS"
openssl enc -e -aes-256-cbc -pass fd:3  -in tmp.file -out file

cp file{,.old}

# decode | edit | encode
exec 3<<<"$PASS" 4<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file.old | 
   sed 's/l/L/g' | 
   openssl enc -e -aes-256-cbc -pass fd:4 -out file

exec 3<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file

rm -P tmp.file file.old
unset PASS

)

1

Xin lỗi, câu trả lời trước đây của tôi là từ openssl man, không phải các tài liệu enc.

Giải pháp này không phải là một đường ống dẫn, nhưng tôi tin rằng giải pháp này ngăn mật khẩu hiển thị với ps.

Sử dụng một tài liệu ở đây, chỉ openssl nhìn thấy văn bản của mật khẩu.
Miễn là bạn chắc chắn loại bỏ tệp trung gian, không còn dấu vết. Có lẽ ai đó có thể giúp làm điều này trong một đường ống và loại bỏ các tập tin trung gian?

# cp file{,.old}  don't need this anymore since intermediate becomes same
read -sp 'Enter password. ' PASS; echo
#no need to export, env's are readable, as mentioned

# decode into intermediate file
openssl <<HERE 2>&1 >/dev/null
enc -d -aes-256-cbc -k "$PASS" -in file -out intermediate
HERE

# edit intermediate

# encode intermediate back into file
openssl <<HERE 2>&1 >/dev/null
enc -e -aes-256-cbc -k "$PASS" -in intermediate -out file 
HERE
unset PASS
rm -f intermediate

Đây sẽ là một câu trả lời tốt hơn nếu nó giải thích cách sử dụng công tắc. Điều đó không sai (ngoại trừ enclệnh không có -kncông tắc, ít nhất là trên các phiên bản hiện tại, nó -pass), nhưng không nhiều thông tin. (Downvote không phải của tôi.)
Gilles 'SO- ngừng trở thành ác quỷ'

Cảm ơn @Gilles, đã xem các tài liệu và thấy lỗi lầm của tôi, cập nhật câu trả lời với một cách tiếp cận khác.
bsd
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.