มีวิธีการส่งผ่านข้อมูลที่สำคัญใน bash โดยใช้พรอมต์สำหรับคำสั่งใด ๆ ?


40

สมมติว่าฉันกำลังใช้sha1passเพื่อสร้างแฮชของรหัสผ่านที่ละเอียดอ่อนบางตัวในบรรทัดคำสั่ง ฉันสามารถใช้sha1pass mysecretเพื่อสร้างแฮชของmysecretแต่นี่มีข้อเสียที่mysecretตอนนี้อยู่ในประวัติศาสตร์ทุบตี มีวิธีการที่จะบรรลุเป้าหมายสุดท้ายของคำสั่งนี้ในขณะที่หลีกเลี่ยงการเปิดเผยmysecretในข้อความธรรมดาpasswdหรือไม่โดยใช้คำสั่ง-style?

ฉันสนใจวิธีการทั่วไปในการทำเช่นนี้เพื่อส่งผ่านข้อมูลที่ละเอียดอ่อนไปยังคำสั่งใด ๆ วิธีการจะเปลี่ยนเมื่อข้อมูลที่ละเอียดอ่อนถูกส่งผ่านเป็นอาร์กิวเมนต์ (เช่นในsha1pass) หรือใน STDIN ไปยังคำสั่งบางอย่าง

มีวิธีการทำสิ่งนี้หรือไม่?


แก้ไข : คำถามนี้ดึงดูดความสนใจจำนวนมากและมีคำตอบที่ดีหลายข้อเสนอด้านล่าง สรุปคือ:

  • ตามคำตอบของ @ Kusalanandaเราจะไม่ต้องให้รหัสผ่านหรือความลับเป็นอาร์กิวเมนต์บรรทัดคำสั่งสำหรับยูทิลิตี้ สิ่งนี้มีความเสี่ยงในหลายวิธีตามที่อธิบายไว้โดยเขาและควรใช้ยูทิลิตี้ที่ออกแบบมาดีกว่าที่สามารถรับข้อมูลลับบน STDIN ได้
  • คำตอบของ @ vfbsilvaอธิบายถึงวิธีการป้องกันไม่ให้สิ่งต่าง ๆ ถูกเก็บไว้ในประวัติทุบตี
  • @ คำตอบของโจนาธานอธิบายวิธีการที่ดีอย่างสมบูรณ์แบบสำหรับการทำสิ่งนี้ให้สำเร็จตราบใดที่โปรแกรมสามารถใช้ข้อมูลลับของมันใน STDIN ดังนั้นฉันตัดสินใจยอมรับคำตอบนี้ sha1passใน OP ของฉันเป็นเพียงตัวอย่าง แต่การสนทนาได้กำหนดว่ามีเครื่องมือที่ดีกว่าที่ใช้ข้อมูลบน STDIN
  • เป็น@R ..บันทึกในคำตอบของเขาการใช้คำสั่งขยายบนตัวแปรไม่ปลอดภัย

ดังนั้นโดยสรุปฉันยอมรับคำตอบของ @ Jonathanเนื่องจากเป็นทางออกที่ดีที่สุดเนื่องจากคุณมีโปรแกรมที่ออกแบบมาอย่างดีและมีความประพฤติดี แม้ว่าการส่งรหัสผ่านหรือความลับในฐานะที่เป็นอาร์กิวเมนต์บรรทัดคำสั่งจะไม่ปลอดภัยโดยพื้นฐาน


6
ไม่เพียงเท่านั้น: ใครก็ตามที่อยู่ในเครื่องเดียวกันที่ได้รับอนุญาตให้ทำรายการกระบวนการทำงานอาจเห็นว่าsha1pass mysecretกำลังทำงานอยู่และรู้ว่าอะไรmysecretคืออะไร (ใช้งานได้เพียงไม่กี่วินาทีในขณะที่โปรแกรมกำลังทำงานอยู่แน่นอน ... )
MathematicalOrchid

