จะปลอดภัยหรือไม่ที่จะใช้ echo เพื่อส่งผ่านข้อมูลที่ละเอียดอ่อนไปยัง chpasswd?


17

ฉันพยายามที่จะตั้งค่ารหัสผ่านบัญชีผู้ใช้จำนวนchpasswdไม่มากโดยใช้ รหัสผ่านควรมีการสร้างแบบสุ่มและพิมพ์stdout(ฉันต้องเขียนพวกเขาลงหรือใส่ไว้ในการจัดเก็บรหัสผ่าน) chpasswdและยังผ่านเข้าสู่

อย่างไร้เดียงสาฉันจะทำเช่นนี้

{
  echo student1:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
  echo student2:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
} | tee >(chpasswd)

อย่างไรก็ตามฉันกังวลเกี่ยวกับการส่งรหัสผ่านใหม่เป็นอาร์กิวเมนต์บรรทัดคำสั่งไปที่echoเนื่องจากผู้ใช้รายอื่นมักมองเห็นข้อโต้แย้งในps -aux(แม้ว่าฉันจะไม่เคยเห็นechoบรรทัดใด ๆปรากฏps)

มีวิธีอื่นในการเพิ่มมูลค่าให้กับรหัสผ่านที่ส่งคืนของฉันแล้วส่งผ่านเข้าไปยังchpasswd?


6
echoเป็นเปลือกในตัว มันจะไม่เปิดขึ้นในตารางกระบวนการ
Kusalananda

คำตอบ:


15

รหัสของคุณควรจะปลอดภัยเนื่องจากechoจะไม่แสดงในตารางกระบวนการเนื่องจากเป็นเชลล์ในตัว

นี่คือทางเลือกอื่น:

#!/bin/bash

n=20
paste -d : <( seq -f 'student%.0f' 1 "$n" ) \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

สิ่งนี้จะสร้างชื่อนักเรียนและรหัสผ่านnของคุณโดยไม่ต้องผ่านรหัสผ่านใด ๆ ในบรรทัดคำสั่งของคำสั่งใด ๆ

pasteยูทิลิตี้กาวกันหลายไฟล์เป็นคอลัมน์และแทรกตัวคั่นในระหว่างพวกเขา ที่นี่เราใช้:เป็นตัวคั่นและให้สอง "ไฟล์" (การทดแทนกระบวนการ) อันแรกประกอบด้วยเอาต์พุตของseqคำสั่งที่สร้างชื่อผู้ใช้ 20 คนและอันที่สองประกอบด้วยเอาต์พุตของไพพ์ไลน์ที่สร้างสตริงสุ่มยาว 20 สตริงที่มีความยาว 13

หากคุณมีไฟล์ชื่อผู้ใช้ที่สร้างขึ้นแล้ว:

#!/bin/bash

n=$(wc -l <usernames.txt)

paste -d : usernames.txt \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

สิ่งเหล่านี้จะบันทึกรหัสผ่านและชื่อผู้ใช้ลงในไฟล์secret.txtแทนที่จะแสดงรหัสผ่านที่สร้างขึ้นในเทอร์มินัล


2
นั่นเป็นทางออกที่ฉลาดที่ไม่ต้องการechoหรือprintfอย่างไรก็ตามรหัสนั้นค่อนข้างอึดอัดในการถอดรหัส
Nils Werner

@NilsWerner เพิ่มคำอธิบายอีกเล็กน้อย แจ้งให้เราทราบหากมีสิ่งใดที่คุณต้องการให้ฉันขยาย
Kusalananda

1
คุณไม่ควรพึ่งพาechoการสร้างเชลล์ในตัว บนเปลือกหอยส่วนใหญ่จะเป็น แต่ก็ไม่มีข้อกำหนดใด ๆ
Austin Hemmelgarn

1
@ Kusalananda เพียงแค่อยากรู้อยากเห็นมีความแตกต่างที่มีประสิทธิภาพระหว่างtee secret.txt > >(chpasswd)และtee secret.txt | chpasswd? หลังดูเหมือนว่าไกลกันมากขึ้นดังนั้นฉันสงสัยว่าทำไมคุณเลือกที่จะใช้ทดแทนกระบวนการแทนท่อธรรมดา
คริสโต Shroba

1
@ChristopherShroba ไม่มีเหตุผลอื่นนอกจากมันคล้ายกับรหัสที่มีอยู่แล้วในคำถาม (ใช้การทดแทนกระบวนการด้วยtee) ตอนนี้คุณได้ชี้ให้เห็นแล้วฉันคิดว่าฉันจะเปลี่ยนมันจริง (มันดูดีกว่า) ขอบคุณ
Kusalananda

8

echoมีแนวโน้มที่จะสร้างขึ้นในเชลล์ดังนั้นมันจะไม่ปรากฏpsเป็นกระบวนการแยกต่างหาก

