Làm thế nào để truyền mật khẩu cho một tiến trình con?


18

Truyền mật khẩu trên dòng lệnh (cho một tiến trình con bắt đầu từ chương trình của tôi) được biết là không an toàn (bởi vì người dùng khác có thể nhìn thấy nó ngay cả khi người dùng khác sử dụng lệnh ps). Thay vào đó, có thể vượt qua nó như một biến môi trường không?

Tôi có thể sử dụng cái gì khác để vượt qua nó? (Ngoại trừ biến môi trường) giải pháp đơn giản nhất dường như sử dụng đường ống, nhưng giải pháp đơn giản nhất này không dễ dàng.

Tôi lập trình ở Perl.


2
Tại sao nó không dễ dàng? Nó không phải là một ống riêng biệt / được đặt tên, chỉ cần stdin / out thông thường sẽ làm ... điều đó không nên gặp quá nhiều rắc rối trong bất kỳ ngôn ngữ nào. Bạn có thể đặt nó trong một tệp cấu hình đơn giản nếu bạn có thể chắc chắn rằng nó chỉ có thể đọc được bởi các quá trình quan tâm (khó hơn rất nhiều so với âm thanh).
frostschutz 16/07/2016

1
Nếu bạn không gọi exec ở trẻ, bạn vẫn có một bản sao của mật khẩu mà không cần phải làm gì cả.
James Youngman

Câu trả lời:


26

Đối số quy trình được hiển thị cho tất cả người dùng, nhưng môi trường chỉ hiển thị cho cùng một người dùng ( ít nhất là trên Linux và tôi nghĩ trên mọi biến thể unix hiện đại). Vì vậy, truyền mật khẩu thông qua một biến môi trường là an toàn. Nếu ai đó có thể đọc các biến môi trường của bạn, họ có thể thực thi các quy trình như bạn, vậy là trò chơi đã kết thúc.

Nội dung của môi trường có nguy cơ bị rò rỉ gián tiếp, ví dụ nếu bạn chạy psđể điều tra một cái gì đó và vô tình sao chép-dán kết quả bao gồm các biến môi trường bí mật ở nơi công cộng. Một rủi ro khác là bạn chuyển biến môi trường cho một chương trình không cần đến nó (bao gồm cả con của quá trình cần mật khẩu) và chương trình đó phơi bày các biến môi trường của nó vì nó không bảo mật chúng. Làm thế nào xấu những rủi ro rò rỉ thứ cấp phụ thuộc vào quá trình với mật khẩu làm gì (nó chạy trong bao lâu? Nó có chạy các quy trình con không?).

Dễ dàng hơn để đảm bảo rằng mật khẩu sẽ không bị rò rỉ một cách tình cờ bằng cách chuyển nó qua một kênh không được thiết kế để nghe lén, chẳng hạn như đường ống. Điều này là khá dễ dàng để làm ở phía gửi. Ví dụ: nếu bạn có mật khẩu trong biến shell, bạn chỉ có thể làm

echo "$password" | theprogram

nếu theprogrammong đợi mật khẩu trên đầu vào tiêu chuẩn của nó. Lưu ý rằng điều này là an toàn vì echolà một nội dung; nó sẽ không an toàn với một lệnh bên ngoài vì đối số sẽ được đưa ra trong psđầu ra. Một cách khác để đạt được hiệu quả tương tự là với một tài liệu ở đây:

theprogram <<EOF
$password
EOF

Một số chương trình yêu cầu mật khẩu có thể được yêu cầu đọc nó từ một bộ mô tả tệp cụ thể. Bạn có thể sử dụng một mô tả tập tin khác với đầu vào tiêu chuẩn nếu bạn cần đầu vào tiêu chuẩn cho một cái gì đó khác. Ví dụ gpg: với :

get-encrypted-data | gpg --passphrase-fd 3 --decrypt … 3<<EOP >decrypted-data
$password
EOP

