نوشتن Bcheck با مثال واقعی

بخش صفر: چکیده

تا به حال سعی بر نوشتن یک افزونه Burp Suite کرده اید؟ در پست قبلی من (سفر من در رمزگشایی درخواست های رمزگذاری شده) باهم یک افزونه برای رمزگشایی یک عبارت رمزگذاری شده نوشتیم تا مراحل تست وب اپلیکیشن بسیار ساده تر و به کمک ابزارهای Burp Suite انجام شود. همانطور که مشاهده کردیم نوشتن یک افزونه برای اپلیکیشن Burp Suite کاری زمان بر است و به صرفه نیست که برای تسک‌های کوچک و ساده زمان زیادی را صرف نوشتن افزونه Burp Suite کنیم (و شاید حتی زمان کافی هم نداشته باشیم!). در این صورت چه می‌کنید؟ من تا قبل از آشنایی با Bcheck در صورت مواجه شدن با چنین سناریویی و در صورت وجود نداشتن زمان کافی، سعی بر نوشتن یک اسکریپت پایتون می‌کردم اما حالا باهم خواهیم دید که Bcheck چه تاثیری در کارهای روزمره شما (باگ بانتی، تست نفوذ و...) خواهد گذاشت.

بخش اول: Bcheck

Burp Scanner همراه پکیج‌های از پیش تعریف شده می‌آید که محدوده وسیعی از آسیب پذیری‌های مرسوم همچون SQLi و یا XSS را پوشش می‌دهد اما از آسیب پذیری‌های خاص تکنولوژی (Technology-Specific) همانند Log4J پشتیبانی نمی‌کند. برای افزودن این آسیب پذیری‌ها به Burp Scanner شما یا باید خوش شانس باشید که کسی در گذشته برای آن آسیب پذیری افزونه Burp Suite نوشته باشد یا اینکه خودتان برای آن آسیب پذیری خاص افزونه بنویسید. از نسخه 2023.6 به بعد، Bcheck برای نوشتن سریع افزونه و اضافه کردن آن به Burp Scanner معرفی شد. Bchecks در وبسایت PortSwigger اینگونه تعریف شده است:

BChecks are custom scan checks that you can create and import. Burp Scanner runs these checks in addition to its built-in scanning routine, helping you to target your scans and make your testing workflow as efficient as possible.

 Bcheck از منوی Extensions در نرم افزار Burp Suite قابل دسترسی است.


 در قسمت بعدی آسیب پذیری Dom-based XSS را در سامانه ساز مروارید معرفی کرده و سپس یک Bcheck برای آن می‌نویسیم و با زبان و ساختار Bcheck آشنا می‌شویم.

 بخش دوم: Dom-XSS در سامانه ساز مروارید

مدتی پیش از من خواسته شد تا یک وب اپلیکیشن که توسط سامانه ساز مروارید ساخته شده بود را بررسی کنم. در حین این عملیات چند آسیب پذیری Dom XSS کشف شد. مسئله وقتی جالب شد که متوجه شدم تمامی اپلیکیشن‌های پیاده سازی شده توسط این پنل (شرکت سامانه ساز مروارید) آسیب پذیر هستند.

این آسیب پذیری از تکه کد HTML زیر شروع می‌شود:

<body onload=onLoad();>

 پس از لود شدن کد‌های HTML، تابع ‌onLoad صدا زده می‌شود. در تابع onLoad داریم:

function onLoad() {
var url_string = location.href;
var url = new URL(url_string);
var myParam = htmlEncode(url.searchParams.get("param"));
var myroute = htmlEncode(url.searchParams.get("route"));
var params = htmlEncode(url.search.replace('?',''));
/** SOME STUFF HERE **/
params = filterRoute(params);
myroute = filterRoute(myroute);
myParam = filterRoute(myParam);

var div = document.createElement('div');
div.innerHTML = '<div><app-root inputParam="'+params+ 
                  '" inputcomponenename="'+myroute+'/' + myParam+'">';
document.getElementById("agLoad").appendChild(div);
/** SOME STUFF HERE **/

}