@MathematicalOrchid สิ่งนี้สามารถหลีกเลี่ยงได้โดยการเรียกใช้ในเครื่องเสมือนส่วนตัว แต่นั่นอาจเป็นงานที่มากเกินไปในการสร้างรหัสผ่านเดียว ... :-)
Kusalananda

5
@ Kusalananda จุดของฉันถูกเพิ่มเติม "ไม่เคยใส่ข้อมูลที่สำคัญในบรรทัดคำสั่งแม้ว่าคุณจะคิดวิธีปิดประวัติคำสั่ง" ...
MathematicalOrchid

2
เพียงเท่านี้คุณก็รู้ว่า SHA-1 ถูกคัดค้านเนื่องจากการแฮ็กคีย์หรือรหัสผ่านตั้งแต่ไม่กี่ปีที่ผ่านมา
David Foerster

2
โปรดทราบว่าหากระบบใช้ daemon การตรวจสอบคำสั่งทั้งหมดและอาร์กิวเมนต์ทั้งหมดโดยผู้ใช้ทั้งหมดจะถูกบันทึกจากส่วนกลางโดย root ดังนั้นทุกคนที่สามารถเข้าถึงบันทึกเหล่านั้นจะเห็นสิ่งนี้
Randall

คำตอบ:


20

หากใช้zshหรือbashเชลล์ให้ใช้ตัวเลือก -s กับreadเชลล์บิวด์อินเพื่ออ่านบรรทัดจากอุปกรณ์เทอร์มินัลโดยไม่แสดงให้เห็น

IFS= read -rs VARIABLE < /dev/tty

จากนั้นคุณสามารถใช้การเปลี่ยนเส้นทางแฟนซีเพื่อใช้ตัวแปรเป็น stdin

sha1pass <<<"$VARIABLE"

หากใครก็ตามวิ่งpsสิ่งที่พวกเขาจะเห็นคือ "sha1pass"

ที่ถือว่าsha1passรหัสผ่านอ่านจาก stdin (หนึ่งบรรทัดโดยไม่สนใจตัวคั่นบรรทัด) เมื่อไม่ได้รับอาร์กิวเมนต์ใด ๆ


ฉันเชื่อว่าเราจัดตั้งขึ้นที่sha1passไม่ได้ใช้สตรีมอินพุตมาตรฐาน
Kusalananda

@ Kusalananda เอาล่ะ แต่วิธีนี้ใช้ได้กับโปรแกรมที่อ่านจาก stdin
Jonathan

ดังนั้นสมมติว่ายูทิลิตี้สามารถรับข้อมูลลับบน STDIN นี่เป็นโซลูชันที่ปลอดภัยและปลอดภัย
คิด

ฉันตัดสินใจที่จะยอมรับคำตอบนี้เนื่องจากมันเป็นทางออกที่ดีที่สุดเนื่องจากคุณมีโปรแกรมที่ได้รับการออกแบบมาเป็นอย่างดี sha1passเป็นเพียงตัวอย่างใน OP ของฉันและไม่ใช่ทางเลือกที่ดีที่สุดที่จะใช้สำหรับสิ่งนี้
รวบรวม

1
@cemulate ... ไม่ปลอดภัยในบรรทัดคำสั่ง ในบริบทของ heredoc หรือ herestring (ดังคำตอบที่นี่) มันไม่ได้ถูกเปิดเผยpsแต่อาจถูกเขียนลงในไฟล์ชั่วคราว - ถ้ามีใครต้องการหลีกเลี่ยงสิ่งนั้นsshpass < <(printf '%s\n' "$VARIABLE")อาจถูกพิจารณา (เพราะprintfเป็น builtin ไม่ใช่ คำสั่งภายนอกจะไม่ถูกส่งผ่านไปยังexecvและเข้าถึงได้ผ่านps)
Charles Duffy

35

