การทดสอบแฮกโดยใช้ลินุกซ์ Nebula

Pichaya Morimoto
4 min readMay 27, 2016

สารบัญ

0x01 — การทดสอบแฮกโดยใช้ลินุกซ์ Nebula

0x02 — Nebula เลเวล 00: หาโปรแกรม SUID ทดสอบยกระดับสิทธิ์แบบง่าย ๆ

0x03 — Nebula เลเวล 01: ลองแฮกช่องโหว่โปรแกรมด้วย $PATH

0x04 — Nebula เลเวล 02: ลองแฮกช่องโหว่ cmd injection + shell variable

0x05 — Nebula เลเวล 03: ลองแฮกช่องโหว่ใน crontab

0x06 — Nebula เลเวล 04: ลองแฮก bypass blacklist filter ชื่อไฟล์

0x07 — Nebula เลเวล 05: ลองแฮกจาก SSH private key

0x08 — Nebula เลเวล 06: ลองแคร๊กรหัสผ่าน Unix-Crypt

0x09 — Nebula เลเวล 07: ลองแฮกช่องโหว่ command injection บนเว็บ perl-cgi

0x10 — Nebula เลเวล 08: มาลองแฮกทำ network forensics

0x11 — Nebula เลเวล 09: มาลองแฮกช่องโหว่ใน PHP

Nebula เป็น ลินุกซ์ (Linux) ที่ออกแบบมาเพื่อจำลองช่องโหว่ (vulnerability) ต่าง ๆ มาให้ลองแฮกกัน โดยจะเน้นเป็นในมุมมองของ ผู้โจมตี (attacker) อยู่ในเครื่องเดียวกับ เป้าหมายแล้ว แต่จะต้องการยกระดับสิทธิ์ (privilege escalation) โดยอาศัยการตั้งค่าที่ไม่ปลอดภัย (security misconfiguration) ในแบบต่าง ๆ ตัวอย่างช่องโหว่ที่ควรจะรู้หรือสิ่งที่จะได้เรียนรู้ในระหว่างการเล่น Nebula ก็เช่น..

1. Permissions

สิทธิ์ของไฟล์ในระบบ (ในทีนี้จะพูดถึงแต่ลินุกซ์เป็นหลัก) โดยในลินุกซ์โดยพื้นฐานแล้วจะมีวิธีแบ่งกำหนดสิทธิ์ไฟล์แต่ละอันดังตัวอย่างต่อไปนี้

$ ls -lh /bin/cat
-rwxr-xr-x 1 root root 47K Mar 10 14:10 /bin/cat

ผลจากคำสั่ง ls จะเห็นว่าไฟล์โปรแกรม cat นั้นมีเจ้าของเป็น root (คำว่า root ด้านซ้าย), มีกลุ่มเป็นของ root (คำว่า root ด้านขวา), และมีสิทธิ์เป็น rwxr-xr-x ตรงนี้จะต้องแยกออกเป็น 3 ส่วนคือ rwx อันแรกเป็นสิทธิ์ของ เจ้าของไฟล์ สามารถ อ่าน (r:read) แก้ไข (w:write) และ สั่งให้ทำงาน/รันโปรแกรม (x:execute) ได้ ส่วน r-x อันถัดมาทางขวาเป็นสิทธิ์ของกลุ่ม สามารถอ่านได้ สั่งให้ทำงานได้แต่แก้ไขไม่ได้ และสุดท้าย r-x อันขวาสุดหมายถึงแบบเดียวกันกับสิทธิ์ของกลุ่มแต่ เป็นสิทธิ์ของคนอื่น ๆ ที่นอกเหนือจากเจ้าของไฟล์และกลุ่ม