در نگاه اول متوجه یک Sink آسیب پذیر به XSS به نام innerHTML می‌شویم که ظاهرا درحال نوشتن محتویات تگی از نوع div با استفاده از پارامترهای موجود در URL است. یکی از کاربردهای تابع innerHTML، جایگزین کردن (Replacing) محتویات یک المنت HTML است. انجام این عمل با استفاده از متغییرهای تحت کنترل کاربر یک ریسک امنیتی را به کد معرفی می‌کند.

ما تا اینجا توانسته‌ایم تا یک Sink آسیب پذیر پیدا کنیم. قدم بعدی این است که بررسی کنیم که آیا Source تحت کنترلی وجود دارد که در نهایت به این Sink آسیب پذیر برسد؟

در ابتدای تابع onLoad، مسیر حال حاضر اپلیکیشن در متغیر url_string ذخیره  و سپس یک Object از نوع URL توسط آن ساخته می‌شود. عملکرد این Interface در واقع Parse کردن یک URL و راحتی در دسترسی به بخش‌های مختلف آن URL است.

در ادامه پارامترهای موجود در URL توسط تابع searchParams استخراج و به عنوان ورودی به تابع htmlEncode ارسال می‌شوند. در نگاه اول، این کار برنامه نویس برای جلوگیری از وقوع آسیب پذیری‌های Injection همانند XSS صورت گرفته است. برای بررسی صحت این امر، کد این تابع را مورد بررسی قرار می‌دهیم:

function htmlEncode(input) {
let doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}

با کمک گرفتن از ChatGPT متوجه می‌شویم که این تابع به طور خلاصه، یک رشته HTML (ورودی) می گیرد، آن را با استفاده از DOMParser تجزیه می‌کند و سپس محتوای متن عنصر HTML ریشه را برمی گرداند.

همانطور که در تصویر بالا می‌بینید، امکان استفاده از تگ‌های HTML برای رسیدن به XSS وجود ندارد.

در ادامه‌ی تابع onLoad، تابع filterRoute روی مقادیر متغیرهای params، myroute و myParam اجرا شده و مقادیر این متغیرها را جایگزین می‌کند. در تکه کد زیر می‌توانید محتویات تابع filterRoute را مشاهده کنید:

function filterRoute(inRoute) {
if(inRoute == '' || inRoute == undefined || inRoute == null){
return '';
}
if(inRoute.toString().indexOf('<') > -1 ){
return '';
}else return inRoute;
}

در ابتدای این تابع شرطی وجود دارد که در صورت خالی بودن، undefined و یا null بودن متغیر ورودی، تابع رشته‌ای خالی را به عنوان خروجی برمی‌گرداند. در ادامه شرطی دیگر وجود دارد که در صورت وجود کاراکتر '>' در ورودی، رشته‌ای خالی را به عنوان خروجی برگرداند. در حقیقت هدف این تابع جلوگیری از وقوع XSS با رد کردن رشته‌هایی است که کاراکتر '>' در آنها وجود دارد.

 در نهایت در انتهای تابع onLoad ورودی ما با گذر کردن از دو شرط تدافعی به Sink آسیب پذیر innerHTML می‌رسد. اما آیا اکسپلویت کردن XSS با وجود آن دو شرط قابل انجام است؟

بله! با استفاده کردن از Eventهای HTML همانند onmouseover. بگذارید نگاهی دقیق‌تر به ‌Sink آسیب پذیر بیندازیم:

div.innerHTML = '<div><app-root inputParam="'+params+
 '" inputcomponenename="'+myroute+'/' + myParam+'">

همانطور که بررسی کردیم، نشانه‌ای از وجود مانعی برای جلوگیری از وارد کردن عبارت '" (یک Quote و یک Double Quote) دیده نشد! حال چه می‌شود که ما پارامتر زیر را به سمت سرور ارسال کنیم؟

?route='"/onmouseover=alert(origin)//


بخش سوم: نوشتن Bcheck

برای نوشتن یک Custom Scanner با استفاده از Bcheck ابتدا باید با ساختار و زبان آن آشنا شویم.

Bcheck از Indentation برای جدا سازی بلاک‌های کد استفاده می‌کند. برای توضیح بیشتر، Bcheck موجود در این لینک استفاده می‌کنیم.