เป็นการดีที่คุณไม่เคยพิมพ์รหัสผ่านข้อความที่ชัดเจนในบรรทัดคำสั่งเป็นอาร์กิวเมนต์ไปยังคำสั่ง การทำเช่นนี้จะทำให้รหัสผ่านเป็นอาร์กิวเมนต์ของคำสั่งและอาจเห็นอาร์กิวเมนต์ของบรรทัดคำสั่งในตารางกระบวนการโดยใช้เครื่องมืออย่างง่ายเช่นpsหรือบันทึกลงในบันทึกการตรวจสอบบางอย่าง

ต้องบอกว่ามีวิธีการซ่อนรหัสผ่านที่แท้จริงจากประวัติคำสั่งของเชลล์

sha1pass "$( head -n 1 )"

Enterจากนั้นพิมพ์รหัสผ่านและกด คำสั่งใช้ที่นี่ยอมรับว่าหนึ่งบรรทัดของการป้อนข้อมูลและการขึ้นบรรทัดใหม่ล่าสุดที่คุณพิมพ์จะไม่เป็นส่วนหนึ่งของข้อมูลที่ถูกส่งผ่านไปยังheadsha1pass

เพื่อป้องกันไม่ให้ตัวละครสะท้อน:

sha1pass "$( stty -echo; head -n 1; stty echo )"

stty -echoคำสั่งจะปิดการสะท้อนของตัวอักษรที่พิมพ์ลงบนเครื่องคอมพิวเตอร์ stty echoสะท้อนการเรียกคืนแล้วด้วย

ในการส่งผ่านอินพุตมาตรฐานคำสั่งสุดท้ายนั้นสามารถเปลี่ยนแปลงได้ (คุณจะทำเช่นนี้หากsha1passข้อมูลที่ยอมรับในอินพุตมาตรฐาน แต่ปรากฏราวกับว่ายูทิลิตีนี้ไม่สนใจอินพุตมาตรฐาน):

{ stty -echo; head -n 1; stty echo; } | somecommand

หากคุณต้องการอินพุตหลายบรรทัด (เหนือสมมติว่าบรรทัดเดียวควรผ่านโดยไม่มีอักขระขึ้นบรรทัดใหม่ในตอนท้าย) จากนั้นแทนที่headคำสั่งทั้งหมดด้วยcatและยุติอินพุต (สมมติว่าsomecommandตัวเองอ่านจนกระทั่งสิ้นสุดไฟล์) ด้วยCtrl+D( ต่อไปนี้Returnหากคุณต้องการรวมอักขระบรรทัดใหม่ในอินพุตหรือสองครั้งหากไม่ได้)

สิ่งนี้จะใช้งานได้ไม่ว่าคุณจะใช้เชลล์แบบใด (ตราบใดที่มันเป็นเชลล์แบบบอร์นหรือ rc-like)

เชลล์บางตัวอาจถูกสร้างขึ้นเพื่อไม่บันทึกคำสั่งที่พิมพ์ไว้ในไฟล์ประวัติถ้าคำสั่งถูกนำหน้าด้วยช่องว่าง นี้มักจะเกี่ยวข้องต้องตั้งค่าHISTCONTROL ignorespaceนี้ได้รับการสนับสนุนอย่างน้อยbashและkshใน OpenBSD แต่ไม่เช่นหรือksh93 ผู้ใช้อาจใช้ตัวเลือกหรือตัวแปรเพื่อกำหนดรูปแบบที่จะเพิกเฉยdashzshhistignorespaceHISTORY_IGNORE

ในเชลล์ที่รองรับการอ่านreadโดยไม่ใช้การสะท้อนอักขระไปยังเทอร์มินัลคุณอาจใช้

IFS= read -rs password     # -s turns off echoing in bash or zsh
                           # -r for reading backslashes as-is,
                           # IFS= to preserve leading and trailing blanks
sha1pass "$password"

แต่สิ่งนี้เห็นได้ชัดว่ายังคงมีปัญหาเดียวกันโดยอาจเปิดเผยรหัสผ่านในตารางกระบวนการ