การตั้งค่าสิทธิ์ของไฟล์อย่างไม่ปลอดภัย อาจทำให้เกิดปัญหาด้านความปลอดภัยตามมาได้อย่างชัดเจนมาก ตัวอย่างเช่นผู้ใช้งานชื่อ longcat อาจจะสามารถแก้ไขไฟล์หน้าเว็บของผู้ใช้งานชื่อ yumyum ที่อยู่บนเครื่องเดียวกันได้ ถ้ามีการตั้งค่าสิทธิ์ของไฟล์เว็บนั้นไว้อย่างไม่ปลอดภัยยอมให้ใครก็ได้ มีสิทธิ์เขียน (w:write) ได้ตัวอย่างเช่น

$ ls -lh myweb.html
-rwxrwxrwx 1 yumyum yumyum 12 May 27 13:53 myweb.html

จะเห็นว่าไฟล์ myweb.html ของ yumyum ถูกตั้งค่าเป็นสามารถ อ่าน-แก้ไข-สั่งให้ทำงาน โดยใครก็ได้ (rwx อันขวาสุด) แปลว่า ผู้ใช้งาน longcat ที่อยู่บนเครื่องเดียวกันก็มีสิทธิ์เข้ามาแก้ไขไฟล์นี้เช่นกัน จะเห็นว่าการตั้งค่าสิทธิ์แบบนี้ไม่ปลอดภัย ในกรณีนี้

2. SUID files

ไฟล์ SUID คือไฟล์โปรแกรม ที่มีการตั้งค่าสิทธิ์แบบ SUID bit ไว้ (จากนี้ขอเรียกย่อ ๆ ว่า SUID) ซึ่งเมื่อถูกเรียกใช้งานจะทำงานในสิทธิ์ของเจ้าของไฟล์ (มีอีกอย่างเรียกว่า GUID bit เมื่อถูกเรียกใช้งานจะทำงานในสิทธิ์ของกลุ่มของไฟล์)ในบางกรณีเราจำเป็นจะต้องใช้ SUID bit เพื่อให้โปรแกรมที่ถูกเรียกโดยผู้ใช้งานคนนึงทำงานเป็นสิทธิ์ผู้ใช้งานอีกคนนึงได้ (SUID ย่อมาจาก Set User ID up on execution) เช่น โปรแกรมที่ใช้ในการเปลี่ยนรหัสผ่าน passwd ใน Linux

$ ls -lh /usr/bin/passwd
-rwsr-xr-x 1 root root 46K Jan 26 19:50 /usr/bin/passwd

จะสังเกตเห็นว่า สิทธิ์ของเจ้าของไฟล์ตั้งไว้เป็น rws ซึ่งตัว s นี้แหละที่บ่งชี้ว่ามีการตั้งค่าสิทธิ์แบบ SUID bit ไว้ เหตุผลที่ต้องใช้ในกรณีนี้ก็เพราะว่า ในกระบวนการเปลี่ยนรหัสผ่านใน Linux นั้น จะต้องทำการแก้ไขไฟล์ shadow (อยู่ใน /etc/ )ที่เก็บค่า hash ของรหัสผ่านของผู้ใช้งานทุกคนในระบบ ซึ่งในการที่เราจะให้ผู้ใช้งานแต่ละคนเปลี่ยนรหัสผ่านตัวเองได้นั้น แน่นอนว่าเราไม่ได้หมายความถึงต้องการให้พวกเขามีสิทธิ์ในการอ่านหรือเขียนไฟล์ shadow ได้ตรง ๆ เพราะมันมีค่า hash ของรหัสผ่านคนอื่นอยู่ด้วย (ถ้าให้สิทธิ์นั้นไปผู้ใช้งานอาจแอบดูหรือแอบแก้รหัสคนอื่นได้)

