בבלוג זה אציג ממצא אותו מצאתי יחד עם דקלה ברדה ב-PayPal אשר מאפשר לתוקף זדוני לבצע מניפולציה על חשבוניות ובכך לקבל תשלום על מוצרים במקום המוכר.
בבלוג זה תראו כיצד:
- עקפנו את מנגנון ה-captcha של PayPal
- בצענו Brute Force באמצעות VPN על חשבוניות
- בצענו מניפולציה על הפרמטרים של החשבונית וקיבלנו את התשלום
Technical
פתחנו חשבון במערכת הבדיקות של PayPal כדי שנוכל לבצע מניפולציה על פעולות שמצריכות כסף. הדבר נעשה על ידי כניסה לאתר הבא:
https://www.sandbox.paypal.com
לאחר שהצלחנו לבצע את המניפולציה ניסינו לבצע את אותו הדבר ב-Domain המרכזי:
https://www.paypal.com
הממצא מתחיל במחקר הפונקציונאליות השונה שקיימת בPayPal-, כך הגענו לחשבונית, והתחלנו לבחון את מנגנון התשלום לחשבוניות שנוצרות בעת רכישת מוצר.
המבנה של לינק לחשבונית הינו:
https://www.paypal.com/invoice/payerView/details/INV2-XXXX-XXXX-XXXX-XXXX
כל אחד יכול לגשת ללינק אם הוא יודע מה הכתובת אליו.
כך ניסינו לבדוק האם אנו יכולים לאתר חשבוניות של משתמשים אחרים, כמות התווים היא יחסית גדולה עבור ביצוע brute force, ובדרך כלל לבצע brute force לכמות כזאת של תווים זה חסר תועלת לחלוטין.
אך עקב העובדה שבPayPal- רשומים מאות מיליוני משתמשים ועשרות מיליוני מוכרים וכל מוכר יוצר חשבונית על כל מוצר שקונים ממנו, שלא נדבר על כמות המוצרים שהסינים מוכרים ב-eBay באמצעות PayPal, כך יוצא שקיימות כמה מאות מיליוני חשבוניות במערכת מה שמקל על תהליך ה-brute force.
ניסינו לבצע בדיקה ולבחון כמה זמן ייקח לנו לפגוע בחשבונית אחת לפחות, בצענו זאת בשביל האתגר ועל מנת להכניס את הנתון למחקר שאנו מבצעים טרם הדיווח ל-PayPal על ליקוי האבטחה.
אך לאחר מספר ניסיונות brute force נתקלנו במנגנון captcha לא שגרתי, נראה ש-PayPal החליטו ליצור מנגנון captcha אותנטי משלהם:
אם אנו מזינים את הטקסט הכתוב ומאשרים את ה-captcha, אנו נראה שהתווסף הפרמטר grgrpt בפורמט base64 בשורת הכתובות:
Z3JncnB0=
מה שנראה כך:
כך שעל מנת לעקוף, את מנגנון ה- captcha הזה כל מה שהיה עלינו לעשות הוא פשוט להוסיף לשורת הכתובות את הפרמטר הבא ברגע שמופיע captcha:
Z3JncnB0=
ובכך ה-backend של PayPal מסיק שהזנו את ה- captcha בצורה נכונה.
לאחר שעקפנו את מנגנון ה-captcha בקלות רבה יחסית, חזרנו לבצע את הBrute Force- על החשבוניות, לכאורה ללא כל בעיה עד אשר נתקלנו בחסימת IP שלא ציפינו לה.
מסתבר ש-PayPal מבצעת חסימת IP לאחר פרק זמן של כרבע שעה של brute force ומשחררת את ה-IP לאחר פרק זמן מסוים.
כך שלעקוף captcha אינו מספיק על מנת להשיג חשבוניות אלא אנו צריכים גם לעקוף חסימת IP.
על מנת לעשות זאת נרשמנו ל-ZoroVPN ושדרגנו את סקריפט ה-python הפשוט שלנו שביצע את ה- brute force.
הרעיון המרכזי שעומד מאחורי ה-script מתחלק ל-2:
השרת המנהל:
- יוצרים רשימה רנדומלית של תוקנים (יש יותר סיכוי לפגוע ככה מאשר לבצע brute force רציף) בשרת המרכזי שמנהל את הרשימה, מנקים את הרשימה מכפילויות (כמעט ולא נתקלנו בכאלה) ושומרים אותה בקובץ על מנת שלא נחזור על תוקן שנבדק.
- כל פעם שולחים רשימה של 10,000,000 תוקנים לאחד משרתי ה-brute force ב-Queue השרתים שלנו.
- במידה ואחד השרתים מוצא תוקן הוא מחזיר אותו לשרת המנהל לרשימת התוקנים התקינים.
השרת המבצע:
- מקבל רשימה של 10,000,000 תוקנים ומתחיל לבצע brute force.
- במידה ונתקל בcaptcha- מוסיף את הפרמטר Z3JncnB0= בשורת הכתובות.
- במידה ונחסמה כתובת ה-IP של השרת מחליפים כתובת IP באמצעות ZoroVPN.
- במידה ומצאנו תוקן תקין שולחים לשרת המנהל.
- בסוף ריצה אחת על כל עשר מיליון תוקנים תתבצע הדפסה על המסך של כמות התוקנים שנמצאו בריצה אם נמצאו בכלל.
לאחר שהצלחנו למצוא 2 תוקנים בריצה של כמעט יומיים (כ-40 שעות ריצה), שזה מוכיח שאכן ניתן למצוא תוקנים באמצעות brute force עברנו לשלב המניפולציה.
בשלב המניפולציה תחילה אנו יוצרים חשבונית ולאחר מכן אנחנו עורכים אותה על ידי לחיצה על edit על מנת שנוכל לבצע את המניפולציה על כל הפרמטרים ולא רק על אלה שאנו רואים ב-UI.
לאחר שבחנו את כל הפרמטרים לעומק בקבלה שיצרנו עלינו להתאים אותה לקבלה שאנו מבצעים לה שיוך לחשבון שלנו, הגענו למסקנה שעלינו לערוך את הפרמטרים הבאים על מנת להצליח בשיוך הקבלה:
• invoiceNumber – עורכים את הפרמטר למספר כלשהו שאינו בשימוש
• UnitPrice/TotalAmount – עורכים את הפרמטר לסכום התשלום שעל הלקוח יהיה לשלם
• (emailAddress(buyer – פרמטר זה עלינו לשנות למייל של הקונה מהקבלה שאנו מעבירים לחשבון שלנו
• businessName/firstname/lastname – פרמטר זה עלינו לשנות למייל של המוכר מהקבלה שאנו מעבירים לחשבון שלנו
• (emailAddress(seller – זה בעצם המייל של מי שיקבל את הכסף בסופו של דבר, לכן כאן נכתוב את המייל שלנו
• encryptedInvoiceId – פרמטר זה אנו משנים לתוקן של הקבלה שאנו מעבירים אלינו
מה שיראה כך:
כתוצאה משליחת הקבלה לצד השרת של PayPal היא תעבור שיוך מחדש ותהיה שייכת מעתה לחשבון התוקף ולא לחשבון המוכר האמיתי.
מבחינת ה-UI, ב-PayPal טרם ביצוע התשלום דבר לא ישתנה הן בחשבון הקונה והן בחשבון המוכר.
במידה והקונה משלים את תהליך התשלום:
- צד המוכר – הקבלה נשארת במצב unpaid.
- צד הקונה – הקונה מקבל מייל מ-PayPal שהתשלום עבר בהצלחה ובמערכת נראה שהוא ביצע את התשלום בצורה תקינה.
- צד התוקף – התשלום על הקבלה יעבור במלואו לתוקף ואפילו PayPal יגזרו עמלה על הפעולה!
כך הצלחנו לבצע מניפולציה על קבלות בPayPal.
דיווחנו ל-PayPal והם הגיבו באחריות ותקנו את הממצא.