หากยูทิลิตีอ่านจากอินพุตมาตรฐานและหากเชลล์รองรับ "here-strings" อาจมีการเปลี่ยนแปลงด้านบน

IFS= read -rs password
somecommand <<<"$password"

สรุปความคิดเห็นด้านล่าง:

  • การดำเนินการคำสั่งด้วยรหัสผ่านที่กำหนดในบรรทัดคำสั่งซึ่งคำสั่งทั้งหมดข้างต้นทำยกเว้นคำสั่งที่ส่งข้อมูลไปยังคำสั่งอาจทำให้รหัสผ่านปรากฏแก่ทุกคนที่ทำงานpsในเวลาเดียวกัน ไม่มีคำสั่งใด ๆ ข้างต้นที่จะบันทึกรหัสผ่านที่พิมพ์ไว้ในไฟล์ประวัติของเชลล์หากเรียกใช้จากเชลล์แบบโต้ตอบ

  • โปรแกรมที่ทำงานได้ดีที่อ่านรหัสผ่านแบบข้อความธรรมดาทำได้โดยอ่านจากอินพุตมาตรฐานจากไฟล์หรือจากเทอร์มินัลโดยตรง

  • sha1pass จะต้องใช้รหัสผ่านในบรรทัดคำสั่งทั้งพิมพ์โดยตรงหรือใช้รูปแบบของการทดแทนคำสั่งบางรูปแบบ

  • หากเป็นไปได้ให้ใช้เครื่องมืออื่น


11
สิ่งนี้ไม่ถูกต้อง ผลลัพธ์ของการขยายคำสั่ง$(...)จะเป็นส่วนหนึ่งของบรรทัดคำสั่งและมองเห็นได้ในpsเอาต์พุตยกเว้นบนระบบที่มีการชุบแข็ง / proc
..

3
@ Kusalananda หรือแม้แต่เขียนทับ argv หลังจากที่คุณเริ่มออกจากหน้าต่างที่มีช่องโหว่ก่อนที่จะทำการเขียนทับ มันเป็นการบรรเทาผลกระทบไม่ใช่การแก้ไข
Charles Duffy

5
@ Kusalananda ไม่มีโปรแกรมที่ออกแบบมาอย่างดีสำหรับรหัสผ่านการแฮชที่จำเป็นต้องป้อนข้อมูลในบรรทัดคำสั่งดังนั้นโดยทั่วไปเงื่อนไขจะได้รับ - หากไม่เป็นเช่นนั้นเราควรเลือกเครื่องมืออื่น
Charles Duffy

4
@CharlesDuffy: เครื่องมือที่นี่ดูเหมือนจะแตกหัก sha1passทำงานโดยไม่มีรหัสผ่านบนบรรทัดคำสั่งดูเหมือนว่าจะสร้างผลลัพธ์โดยไม่ต้องอ่านอะไรเลย ... ดังนั้น OP จำเป็นต้องเลือกเครื่องมือที่แตกต่างกัน
..

8
คำตอบนี้ไม่ปลอดภัยจากมุมมองด้านความปลอดภัยและข้อดีเพียงอย่างเดียวคือรหัสผ่านไม่ปรากฏในประวัติเชลล์ แต่ข้อดีนั้นง่ายกว่าที่จะทำโดยการรวมช่องว่างด้านหน้าคำสั่ง
Ferrybig

25

หากคุณตั้งค่าHISTCONTROLเช่นนั้น:

HISTCONTROL=ignorespace

และเริ่มคำสั่งด้วยช่องว่าง:

~$  mycommand

มันจะไม่ถูกเก็บไว้ในประวัติศาสตร์


10

ส่งผ่านข้อมูลที่ละเอียดอ่อนผ่านไพพ์หรือ here-doc:

command_with_secret_output | command_with_secret_input

หรือ:

command_with_secret_input <<EOF
$secret
EOF