ดังนั้น การทำ SUID bit จะทำให้ ตัวโปรแกรม passwd ที่มีเจ้าของเป็น root เมื่อถูกเรียกใช้งานโดยใครก็ตาม โปรแกรมนี้จะสามารถทำงานด้วยสิทธิ์ root ในขณะที่จะแก้ไขรหัสผ่านกับไฟล์ shadow ได้ โดยไม่ต้องให้สิทธิ์ผู้ใช้งานคนนั้น แก้ไขไฟล์ shadow ได้เอง แต่ว่าการตั้งค่า SUID bit ถ้าตั้งค่าในโปรแกรมที่มีช่องโหว่ หรือตั้งค่าบางอย่าง อย่างไม่ปลอดภัยแล้ว อาจทำให้ ผู้โจมตีระบบสามารถยกระดับสิทธิ์ตัวเองเป็นสิทธิ์เดียวกับเจ้าของไฟล์ได้ เช่นจากผู้ใช้งาน longcat ถ้าเรียกใช้งานโปรแกรม pwnies ที่ถูกตั้งค่า SUID bit ไว้แล้วมีเจ้าของเป็น root แล้วเกิดว่า โปรแกรม pwnies เขียนมาให้ดันรับค่า argument เพิ่มเติมเข้ามาแล้วเรียกโปรแกรอื่นได้ longcat อาจจะไปเรียก /bin/bash ทำให้ เปิด shell ในสิทธิ์ของ root ได้ (ภาษาลินุกซ์เรียกว่า spawn shell ต่อไปนี้จะขอเรียกคำนี้ละกัน)

3. Race conditions

race condition คำนี้ใครเคยเรียนวิชา ระบบปฏิบัติการ (OS:operating system) น่าจะคุ้นเคยกันดี จริง ๆ มันก็อันเดียวกันเป๊ะ แต่ตอนอาจารย์สอนเค้ามักจะสอนในว่ามันคือ การที่ process ใน OS มากกว่าหนึ่ง process พยายามจะเข้าถึง resource เดียวกัน เช่นไฟล์เดียวกันพร้อม ๆ กัน ทำให้อาจเกิดปัญหาได้ (นึกง่าย ๆ จะเกิดอะไรขึ้นถ้า มีโปรแกรมสองโปรแกรมในเครื่องเกิดอยากใช้ เครื่อง printer ที่มีอยู่เครื่องเดียว พร้อม ๆ กัน ต่างคนต่างไม่ยอมจะให้อีกโปรแกรมใช้ก่อน ตรงนี้ก็จะเกิด deadlock ไง) แล้วมันเกี่ยวกับแฮก เกี่ยวกับช่องโหว่ยังไง? ในโลกของ computer security มีการนำ แนวคิด แบบเดียวกันนี้ไปใช้ในการยกระดับสิทธิ์ของผู้โจมตีระบบได้ในหลาย ๆ สถานการณ์ตัวอย่างเช่น

ผู้ดูแลระบบใช้บัญชี root เรียกโปรแกรมชื่อ pwnies ตัวโปรแกรมนี้จะไปเขียนไฟล์ชั่วคราวไว้ใน /tmp/ ชื่อ script.sh แล้วเรียกใช้งานไฟล์นี้แล้วลบทิ้ง อย่างรวดเร็ว

จะเกิดอะไรขึ้นไฟล์ script.sh ตั้งค่าสิทธิ์ให้ใครก็ได้สามารถเขียนไฟล์ได้? ถ้าเป็นแบบนั้นช่องโหว่ของโปรแกรม pwnies ก็คือ… ผู้ใช้งานอีกคน longcat สามารถเขียนโปรแกรมขึ้นมาแล้ววนลูป พยายามจะสร้างไฟล์แล้วใส่คำสั่ง “useradd -G sudo longcat” เข้าไปใน script.sh? ถ้าเกิดว่าใน ขณะนั้นในจังหวะที่ longcat ใส่คำสั่งนี้เข้าไปในไฟล์แล้วโปรแกรม pwnies ดันไปเรียกใช้งานไฟล์นี้พอดี?

ผลคือจะทำให้ คำสั่งนี้ถูกสั่งทำงานด้วยสิทธิ์ root ในการทำ backdoor ที่เพิ่มผู้ใช้งาน longcat ให้อยู่ในกลุ่ม sudo ซึ่งหมายความว่า longcat จะสามารถมีสิทธิ์เทียบเท่า root ในระบบ ยกระดับสิทธิ์ได้สำเร็จครับ การที่ longcat พยายามจะเขียนไฟล์ script.sh ในห้วงเวลาระหว่างที่ pwnies สร้างไฟล์เสร็จแล้วและกำลังจะรันไฟล์นั้น เราเรียกว่าการโจมตีแบบ race condition ครับ

