วิธีที่ปลอดภัยในการส่งรหัสผ่านสำหรับ> 1 โปรแกรมใน bash


21

ฉันเขียนสคริปต์และจำเป็นที่จะต้องขอให้ผู้ใช้รหัสผ่านของเขาและผ่านไปbash opensslในขณะที่opensslสามารถอ่านรหัสผ่านได้ฉันต้องการโปรแกรมสองรันและไม่ต้องการถามผู้ใช้สองครั้ง นี่คือสคริปต์:

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

รหัสผ่านนี้ไม่ปลอดภัยเนื่องจากสามารถดูรหัสผ่านได้อย่างง่ายดายโดยดูที่บรรทัดคำสั่ง บางคนสามารถอ่านโดยใช้psตัวอย่างเช่น

opensslสามารถอ่านรหัสผ่านจากตัวแปรสภาพแวดล้อมดังนั้นฉันสามารถแทนที่-k "$PASS"ด้วย-pass env:PASSแต่ก็ยังไม่ปลอดภัย ตัวแปรสภาพแวดล้อมของกระบวนการใด ๆ สามารถอ่านได้อย่างอิสระ ( psสามารถทำได้อีกครั้ง)

ดังนั้นฉันจะส่งรหัสผ่านไปยังสองopensslอินสแตนซ์ได้อย่างปลอดภัยได้อย่างไร


การรวมกันของ GnuPG และ PinEntry สามารถใช้ได้ที่นี่gnupg.org/related_software/pinentry/index.en.html
Nikhil Mulley

"ตัวแปรสภาพแวดล้อมของกระบวนการใด ๆ สามารถอ่านได้อย่างอิสระ" - สิ่งนี้ไม่ถูกต้องทั้งหมด psอ่านสภาพแวดล้อมของกระบวนการ/proc/<pid>/environแต่ไฟล์นี้มี0600สิทธิ์ใช้งานดังนั้นเฉพาะผู้ใช้รูทและผู้ใช้ที่ทำงานในกระบวนการเท่านั้นที่สามารถอ่านสภาพแวดล้อมของกระบวนการได้ ฉันจะบอกว่ามันค่อนข้างปลอดภัย
Martin von Wittich

คำตอบ:


16

ส่งรหัสผ่านไปที่ file descriptor แยกต่างหากจากอินพุต (สองครั้งหนึ่งครั้งสำหรับการเข้ารหัสและอีกครั้งสำหรับการถอดรหัส) อย่าส่งออกPASSไปยังสภาพแวดล้อม

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

หากระบบของคุณไม่มี/dev/fdคุณสามารถใช้-passอาร์กิวเมนต์เพื่อบอกopensslให้อ่านวลีรหัสผ่านจากตัวอธิบายไฟล์ที่เปิดอยู่

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

ตามที่ฉันเข้าใจจากคำตอบของคุณในbashรุ่นที่มีenv:PASSความปลอดภัยเช่นกัน

printf '%s\n' "$PASS"ไม่ปลอดภัย บางคนสามารถอ่านบรรทัดคำสั่งด้วยpsเช่น

6
@ user14284 ไม่และไม่ env:PASSไม่ปลอดภัยเนื่องจากรหัสผ่านจะปรากฏในสภาพแวดล้อมของopensslกระบวนการ (จะไม่ปรากฏในสภาพแวดล้อมของbashกระบวนการ แต่ไม่เพียงพอ) การใช้printfมีความปลอดภัยเพราะเป็นทุบตีในตัว
Gilles 'SO- หยุดความชั่วร้าย'

echo เป็น bash ในตัวดังนั้นคำสั่ง echo อย่างง่ายจะไม่ปลอดภัยหรือไม่? echo $PASS | openssl .... มันจะไม่ปรากฏในรายชื่อ ps ที่เดียวที่คุณสามารถผ่านได้คือหน่วยความจำในกระบวนการทุบตี ฉันคิด ?
gaoithe

1
@gaoithe ใช่echoจะปลอดภัยด้วยเหตุผลเดียวกันprintfคือปลอดภัย (และprintfจะไม่ปลอดภัยในเชลล์ที่ไม่ได้สร้างขึ้นมา) เหตุผลที่ฉันใช้printfและไม่ใช่echoว่าechoอาจทำให้แบ็กสแลชหายไป (ขึ้นอยู่กับตัวเลือก bash)
Gilles 'หยุดความชั่วร้าย'

8

การใช้ Bash สามารถทำได้โดยไม่ต้องใช้printf '%s\n' "$PASS"โดยการเชื่อมโยงสตริงที่นี่กับตัวอธิบายไฟล์โดยใช้execคำสั่งBash builtin

สำหรับข้อมูลเพิ่มเติมโปรดดูที่: เชลล์รักษาความปลอดภัยรหัสผ่านสคริปต์ของพารามิเตอร์บรรทัดคำสั่ง

(

# 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

ขออภัยคำตอบก่อนหน้าของฉันมาจากคน openssl ไม่ใช่เอกสาร openssl enc

โซลูชันนี้ไม่ใช่ไปป์ไลน์ แต่ฉันเชื่อว่าโซลูชันนี้จะป้องกันไม่ให้รหัสผ่านปรากฏแก่ ps

ใช้เอกสารที่นี่ openssl เท่านั้นเห็นข้อความของรหัสผ่าน
ตราบใดที่คุณแน่ใจว่าจะกำจัดไฟล์กลางไม่มีร่องรอยเหลืออยู่ บางทีใครบางคนสามารถช่วยทำสิ่งนี้ได้ในขั้นตอนการปฏิบัติงานและกำจัดไฟล์กลาง?

# 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

นี่จะเป็นคำตอบที่ดีกว่าถ้ามันอธิบายวิธีใช้สวิตช์ มันไม่ผิด (ยกเว้นว่าencคำสั่งไม่มี-knสวิตช์อย่างน้อยในเวอร์ชันปัจจุบันมัน-pass) แต่ก็ไม่ได้ให้ข้อมูลอะไรมาก (downvote ไม่ใช่ของฉัน)
Gilles 'หยุดความชั่วร้าย'

ขอบคุณ @Gilles มองไปที่เอกสารและเห็นความผิดพลาดของฉันอัปเดตคำตอบด้วยวิธีการอื่น
bsd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.