ไม่เป็นไรสำหรับความลับที่จะอยู่ในตัวแปรเชลล์ (ไม่ถูกเอ็กซ์พอร์ต) แต่คุณไม่สามารถใช้ตัวแปรเหล่านั้นบนบรรทัดคำสั่งเฉพาะในที่นี่คือเอกสารและเชลล์ภายใน

ตามที่ระบุไว้โดย Kusalananda ในความคิดเห็นหากคุณป้อนคำสั่งในเชลล์แบบโต้ตอบบรรทัดที่คุณป้อนสำหรับเอกสารที่นี่จะถูกเก็บไว้ในประวัติเชลล์ดังนั้นจึงไม่ปลอดภัยที่จะพิมพ์รหัสผ่านที่นั่น แต่ก็ควรจะเป็น ปลอดภัยในการใช้ตัวแปรเชลล์ที่มีความลับ ประวัติจะมีข้อความ$secretมากกว่าที่จะ$secretขยายออกไป

การใช้การขยายคำสั่งไม่ปลอดภัย :

command_with_secret_input "$(command_with_secret_output)"

เนื่องจากเอาต์พุตจะรวมอยู่ในบรรทัดคำสั่งและมองเห็นได้ในpsเอาต์พุต (หรือการอ่านด้วยตนเองจาก / proc) ยกเว้นในระบบที่มีการชุบแข็ง / proc

การกำหนดตัวแปรก็โอเคเช่นกัน:

secret=$(command_with_secret_output)

สิ่งที่ฉันกำลังมองหาคือคำสั่งจริงcommand_with_secret_outputที่อนุญาตให้ฉันพิมพ์เอาต์พุตลับ คำสั่งดังกล่าวมีอยู่ที่สามารถทดแทนได้ที่นี่หรือไม่?
cemulate

โปรดทราบว่าการพิมพ์เอกสารที่นี่ในbash เซสชันแบบโต้ตอบจะบันทึกเอกสารในไฟล์ประวัติ
Kusalananda

@cemulate: เพียงแค่ใช้ builtin เปลือกเช่นread แล้วความลับของคุณอยู่ในread -r secret $secretคุณสามารถเรียกใช้ stty ก่อน / หลังเพื่อซ่อนอินพุตหากคุณต้องการ
..

3
@Kusalananda: sha1passดูเหมือนว่าจะใช้งานไม่ได้ / ไม่ปลอดภัย / เป็นพื้นฐานเพราะไม่สามารถอ่านรหัสผ่านจาก stdin หรือไฟล์ได้ ฉันคิดว่ามียูทิลิตี้ที่แตกต่างกันในการแก้ปัญหา
. ..

1
@cemulate ความคิดเห็นสุดท้ายของคุณต่อ R คือที่ตรงจุด นั่นเป็นสาเหตุที่มันไม่ช่วย read -rsจะทำงาน (ถ้าคุณรวม-rถึงสามารถมีรหัสผ่านที่มีเครื่องหมายแบ็กสแลชอยู่ด้วย) แต่จากนั้นคุณกลับมาที่อาจแสดงรหัสผ่านในรายการกระบวนการ (และขึ้นอยู่กับว่าบัญชีกระบวนการถูกเปิดใช้งานและวิธีการกำหนดค่า ในบันทึกกระบวนการบัญชีด้วย)
Kusalananda

6

เพียงเขียนค่าลงในไฟล์และส่งไฟล์:

$ cat > mysecret
Big seecreeeet!
$ cat mysecret | sha1pass 

ผมไม่แน่ใจว่าวิธีการทำงานถ้ามันสามารถใช้เป็นไฟล์ใส่คุณสามารถใช้sha1pass sha1pass < mysecretหากไม่มีการใช้catอาจเป็นปัญหาเนื่องจากมีการขึ้นบรรทัดใหม่ขั้นสุดท้าย หากเป็นกรณีนี้ให้ใช้ (หากคุณheadรองรับ-c):

head -c-1 mysecret | sha1pass 