4. Shell meta-variables

ในลินุกซ์ shell นั้น เราสามารถตั้งค่าตัวแปร (variable) ได้ซึ่งค่าเหล่านี้บางคนจะเรียกว่า shell environment variable มันจะสามารถที่จะถูกเรียกใช้งานโดยโปรแกรมอื่น ๆ ได้ ตัวอย่างเช่นถ้าเราจะดูว่ามีตัวแปรอะไรใน shell เราอยู่บ้างสามารถทำได้โดย…

$ env
SHELL=/bin/bash
USER=longcat
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/longcat/
HOME=/home/longcat
[…]

จะเห็นว่าในตัวอย่างด้านบนการพิมพ์คำสั่ง env จะแสดงตัวแปรต่าง ๆ มากมายพร้อมค่าที่ถูกตั้งไว้อยู่ ตัวอย่างช่องโหว่ที่ไม่ปลอดภัยก็เช่นว่า ถ้าโปรแกรมที่ทำงานด้วย SUID bit ของผู้ใช้งานที่มีสิทธิ์สูง (ตัวอย่างง่าย ๆ ก็ root) มีการรับค่าตัวแปรจาก shell ไปประมวลผล แล้วลืมคำนึงไปว่าค่าพวกนี้อาจถูกแก้ไขได้ อาจจะทำให้เกิดช่องโหว่ต่าง ๆ ได้ เช่น ถ้าโปรแกรมชื่อ pwnies ทำงานด้วย SUID bit ของ root แล้วรับค่าจากตัวแปร yumyum ไปรันเป็น argument ของอีกคำสั่งของ command นึงในโปรแกรม ถ้า ผู้ใช้งาน longcat ตั้งค่าตัวแปร yumyum เป็น `/bin/bash` (โดยใช้ \ มาช่วย escape นะครับเวลาพิมพ์ ` ใน shell ที่จะหมายถึง string ธรรมดา ไม่งั้นมันจะเป็นความหมายถึงการสั่งให้โปรแกรมทำงานใน shell แทน)

export yumyum=\`/bin/bash\`

ใส่เข้าไปก็อาจทำให้ โปรแกรม pwnies ทำการ spawn shell ของ root ออกมาทำให้ ผู้ใช้งาน longcat สามารถยกระดับสิทธิ์เป็น root ได้

5. $PATH weaknesses

$PATH เป็นตัวแปรนึงใน shell meta-variable ในข้อ 4 ที่มักจะเป็นที่นิยมในการถูกใช้ในการแฮกยกระดับสิทธิ์มากเป็นพิเศษ ขออธิบายก่อนว่า $PATH คืออะไร.. มันคือตัวแปรที่ เวลาผู้ใช้งานพิมพ์คำสั่งใด ๆ ลงไปใน shell ตัวอย่างเช่นพิมพ์คำว่า ls ลงไป

$ ls

จริง ๆ แล้วคำว่า ls ที่ถูกพิมพ์ในทีนี้เจ้า shell มันจะไปหาใน directory ในตัวแปร $PATH ว่ามีไฟล์ชื่อ ls รึเปล่า… ถ้าย้อนกลับไปดูข้อ 4 จะเห็นค่าของ $PATH เป็น

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/longcat/

ซึ่งหมายความว่า shell จะไปหาใน /usr/local/sbin/ ว่ามีไหม ไฟล์ชื่อ ls ถ้ามีให้สั่งให้ทำงาน ถ้าไม่มีไปหาใน /usr/local/bin/ ต่อ ไล่จากซ้ายไปขวาคั่นด้วยเครื่องหมาย โคลอน (:) ต่อไปเรื่อย ๆ ถ้าหาจนถึงสุดท้าย /home/longcat/ แล้วยังไม่เจอไฟล์ชื่อ ls เจ้า shell ก็จะตอบกลับมาว่า…

ls: command not found

คือหมายถึงหา ls ใน directory ที่บอกใน $PATH หมดแล้วนะ แต่ไม่เจอ แต่ว่าในความเป็นจริง จะเจอโปรแกรม ls อยู่ใน /bin/ และเรียกขึ้นมาใช้งานได้ ดังนั้นถ้าเราเขียนโปรแกรมชื่อ pwnies แล้วเรียกใช้งาน ls ตรง ๆ เช่น

system("ls");

ด้วยการที่คนเขียนโปรแกรมมือใหม่ มักจะเรียกโปรแกรมอื่น ในโปรแกรมของพวกเขาแบบนี้ โดยการไม่ได้ใส่ absolute path เต็ม ๆ ไปว่า /bin/ls ทำให้ ผู้โจมตีระบบสามารถตั้งค่า $PATH ของตัวเองเป็น /home/longcat/hack/ ด้วยคำสั่ง

$ mkdir -p /home/longcat/hack/
$ export PATH=/home/longcat/hack/

แล้วทำสำเนาโปรแกรม /bin/bash ในชื่อ ls แทนด้วยคำสั่ง

$ cp /bin/bash /home/longcat/hack/ls

ทำให้โค้ดในโปรแกรม pwnies บรรทัดที่ว่า system(“ls”); แทนที่จะไปเรียกใช้งานโปรแกรม ls ที่ควรจะเป็น /bin/ls ที่โชว์รายชื่อไฟล์ กับกลายเป็นไปเรียกใช้งาน /home/longcat/hack/ls แทน และ เมื่อโปรแกรม pwnies ถูกตั้ง SUID bit เป็นของ root แล้วละก็ จะทำให้ผู้ใช้งาน longcat สามารถยกระดับสิทธิ์ตัวเองเป็นผู้ดูแลระบบในสิทธิ์ root ได้โดยการ spawn root shell ครับ

6. Scripting language weaknesses

ในหัวข้อนี้จะหมายถึง ช่องโหว่ ที่เกิดจากโค้ดในภาษาเชิง scripting ที่เรียกใช้งานโค้ดผ่าน interpreter ได้โดยไม่ต้อง compile ก่อนเช่น Perl, Ruby, Python ครับ

ในแต่ละภาษาก็จะมีจุดอ่อน ที่ถ้าเขียนโปรแกรมมาไม่ดีก็อาจจะถูกโจมตีเพื่อยกระดับสิทธิ์ในระบบได้เช่นกัน ในทีนี้ขอละไว้เดี๋ยวจะอธิบายโดยละเอียดอีกทีเป็นกรณี ๆ ไปในบทความครั้งต่อไปครับ

7. Binary compilation failures

ในหัวข้อนี้จะหมายถึง ช่องโหว่ ที่เกิดจากการที่ compile โปรแกรมในภาษา C/C++ แล้วไม่ได้ใส่ option เพื่อความปลอดภัย เช่นถ้า compile ด้วย gcc บนลินุกซ์สามารถใส่ option เพื่อ optimize อย่าง…

  • -fstack-protector ช่วยในป้องกันการโจมตีด้วย buffer overflow
  • -D_FORTIFY_SOURCE=2 ช่วยป้องกันการโจมตีด้วย buffer overflow
  • -­Wformat ­-Wformat­security ช่วยในการแจ้งเตือนตอน compile ว่ามีความเสี่ยงจะถูกโจมตีด้วยช่องโหว่ format string
  • -fPIE -pie เปิดใช้งาน ASLR สุ่มค่าใน memory เวลาโปรแกรมทำงาน ช่วยป้องกันการโจมตีด้วย buffer overflow

ใครสนใจเรื่อง gcc option นี้ดูเพิ่มเติมได้ในคู่มือ binary hardening ของ Debian ครับ

ที่มา: https://exploit-exercises.com/nebula/

--

--