این Bcheck برای آسیب پذیری Dom-based XSS در سامانه ساز مروارید نوشته شده است. این آسیب پذیری تمامی پنل‌های ساخته شده توسط شرکت "شرکت سامانه ساز مروارید" را تحت تاثیر قرار می‌دهد.

metadata section of bcheck

در بخش ابتدایی کد قسمت Metadata را مشاهده می‌کنیم. همانطور که از نامش پیداست از این قسمت برای اضافه کردن اطلاعات Bcheck استفاده می‌کنیم. این Object از ویژگی‌های زیر پشتیبانی می‌کند:

  • language: قسمتی اجباری است و ورژن زبان استفاده را در آن قرار می‌دهیم.
  • name: قسمتی اجباری است و اسمی را که برای Bcheck انتخاب کرده‌ایم را در این قسمت قرار می‌دهیم.
  • description: توضیحات Bcheck را در این قسمت وارد می‌کنیم.
  • author: همانطور که از نامش حدس زدید، این قسمت برای اضافه کردن اسم نویسنده Bcheck است.
  • tags: تگ‌های مرتبط با Bcheck را در این قسمت وارد می‌کنیم.

 در ادامه سراغ قسمت اصلی کد خود می‌رویم:


این قسمت از Bcheck مهم‌ترین قسمت کد و قسمتی است که کار اصلی در آن انجام می‌شود. همانطور که در تصویر بالا مشاهده می‌کنیم، این قسمت از کد با عبارت run for each شروع شده است. در Bcheck عبارت‌‌های این چنینی یک Control flow گفته می‌شود. این قسمت کنترل اجرای Bcheck را بر عهده دارد.

در ادامه قسمت‌های مشخص شده را تعریف می‌کنیم و به توضیح هر یک می‌پردازیم.

run for each

 این قسمت برای تعریف متغیرهایی از جنس آرایه استفاده می‌شود. هنگامی که متغیر فراخوانی می شود، Bcheck یک بار برای هر آیتم در آرایه اجرا می شود.

در تصویر بالا و در بخش ۱، ما قسمت اصلی Bcheck را با تعریف آرایه‌ای به نام vulnerable_path در قسمت  run for each شروع می‌کنیم. مسیرهایی که در این متغیر قرار گرفته‌اند مسیرهایی هستند که به Dom-based XSS آسیب پذیرند. هنگام استفاده از این متغیر در بخش‌های پایین‌تر، چک برای تمامی آنها اجرا خواهد شد.

define

از این قسمت برای معرفی متغیرهای Bcheck استفاده می‌کنیم. همانطور که در بخش دوم از تصویر بالا مشاهده می‌کنید، متغیری با نام xss_paylaod تعریف می‌کنیم و پیلود مورد نظر خود را در آن قرار می‌دهیم.

given...then

این بخش تعیین می‌کند که یک Bcheck چه زمانی (بر روی چه چیزهایی) اجرا شود. هر Bcheck نوشته شده باید یک عبارت given / then داشته باشد. در این بخش می‌توانیم از عبارات زیر استفاده کنیم:

  • given request then: به این معنی‌است که این Bcheck برای هر درخواست (Request) در حال بررسی، اجرا می شود.
  • given response then: به این معنی‌است که این Bcheck برای هر پاسخ (Response) در حال بررسی، اجرا می شود.
  •  given host then: چک برای هر هاست در حال بررسی (Audit) اجرا می‌شود.
  • given path then: چک برای هر مسیر منحصر به فرد اجرا می‌شود.
  • given any insertion point then: چک برای هر محل درج شده اجرا می‌شود.
  • given query insertion point then: چک برای هر Query در حال بررسی اجرا می‌شود.
  • given header insertion point then: چک برای هر Header در حال بررسی اجرا می‌شود.
  • given body insertion point then: چک برای هر قسمت از بدنه درخواست اجرا می‌شود.
  • given cookie insertion point then: چک برای هر کوکی درحال بررسی اجرا می‌شود.
  • همچنین شما می‌توانید از عبارت or برای ترکیب Insertion point ها استفاده کنید.