2
เขียนรหัสผ่านไปยังดิสก์ทำไมในตัวอย่างแรกของคุณเมื่อคุณก็สามารถทำcat | sha1pass? cat mysecret | sha1passและsha1pass < mysecretมีพฤติกรรมเดียวกันกับการขึ้นบรรทัดใหม่ขั้นสุดท้าย catไม่ได้เพิ่มบรรทัดใหม่ อย่างไรก็ตามหากsha1passรองรับการส่งรหัสผ่านผ่านอินพุตมาตรฐานฉันคาดหวังให้ละเว้นบรรทัดใหม่สุดท้ายด้วยตัวเอง ไฟล์ที่มีบรรทัดที่ไม่ได้ถูกยกเลิกโดยการขึ้นบรรทัดใหม่นั้นไม่เป็นธรรมชาติในยูนิกซ์หลังจากนั้นทั้งหมดดังนั้นจึงน่าแปลกที่จะคาดหวังว่าไฟล์ที่ไม่ได้ถูกยกเลิกโดยการขึ้นบรรทัดใหม่
JoL

@JoL ฉัน) เพราะฉันไม่ได้คิดอย่างนั้น: / แต่มันจะทำงานยังไง? cat | sha1passดูเหมือนว่าจะทำงานsha1passก่อนที่จะให้โอกาสฉันป้อนข้อมูลใด ๆ ii) ไม่แน่นอนcat mysecretไม่ได้เพิ่มบรรทัดใหม่ฉันไม่เคยพูดcatเพิ่ม แต่จะรวมไว้ในนั้นด้วย
terdon

ฉันเห็น แต่มันไม่เหมือน< mysecretเอามันทั้ง :)
JoL

ไม่เป็นไร. head -c-1ตอนนี้ที่ผมอ่านอีกครั้งผมเห็นว่าคุณกล่าวว่าภายหลังนำเสนอ ผมคิดว่าผมเพิ่งสับสนว่าทำไมถึงใช้และต่อมานำเสนอcat mysecret | sha1pass sha1pass < mysecretฉันเดาว่าความกังวลคือ sha1pass อาจบ่นเกี่ยวกับไฟล์ปกติสำหรับ stdin; ฉันไม่แน่ใจว่าทำไม
JoL

@JoL มันมากขึ้นเพราะผมไม่เคยใช้sha1passและไม่สามารถหาคู่มือหรือ-hหรือรูปแบบอื่นใดของเอกสารในไม่กี่นาทีผมใช้เวลาค้นหาและอื่น ๆ ไม่สามารถคิดออกถ้าทำงานsha1pass fooได้รับการปฏิบัติfooเป็นสายป้อนหรือเป็นไฟล์การป้อนข้อมูล . ฉันจึงให้ตัวเลือกเพื่อจัดการกับความเป็นไปได้แต่ละอย่าง
terdon

1

หากสิ่งที่ terdon ทำได้ก็เป็นทางออกที่ดีที่สุดโดยผ่านอินพุตมาตรฐาน ปัญหาเดียวที่เหลือคือเขาเขียนรหัสผ่านลงดิสก์ เราสามารถทำสิ่งนี้แทน:

stty -echo
echo -n "password: "
head -1 | sha1pass
stty echo

เช่นเดียวกับ Kusalananda ที่กล่าวว่าstty -echoให้แน่ใจว่าสิ่งที่คุณพิมพ์ไม่ได้เห็นจนกว่าคุณจะทำstty echoอีกครั้ง จะได้รับหนึ่งบรรทัดจากอินพุตมาตรฐานและผ่านมันไปhead -1sha1pass


0

ฉันจะใช้

sha1pass "$(cat)"

catจะอ่านจาก stdin จนกระทั่งEOFซึ่งอาจเกิดจากการกด Ctrl + D จากนั้นผลลัพธ์จะถูกส่งผ่านเป็นอาร์กิวเมนต์ไปที่sha1pass


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