ssh
ทำตามrsh
ประเพณีโดยใช้โปรแกรมเชลล์ของผู้ใช้จากไฟล์รหัสผ่านเพื่อดำเนินการคำสั่ง
ซึ่งหมายความว่าเราสามารถแก้ปัญหานี้ได้โดยไม่ต้องเกี่ยวข้องกับssh
การกำหนดค่า แต่อย่างใด
หากคุณไม่ต้องการให้ผู้ใช้สามารถเข้าถึงเชลล์ได้ให้แทนที่เชลล์ของผู้ใช้นั้นด้วยสคริปต์ หากคุณมองเข้าไป/etc/passwd
คุณจะเห็นว่ามีฟิลด์ที่กำหนดตัวแปลคำสั่งเชลล์ให้กับผู้ใช้แต่ละคน สคริปต์ที่ใช้เป็นเปลือกทั้งสำหรับการเข้าสู่ระบบแบบโต้ตอบของพวกเขาเช่นเดียวกับคำสั่งssh user@host
ssh user@host command arg ...
นี่คือตัวอย่าง ฉันสร้างผู้ใช้foo
ที่มีเชลล์เป็นสคริปต์ สคริปต์จะพิมพ์ข้อความmy arguments are:
ตามด้วยอาร์กิวเมนต์ (แต่ละบรรทัดแยกจากกันและในวงเล็บเหลี่ยม) และยุติ ในกรณีล็อกอินไม่มีข้อโต้แย้ง นี่คือสิ่งที่เกิดขึ้น:
webserver:~
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.
หากผู้ใช้พยายามเรียกใช้คำสั่งจะมีลักษณะดังนี้:
webserver:~
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>
"เปลือก" ของเราได้รับ -c
เรียกใช้สไตล์โดยคำสั่งทั้งหมดเป็นอาร์กิวเมนต์เดียวเช่นเดียวกับที่/bin/sh
จะได้รับ
อย่างที่คุณเห็นสิ่งที่เราทำได้ในตอนนี้คือพัฒนาสคริปต์ให้ไกลขึ้นเพื่อให้จดจำกรณีที่ถูกเรียกใช้ด้วย -c
อาร์กิวเมนต์จากนั้นแยกวิเคราะห์สตริง (พูดโดยการจับคู่รูปแบบ) สตริงเหล่านั้นที่ได้รับอนุญาตสามารถส่งผ่านไปยังเชลล์จริงได้โดยการเรียกซ้ำ/bin/bash -c <string>
สตริงผู้ที่ได้รับอนุญาตให้สามารถส่งผ่านไปยังเปลือกจริงโดยกล่าวอ้างซ้ำกรณีการปฏิเสธสามารถพิมพ์ข้อความแสดงข้อผิดพลาดและยุติ (รวมถึงกรณีที่-c
หายไป)
คุณต้องระวังว่าคุณเขียนสิ่งนี้อย่างไร ฉันขอแนะนำให้เขียนเฉพาะการจับคู่เชิงบวกซึ่งอนุญาตเฉพาะสิ่งที่เฉพาะเจาะจงเท่านั้นและไม่อนุญาตอย่างอื่น
หมายเหตุ:หากคุณเป็นroot
เช่นนั้นคุณยังสามารถเข้าสู่ระบบบัญชีนี้ได้โดยการลบล้างเชลล์ในไฟล์su
su -s /bin/bash foo
คำสั่งเช่นนี้ (แทนเชลล์ที่เลือก) ผู้ที่ไม่ใช่รูทไม่สามารถทำได้
นี่คือสคริปต์ตัวอย่างเช่น จำกัด ผู้ใช้ในการใช้เพียงssh
สำหรับการเข้าถึงไปยังที่เก็บภายใต้git
/git
#!/bin/sh
if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then
printf "interactive login not permitted\n"
exit 1
fi
set -- $2
if [ $# != 2 ] ; then
printf "wrong number of arguments\n"
exit 1
fi
case "$1" in
( git-upload-pack | git-receive-pack )
;;
( * )
printf "command not allowed\n"
exit 1
;;
esac
gitpath=$(readlink -f "$2")
case "$gitpath" in
( /git/* )
;;
( * )
printf "access denied outside of /git\n"
exit 1
;;
esac
if ! [ -e "$gitpath" ] ; then
printf "that git repo doesn't exist\n"
exit 1
fi
"$1" "$gitpath"
แน่นอนเราเชื่อมั่นว่าโปรแกรม Git เหล่านี้git-upload-pack
และgit-receive-pack
ไม่มีช่องโหว่หรือช่องโหว่ที่จะทำให้ผู้ใช้เข้าถึงระบบได้
ซึ่งมีอยู่ในรูปแบบข้อ จำกัด ประเภทนี้ ผู้ใช้ได้รับการรับรองความถูกต้องในการรันโค้ดในโดเมนความปลอดภัยบางโดเมนและเรากำลังยกเลิกข้อ จำกัด ที่จะ จำกัด โดเมนนั้นไว้ที่โดเมนย่อย ตัวอย่างเช่นหากคุณอนุญาตให้ผู้ใช้รันvim
คำสั่งบนไฟล์เฉพาะเพื่อแก้ไขผู้ใช้ก็สามารถรับเชลล์:!sh[Enter]
ได้