4 คะแนน โดย GN⁺ 2024-06-24 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

เป้าหมาย

  • อนุญาตให้เฉพาะผู้ใช้ที่มีสิทธิ์รันคำสั่งด้วยสิทธิ์ root ได้
  • ไม่ใช้การยกระดับสิทธิ์

การติดตั้งใช้งาน

  • สร้างคีย์ SSH เฉพาะสำหรับใช้ยืนยันตัวตนเป็น root

    mkdir /root/.ssh/
    echo ssh-ed25519 AAAAC3Nza... > /root/.ssh/local_keys
    
  • รันอินสแตนซ์เซิร์ฟเวอร์ sshd ที่ bind กับ Unix domain socket

    mkdir /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 ความคิดเห็น

 
GN⁺ 2024-06-24
ความเห็นจาก 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 ในโหมดผู้ใช้เดี่ยวได้ ก็จะทำให้การกู้คืนระบบทำได้ยาก ซึ่งจำเป็นต่อการแก้ปัญหาที่อาจเกิดขึ้นระหว่างการอัปเกรดระบบ