در بخش سوم از تصویر بالا، ادامه Bcheck را با عبارت given host then شروع می‌کنیم. این عبارت به این معنی‌است که چک نوشته شده توسط ما، روی تمامی هاست‌های درحال Audit اجرا خواهد شد.
 

send request

در قسمت چهارم از تصویر ما شاهد عبارت زیر هستیم:
send request called check:
 این عبارت در Bcheck به Actions معروف است. اکشن‌ها کلماتی هستند که به Burp Scanner درخواست انجام کاری همانند ارسال درخواست HTTP را می‌دهند. برای ادامه بهتر است کمی در جزئیات این بخش متمرکز شویم. شما در نوشتن Bcheck می‌توانید از عبارات اکشن زیر استفاده کنید.

 send request

این اکشن به ما امکان ارسال درخواست HTTP همراه با امکان ایجاد تغییرات در درخواست HTTP را می‌دهد.
در قسمت سوم تصویر ما درحال ایجاد یک درخواست HTTP به نام check با مشخصه‌های زیر هستیم:
send request called check:
method: "GET"
path: {vulnerable_path}
#queries: "param=oauth'\"/onmouseover=alert(origin)//"

 همانطور که از نام‌هایشان حدس زدید، ما درحال ساختن و ارسال درخواست GET به نام check، به هاست‌های درحال بررسی و به مسیر vulnerable_path همراه پیلود خود هستیم.

توجه داشته باشید که ارسال پیلود به عنوان پارامتر نیاز نیست، چرا که این آسیب پذیری از نوع DOM XSS است.

علت نام گذاری این درخواست HTTP این است که ما به Response سرور برای بررسی آسیب پذیر بودن یا نبودن نیاز داریم.

send payload

این اکشن همراه با عبارت given insertion point استفاده می‌شود. با استفاده از این اکشن می‌توانید یک درخواست جدید ارسال و پیلود مورد نظر را به درخواست اضافه (Append) و یا جایگزین (Replace) کنید.

 report issue

 این اکشن باعث می‌شود تا Burp Scanner یک Issue در قسمت Issues ایجاد کند. در این اکشن می‌توانیم از کلمات کلیدی زیر برای تعریف Issue استفاده کنیم:
  • severity: تعیین کننده درجه حساس بودن آسیب پذیری است. در این قسمت می‌توان از کلمات high، medium، low و info استفاده کرد.
  • confidence: نشادهنده میزان اطمینان از احتمال وجود آسیب پذیری است که می‌تواند certain، firm و یا tentative باشد.
  • remediation: در این بخش توضیحات لازم برای جلوگیری/اصلاح آسیب پذیری را وارد می‌کنیم.
  • detail: در این قسمت اطلاعات بیشتری را نسبت به آسیب پذیری یافت شده را وارد می‌کنیم.

هنگام استفاده از این اکشن توجه داشته باشید که Bcheck پس از رسیدن به این اکشن و گزارش کردن Issue، بررسی را به اتمام می‌رساند حتی اگر قسمت‌های بدون بررسی باقی مانده باشد.

report issue and continue 

همانند اکشن report issue است با این تفاوت که Bcheck پس از گزارش کردن آسیب پذیری به اتمام نمی‌رسد و به بررسی باقی قسمت‌ها می‌پردازد. در قسمت ۶ از تصویر داریم که:
 

conditionals

یکی از مهم‌ترین ویژگی‌های Bcheck امکان استفاده از عبارات شرطی است. این عبارات هستند که به ما امکان انجام کاری درصورت صحیح بودن یک شرط را می‌دهند. به بخش پنجم از تصویر توجه کنید:


در این قسمت دو شرط را با استفاده از عملگر and ترکیب کرده و در صورت صحیح بودن شرط، یک Issue با استفاده از اکشن report issue and continue صادر می‌کنیم. این دو شرط عبارتی هستند که منجر به آسیب پذیری DOM XSS می‌شوند که در فصل دوم مقاله بررسی کردیم.
Bcheck از عبارات شرطی زیر پشتیبانی می‌کند:
  • if... then:در صورت صحیح بودن شرط مقابل if، یک عملیات (Action) را انجام می‌دهد.
  • else if... then: این عبارت داخل عبارت if... then استفاده شده و هنگامی اجرا می‌شود که شرط قبل از خود نادرست و حاصل شرط else if... then صحیح باشد.
  • else then: این عبارت شرطی نیز داخل یک عبارت شرطی if... then قرار می‌گیرد و درصورتی اجرا می‌شود که هیچ‌کدام از عبارات شرطی داخل if... then صحیح نباشد.
  • end if: نمایانگر پایان عبارت شرطی if... then است.

شما در نوشتن عبارات شرطی خود می‌توانید از عبارت‌های منطقی زیر استفاده کنید:

  • A matches REGEX: امکان استفاده از Regex ها یکی دیگر از قابلیت‌های فوق العاده Bchecks است. این عبارت هنگامی صحیح است که A با رجکس موجود همخوانی داشته باشد.
  • A differs from B: این عبارت هنگامی صحیح است که پیام پاسخ (HTTP Response) A با B متفاوت باشد.
  • A in B: هنگامی صحیح است که مقدار A در B موجود باشد. همانطور که در تصویر بالا مشاهده کردید ما درحال استفاده از این عبارت برای بررسی وجود داشتن دو عبارت خاص در پاسخ HTTP هستیم.
  • A is B: در صورتی صحیح است که A و B یکسان باشند.

با استفاده از عبارات زیر در شرط خود همچنین می‌توانید Action های خود را بر اساس پیام‌های دریافت شده توسط Burp Collaborator اجرا کنید:

  • any interactions: هنگامی که Burp Collaborator هر پیامی دریافت کند، این عبارت مقدار صحیح (True) بر می‌گرداند.
  • dns interactions: این عبارت هنگامی صحیح (True) است که Burp Collaborator یک درخواست DNS دریافت کند.
  • http interactions: هنگامی صحیح است که Burp Collaborator یک پیام HTTP دریافت کند.
  • smtp interactions: این عبارت هنگامی صحیح است که Burp Collaborator یک پیام SMTP دریافت کند.

در نهایت ما با استفاده از عملگرهای منطقی and، or و not می‌توانیم عبارات شرطی خود را با یکدیگر ترکیب و به نتیجه دلخواه خود برسیم.


بخش چهارم: نتیجه گیری

در هنگام نیاز به یک افزونه، جایی که حجم کار کم و مدت زمان انجام کار کوتاه است، نوشتن افزونه با استفاده از Bcheck نجات دهنده است. همانطور که مشاهده کردیم Bcheck با استفاده از ساختاری خوانا، ساده و کوتاه به کمک ما می‌آید تا بتوانیم در کوتاه ترین زمان ممکن، به بهترین نتیجه برسیم. 

نسخه نهایی این Bcheck در آدرس گیتهاب من موجود است.

و در نهایت از راهنمایی و حمایت جناب آقای کشفی استاد و راهنمایم کمال تشکر را دارم. همه دستاوردهایم را مدیون او هستم.

بخش نهایی: تایم‌لاین 

January 13, 2024: گزارش این آسیب پذیری به ایمیل موجود در سایت سامانه ساز مروارید ارسال شد.

January 15, 2024: ایمیلی مطابق تصویر زیر از سمت سامانه ساز مروارید دریافت شد:

February 4, 2024: ایمیلی از طرف من مبنی بر انتشار این پست برای شرکت ارسال شد. پاسخی دریافت نشد.

February 9, 2024: ایمیلی از طرف من برای دریافت آپدیتی از سمت شرکت ارسال شد. همچنان بدون پاسخ.

February 12, 2024: ایمیلی از طرف من برای دریافت آپدیت و اطلاعات بیشتر روی Fix احتمالی ارسال شد.

March 9, 2024: تا به این لحظه هیچ ایمیلی از طرف شرکت سامانه مروارید مبنی بر انتشار آپدیت یا اطلاعاتی از وجود آپدیت احتمالی به دست من نرسیده است.

نظرات

Popular Posts

سفر من در رمزگشایی درخواست های رمزگذاری شده