SSH ในฐานะเทคนิคทดแทน Sudo
(whynothugo.nl)เป้าหมาย
- อนุญาตให้เฉพาะผู้ใช้ที่มีสิทธิ์รันคำสั่งด้วยสิทธิ์ root ได้
- ไม่ใช้การยกระดับสิทธิ์
การติดตั้งใช้งาน
-
สร้างคีย์ SSH เฉพาะสำหรับใช้ยืนยันตัวตนเป็น root
mkdir /root/.ssh/ echo ssh-ed25519 AAAAC3Nza... > /root/.ssh/local_keys -
รันอินสแตนซ์เซิร์ฟเวอร์
sshdที่ bind กับ Unix domain socketmkdir /run/sshd/ chown root:wheel /run/sshd/ chmod 750 /run/sshd/ s6-ipcserver /run/sshd/sshd.sock sshd -ie -o AuthorizedKeysFile=/root/.ssh/local_keys -o PermitRootLogin=yes -
ล็อกบัญชี root และตั้งค่าไม่ให้ล็อกอินด้วยรหัสผ่านได้
# เปลี่ยนรหัสผ่าน root ในไฟล์ /etc/passwd -
ใช้ออปชัน
ProxyCommandเพื่อเชื่อมต่อไปยังอินสแตนซ์sshdภายในเครื่องssh -o ProxyCommand='socat STDIO UNIX-CONNECT:/run/sshd/sshd.sock' \ -i .ssh/root-key.pub \ -t \ root@root \ "cd $(pwd); '$SHELL' --login" -
เขียนสคริปต์ที่ใช้ออปชัน
ProxyUseFdpassเพื่อส่งต่อ file descriptor ของซ็อกเก็ต#!/usr/bin/env python3 import sys import socket import array s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect("/run/sshd/sshd.sock") fds = array.array("i", [s.fileno()]) ancdata = [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fds)] socket.socket(fileno=1).sendmsg([b'\0'], ancdata) -
จากนั้นรันคำสั่ง
sshขั้นสุดท้ายssh -o ProxyCommand='/home/hugo/tmp/passfd.py' \ -i .ssh/root-key.pub \ -o ProxyUseFdpass=yes \ -t \ root@root \ "cd $(pwd); '$SHELL' --login"
บทสรุป
- เทคนิคนี้ใช้ OpenSSH ในการจัดการรายละเอียดด้านความปลอดภัย
- รองรับวิธีการยืนยันตัวตนหลากหลายแบบ รวมถึงคีย์ SSH แบบฮาร์ดแวร์
- ขั้นตอนการตั้งค่าบนโฮสต์ใหม่ไม่ได้ซับซ้อน
- สคริปต์
passfd.pyเป็นวิธีชั่วคราวสำหรับการทดลอง และหากจะใช้งานเป็นประจำควรเขียนเป็น executable ขนาดเล็ก
ความเห็นของ GN⁺
- วิธีนี้สามารถเพิ่มความปลอดภัยในฐานะทางเลือกแทน
sudoหรือdoasได้ - แนวทางที่ใช้ SSH เพื่อเสริมการยืนยันตัวตนรองรับวิธีการยืนยันตัวตนหลายแบบ รวมถึงการยืนยันตัวตนแบบใช้ฮาร์ดแวร์
- การตั้งค่าระบบค่อนข้างเรียบง่าย ทำให้วิศวกรมือใหม่ก็ทำตามได้ไม่ยาก
- หากทำสคริปต์
passfd.pyให้เป็น executable ขนาดเล็กแล้ววางไว้ใน/usr/local/binจะใช้งานได้สะดวกขึ้น - วิธีนี้ทำงานเฉพาะภายในเครื่องโดยไม่เปิดเผยออกสู่เครือข่าย จึงมีความปลอดภัยสูง
1 ความคิดเห็น
ความเห็นจาก Hacker News
ปัญหาความซับซ้อนที่เพิ่มขึ้น: จากเดิมที่เป็นไบนารี suid ตัวเดียว กลับต้องใช้ไบนารีสองตัว คือไบนารีที่รันด้วยสิทธิ์ root และอีกตัวที่ใช้ UNIX socket ทำให้ความซับซ้อนเพิ่มขึ้น รวมถึงงานเข้ารหัสแบบอสมมาตรด้วย
ความปลอดภัยของระบบ: หากจำกัดไบนารี sudo ให้ใช้ได้เฉพาะบางกลุ่ม (wheel) และปรับสิทธิ์ให้เหมาะสม ก็สามารถรักษาระดับความปลอดภัยที่ใกล้เคียงกับแนวทางของ sshd ได้ หากผู้ดูแลแพ็กเกจของระบบทำให้สิทธิ์ sudo พัง ก็ยังแก้เป็นระยะด้วย cron หรือจะติดตั้ง sudo จากซอร์สเองโดยตรงก็ได้
run0 ของ systemd: เครื่องมือ
run0ของ systemd ทำงานคล้าย sudo แต่ไม่ใช่ SUID โดยจะร้องขอให้ service manager เป็นผู้รันคำสั่งแทน ลักษณะการทำงานนี้จึงคล้าย ssh มากกว่าเปรียบเทียบ ssh กับ sudo: มีข้อสงสัยว่าการล็อกอินเป็น root ผ่าน ssh จะปลอดภัยกว่า sudo จริงหรือไม่ และควรมีการถกเถียงกันเรื่องวิธีป้องกันการเข้าถึงผู้ใช้ระยะไกลผ่าน sshd เมื่อเทียบกับข้อจำกัดของ sudo แล้ว แนวทางแบบ ssh อาจเปราะบางกว่า
ปัญหาของบริการเครือข่าย: หาก ssh ไม่เริ่มทำงานตอนบูต ก็จะไม่สามารถล็อกอินผ่านคอนโซลได้ด้วย ซึ่งอาจสร้างปัญหามากกว่า sudo หรือ su
แนวทางที่คล้ายกับ systemd run0: มีแนวทางที่คล้ายกับเครื่องมือ
run0ของ systemdการควบคุมแบบละเอียดของ sudo: sudo สามารถควบคุมคำสั่ง อาร์กิวเมนต์ และการสร้าง subshell ได้อย่างละเอียด แต่แนวทางใหม่จะสูญเสียความสามารถในการควบคุมระดับนี้ไป และยังทำให้การจัดการกุญแจที่เชื่อถือได้ยากขึ้น
การตั้งค่าคอนโซล SSH: วิธีจัดการการเข้าถึง root ด้วยการใช้คอนโซล SSH โดยเฉพาะ พร้อมเสริมความปลอดภัยด้วย Yubikey และการตั้งค่าไฟร์วอลล์
ข้อจำกัดของโปรโตคอล SSH: SSH ไม่ได้มีการสร้างโปรเซสเป็นส่วนหนึ่งของโปรโตคอล และไม่สามารถส่งต่อทรัพยากรในเครื่องไปยัง child process ได้ หากจะใช้แทน sudo ก็จำเป็นต้องมีส่วนขยายที่คล้าย POSIX spawn
การจัดการผู้ใช้: สิ่งสำคัญคือไม่ควรปฏิบัติกับผู้ใช้ราวกับเป็นเด็ก แต่ควรกำหนดค่าเริ่มต้นที่สมเหตุสมผลเพื่อหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น และหากจำเป็นต้องเข้าถึง root ก็ควรล็อกอินผ่านคอนโซล
ปัญหาในโหมดผู้ใช้เดี่ยว: หากไม่สามารถล็อกอินเป็น root ในโหมดผู้ใช้เดี่ยวได้ ก็จะทำให้การกู้คืนระบบทำได้ยาก ซึ่งจำเป็นต่อการแก้ปัญหาที่อาจเกิดขึ้นระหว่างการอัปเกรดระบบ