Nếu chương trình không thể được yêu cầu đọc từ một bộ mô tả tệp nhưng có thể được yêu cầu đọc từ một tệp, bạn có thể yêu cầu nó đọc từ một bộ mô tả tệp bằng cách sử dụng tên tệp như `/ dev / fd / 3.

theprogram --password-from-file=/dev/fd/3 3<<EOF
$password
EOF

Trong ksh, bash hoặc zsh, bạn có thể làm điều này chính xác hơn thông qua quá trình thay thế.

theprogram --password-from-file=<(echo "$password")

Trên Solaris 9 trở lên, /usr/ucb/psđã được thiết lập gốc để có thể đọc và hiển thị các biến môi trường của các quá trình khác - điều này đã bị xóa trong Solaris 10, do đó, câu trả lời "mọi biến thể Unix hiện đại khác" ở trên áp dụng cho các bản phát hành Solaris từ năm 2005 trở về sau.
alanc

@alanc Thật vậy, tôi không coi Solaris <10 là hiện đại ngày nay. Solaris 9 gần như cũ như Windows XP!
Gilles 'SO- ngừng trở nên xấu xa'

Gilles: có ngày tôi có một thời gian khó khăn xem xét Solaris 10 hiện đại bây giờ mà Solaris 11 đã được ra hơn 5 năm, vì vậy tôi hoàn toàn hiểu và đồng ý, nhưng thật đáng buồn biết một số người vẫn chạy Solaris 8 hoặc 9.
alanc

10

Thay vì truyền mật khẩu trực tiếp thông qua một đối số hoặc một biến môi trường

#!/bin/bash
#filename: passwd_receiver
echo "The password is: $1"

sử dụng cùng một đối số hoặc biến môi trường để truyền tên tệp :

#!/bin/bash
#filename: passwd_receiver
echo "The password is: $(< "$1")"

Sau đó, bạn có thể vượt qua hoặc là một tập tin thường xuyên cho phép bảo vệ (mặc dù điều đó sẽ không bảo vệ bạn khỏi các tiến trình khác đang chạy dưới cùng một người dùng), hoặc /dev/stdinống nó trong (mà AFAIK sẽ bảo vệ bạn khỏi các tiến trình khác đang chạy dưới cùng một người dùng):

 echo PASSWORD | ./passwd_receiver /dev/stdin 

Nếu bạn sử dụng /dev/stdinở đây, nó bắt buộc phải là một đường ống . Nếu là thiết bị đầu cuối, các quy trình khác có thể đọc được dưới cùng một người dùng sẽ có thể đọc được.

Nếu bạn đã cần sử dụng của bạn /dev/stdincho một cái gì đó khác, bạn có thể sử dụng thay thế quy trình nếu bạn đang sử dụng vỏ hỗ trợ, về cơ bản tương đương với việc sử dụng đường ống:

./passwd_receiver <(echo PASSWORD)

Các ống được đặt tên (FIFO) có thể trông giống nhau, nhưng chúng có thể bị chặn.

Các giải pháp này cũng không hoàn toàn an toàn , nhưng chúng có thể đủ gần với điều kiện bạn không sử dụng hệ thống bị hạn chế bộ nhớ mà hoán đổi nhiều.

Lý tưởng nhất là bạn đọc các tệp này (ống cũng là một tệp) vào bộ nhớ được đánh dấu bằng mlock (2) là không thể cài đặt được, đây là điều mà các chương trình xử lý mật khẩu như gnupg thường làm.

Ghi chú:

  1. Truyền các số filedescriptor về mặt lý thuyết chỉ tốt như các tệp như chuyển các tên tệp, nhưng các tên tệp thực tế hơn, bởi vì <()cung cấp cho bạn một tên tệp, không phải là một số filedescriptor (và coprocs cung cấp cho bạn các filedescriptors được đánh dấu FD_CLOEXEC , khiến cho các fil filcript này không thể sử dụng được trong bối cảnh này).

  2. Nếu bạn đang sử dụng hệ thống Linux, nơi
    /proc/sys/kernel/yama/ptrace_scopeđược đặt thành 0AFAIK, thì không có cách tự bảo vệ bản thân khỏi các tiến trình khác chạy dưới cùng một người dùng (họ có thể sử dụng ptrace để gắn vào quy trình của bạn và đọc bộ nhớ của bạn)

  3. Nếu bạn chỉ cần giữ mật khẩu của mình tránh xa các quy trình chạy dưới những người dùng khác nhau (nonroot), thì các đối số, biến môi trường, đường ống và các tệp được bảo vệ quyền đều sẽ làm được.


7

Không, các biến môi trường cũng dễ dàng được đọc và rò rỉ cho các tiến trình con. vượt qua nó bằng một đường ống.


2
"Biến môi trường ... rò rỉ cho các tiến trình con" Đó là toàn bộ quan điểm của việc sử dụng biến môi trường. Chúng sẽ vô dụng nếu chúng không được thừa kế. "Các biến môi trường cũng dễ đọc", không có.
Patrick

2
Đọc biến, bỏ đặt nó. Nó không khó. Và bạn có thể sử dụng lập luận tương tự về đường ống. Nếu đường ống không được đọc từ đó, nó sẽ được chuyển sang tiến trình con và tiến trình con có thể đọc nó và lấy mật khẩu.
Patrick

1
@Patrick Các phương tiện được lập thành tài liệu để bỏ đặt các biến môi trường không nhất thiết phải xóa giá trị từ vị trí ps/proccó thể nhìn thấy nó.
zwol 16/07/2016

1
Có một số hệ thống cho phép bạn đọc các biến môi trường của các quá trình tùy ý? Tôi không nghĩ Linux cho phép các quy trình thuộc sở hữu của người khác và nếu bạn là người dùng giống nhau, bạn có thể chỉ cần ptrace()nhắm mục tiêu và đọc bộ nhớ của nó.
ilkkachu

5
Câu trả lời này là sai. Các biến môi trường không thể được đọc bởi người dùng khác.
Gilles 'SO- ngừng trở nên xấu xa

1

Nếu không có gì khác phù hợp, hãy xem xét dịch vụ Giữ khóa Linux (dây khóa nhân).

Bắt đầu tại: security / Keys.txt . Một trong những chuỗi khóa mặc định có thể được sao chép giữa các tiến trình cha và con.

Đây không phải là giải pháp đơn giản nhất, nhưng nó ở đó và dường như được duy trì và sử dụng (nó cũng liên quan đến lỗi Android năm ngoái.)

Tôi không biết về tình trạng "chính trị" của nó, nhưng tôi có nhu cầu tương tự, và bắt đầu làm việc với một ràng buộc Guile. Không đi qua hỗ trợ Perl trước đó.

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.