แต่คุณไม่จำเป็นต้องใช้การทดแทนคำสั่งคุณสามารถรับเอาต์พุตจากไพพ์ไลน์โดยตรงไปที่chpasswd:

{  printf "%s:" "$username";
   head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''
} | chpasswd 

หากคุณต้องการเปลี่ยนรหัสผ่านหลายรหัสด้วยการเรียกใช้ครั้งเดียวchpasswdคุณควรทำซ้ำส่วนสำคัญ ๆ ได้อย่างง่ายดาย หรือทำให้เป็นฟังก์ชัน:

genpws() {
    for user in "$@"; do
        printf "%s:" "$user";
        head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13
        echo
    done
}
genpws username1 username2... | chpasswd 

ในฐานะที่เป็นกัน: ที่head /dev/urandomรู้สึกแปลกเล็กน้อยเนื่องจากurandomไม่ได้มุ่งเน้นเส้น มันอาจอ่านจำนวนไบต์ที่มากเกินไปซึ่งจะส่งผลกระทบต่อแนวคิดเกี่ยวกับเอนโทรปีของเคอร์เนลซึ่งอาจนำไปสู่การ/dev/randomบล็อก มันอาจจะสะอาดกว่าถ้าคุณอ่านข้อมูลจำนวนคงที่และใช้บางอย่างเช่นbase64การแปลงไบต์แบบสุ่มเป็นตัวอักษรที่พิมพ์ได้ (แทนที่จะทิ้งไปประมาณ 3/4 ของไบต์ที่คุณได้รับ)

บางอย่างเช่นนี้จะทำให้คุณประมาณ 16 ตัวอักษรและตัวเลข:

head -c 12 /dev/urandom | base64 | tr -dc A-Za-z0-9 

(นั่นคือจำนวนที่น้อยลงของตัวละคร+และ/ตัวละครในผลลัพธ์ของbase64โอกาสที่จะเป็น 1/32 ต่อตัวละครดังนั้นถ้าฉันได้ combinatorics ของฉันถูกต้องที่ให้โอกาส 99% ของการออกอย่างน้อย 14 ตัวและ โอกาส 99.99% ที่เหลืออย่างน้อย 12)


printfโซลูชันของคุณไม่ได้ทำตามที่รหัสเดิมของฉันทำ: ส่งคืนหลายบรรทัดสำหรับชื่อผู้ใช้หลายชื่อ แต่ฉันขอขอบคุณคำพูดของคุณในhead urandom
Nils Werner

@NilsWerner ดีฉันถึงแม้ว่าการขยายไปยังผู้ใช้หลายคนชัดเจน แต่ไม่ว่าเราจะสร้างฟังก์ชั่นในการสร้างชื่อผู้ใช้: คู่รหัสผ่านสำหรับผู้ใช้หลายคนในครั้งเดียว (ดูการแก้ไข)
ilkkachu

3
คุณไม่สามารถพึ่งพา 10 "บรรทัดแรก" จาก urandom ที่มีอักขระมากพอที่คุณต้องการ เพียงเรียกใช้ urandom โดยตรงผ่าน tr ​​แทน
Kusalananda

@Kusalananda คุณหมายถึงhead -c 10 | base64ท่อส่งน้ำมันของฉันหรือ Nils เป็นท่อด้วยhead | trหรือไม่ 10 "บรรทัด" ของการสุ่มไบต์มีแนวโน้มที่จะเป็นร้อยไบต์ (เนื่องจากมีเพียง 1 ใน 256 จะเป็นบรรทัดใหม่) แม้ว่าในทางทฤษฎีแล้วมันอาจจะเท่ากับ 10 ไบต์ แต่อัตราต่อรองของมันจะเล็กน้อยมาก ในทำนองเดียวกันเมื่อใช้base64หากสุ่มไบต์เกิดขึ้นเพียงแค่พูด\xffแล้ว base64 จะเป็นเพียงแค่สตริงของสแลช แต่ก็ไม่น่าจะสวยเกินไป หากคุณสนใจคุณสามารถอ่านมากกว่า 10 ไบต์ลดอัตราต่อรองของที่นั้นและตัดความยาวของผลลัพธ์ที่ได้
ilkkachu

1
@ilkkachu ฉันหมายถึงรหัสทั้งสอง หากคุณอ่านไบต์แบบสุ่มและต้องการบางสิ่งที่มีความยาวเฉพาะหลังจากกรองสิ่งที่คุณไม่ต้องการแล้วอย่าตัดแหล่งข้อมูลจนกว่าคุณจะแน่ใจว่าคุณมีสิ่งที่คุณต้องการ อย่างที่คุณพูดมันไม่น่าเป็นไปได้มากที่คุณจะได้รับสายสิบบรรทัดใหม่/dev/urandomแต่ความเสี่ยงไม่ใช่ 0%
Kusalananda
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.