مقدمه
Cross Site Scripting یا XSS، از دسته حملات بررسی ورودی های کاربر است. در این حمله، اثر ورودی کاربر در سمت کلاینت یا سرور یا هردو، مورد بررسی قرار گرفته و در صورت عدم اعتبارسنجی ورودی کاربر، مهاجم از این ورودی برای تزریق ورودی آلوده خود بهره می برد. حملات اعتبارسنجی ورودی کاربر، XSS، SQLi، HTTP Header Tampering و ... را دربر می گیرد.
حمله XSS حمله ای است که مهاجم در آن هدف تزریق HTML یا اجرای کد جاوااسکریپت در مرورگر کاربر مشاهده کننده یک صفحه آسیب پذیر را دارد.
انواع حملات XSS
XSS بازتابی (Reflected XSS)
رایج ترین نوع آسیب پذیری XSS است. این حمله زمانی رخ می دهد که داده کاربر به یک وب اپلیکیشن فرستاده شده و بلافاصله در وب اپلیکیشن انعکاس داده می شود. سپس مرورگر، کد را از پاسخ وب سرور گرفته و آن را رندر می کند. بدیهی است که این آسیب پذیری در کد سمت سرور رخ میدهد.
در این نوع حمله، فرد قربانی بایستی از طریق مرورگر خود و درخواست HTTP، Payload را درون صفحه وب تزریق کند و سپس وب سرور پاسخ با کد آلوده را برگرداند و مرورگر کاربر قربانی آنرا اجرا نماید. بنابراین لازم است که مهاجم به نحوی بتواند لینک حاوی کد مخرب را برای قربانی بفرستد و او را مجاب کند که روی آن کلیک نماید. از جمله روش های پنهان کردن Payload، استفاده از سرویس های کوتاه کننده لینک نظیر bit.ly یا tinyurl، ارسال لینک در ایمیل می باشد.
نکته: ترکیب XSS با Sender Spoof (در صورت عدم استفاده از SPF و DMARC رکوردها می تواند روش مناسبی برای رساندن Payload به قربانی باشد).
بیشترین استفاده از XSS بازتابی در ربایش Session IDها یا خود کوکی ها و در نتیجه ربایش نشست کاربران با ارزش می باشد. نمونه ای از یک سناریوی ساده اجرای XSS بازتابی را در تصویر زیر مشاهده می کنید:
XSS ذخیره شده (Stored XSS)
XSS ذخیره شده یا دائم (Persistant) مشابه XSS بازتابی است با این تفاوت که ورودی مخرب بجای آنکه مستقیما درون پاسخ بازتاب داده شود درون وب اپلیکیشن ذخیره می شود. پس از ذخیره این ورودی درون وب اپلیکیشن، این ورودی مخرب در نقطه ای از وب اپلیکیشن بازتاب داده شده و ممکن است تمامی بازدید کنندگان را تحت الشعاع قرار دهد. اگر چه این آسیب پذیری نیز در کد سمت سرور روی می دهد اما بعلت اینکه دائمی است نیازی نیست که کاربر خاصی را گول بزنیم تا روی لینک مورد نظر (و دارای ورودی مخرب ما) کلیک کند تا آسیب پذیری بر روی او اعمال شود بلکه بطور خودکار همه مشاهده کنندگان آن وب اپلیکیشن را تحت الشعاع قرار می دهد و بنابراین XSS ذخیره شده بیشتر مطلوب مهاجمین خواهد بود.
این نوع حمله خطرناک ترین نوع حمله XSS است چرا که هم بازدیدکنندگان سایت را هدف می گیرد و هم تنها نوعی از XSS است که مستقیما وبسایت (و نه فقط بازدیدکنندگان) را هدف گرفته و کد مخرب را درون آن تزریق می نماید. همچنین امکان دیفیس (Deface) و تغییر ظاهر صفحه وب توسط این نوع حمله نیز وجود دارد.
نکته دیگر آنکه، اگرچه در XSS بازتابی کاربر می تواند با هشیاری و تجربه از این حمله قسر در برود اما در XSS دائمی، به محض بازشدن صفحه آسیب پذیر، کدمخرب توسط مرورگر کاربر اجرا خواهد شد و عملا راه دفاعی برای کاربر باقی نمی ماند.
DOM XSS
نوعی از XSS است که تنها درون کد سمت کلاینت (غالبا جاوااسکریپت) قابل اجرا است. بطور کلی این آسیب پذیری درون محیط DOM (Document Object Model) یعنی اسکریپت سمت کلاینت صفحه رخ داده و به کد سمت سرور نمی رسد. همچنین این آسیب پذیری تا حد زیادی شبیه XSS بازتابی است با این تفاوت که با سمت سرور تعامل ندارد. مثلا وب اپلیکیشن می تواند پیام خوشامدگویی را به شکل متفاوت (که در تصویر زیر می بینید) نمایش دهد:
نکته کلیدی در این آسیب پذیری آن است که کد سمت کلاینت می تواند به DOM مرورگر و در نتیجه تمامی اطلاعات درون آن از قبیل URL، هیستوری، کوکی ها، محل ذخیره سازی و ... دسترسی داشته باشد. DOM در اصل آبجکتی است که در هنگام Parseکردن کد صفحه وب ارائه شده توسط وب سرور توسط مرورگر ایجاد می شود تا حرکت در میان تگ های مختلف HTML و سلسله مراتب آن آسان تر شود:
می توان این ساختار را با استفاده از افزونه هایی نظیر Firebug و Dom Inspector در فایرفاکس و Inspect Element در کروم استخراج نمود. در این نوع حمله نیز مهاجم قادر به ربایش کوکی ها و نشست ها یا ربایش اکانت کاربر خواهد بود. همچنین این حمله را می توان در صورت ذخیره درون وب اپلیکیشن از طریق یک کوکی آلوده بصورت دائمی نیز اجرا کرد.
یافتن XSS
کجا دنبال XSS بگردیم؟
بطور کلی، همه این سه نوع آسیب پذیری تنها در صورتی رخ خواهند داد که ورودی کاربر اصلا پاکسازی (Sanitize) نشود یا فقط به شکل جزئی پاکسازی شود. در تست جعبه سیاه یک هدف، از آنجا که به کد منبع اپلیکیشن دسترسی نداریم، بایستی خودمان بفهمیم که با گرفتن ورودی کاربر، اپلیکیشن چگونه آنرا پردازش می کند و چه خروجی می دهد؟ اگر هرگونه وابستگی بین ورودی و خروجی وجود داشته و ورودی کاربر بخشی از خروجی باشد، آنگاه یک نقطه مستعد XSS یافته ایم.
پس هرجا که از کاربر ورودی گرفته می شود، می تواند به صورت بالقوه یک نقطه آسیب پذیر باشد که از طریق آن بتوان کد HTML یا جاوااسکریپت را تزریق نمود. از جمله موارد زیر:
- باکس جستجو
- باکس نظرات و کامنت ها
- متغیرهای GET/POST
- متغیرهای کوکی
- سرایندهای HTTP
- به طور کلی هرجا که به ازای ورودی کاربر، در URL علائم <=> به همراه آن ورودی مشاهده شود.
پس از یافتن یکی از این موارد، یکی از ابتدایی ترین کارها تزریق کد HTML است. مثلا اگر جایی در باکس جستجو، عبارت جستجوشده در URL به صورت …keyword=aaa… آمد، می توانیم تگ <plaintext> را در URL جایگزین نموده و صفحه را تازه سازی (refresh) کنیم. در صورتی که بخشی از صفحه نتایج جستجو تغییر شکل داده به شکل کد HTML (بعلت استفاده از تگ Plaintext) مشاهده شد، یعنی یک قدم در اجرای حمله جلوتر رفته ایم. مثال:
گام بعدی، بررسی امکان تزریق اسکریپت است که با تگ <script> جاوااسکریپت می توان انجام داد. در صورتی که جواب Permission Denied یا Denied Access نگیریم، بازهم یک گام در یافتن XSS جلو رفته ایم.
بطور کلی این فرایند بایستی برای تمامی جاهایی که وب اپلیکیشن اقدام به گرفتن ورودی کاربر می کند بررسی شود (چگونگی یافتن این ورودی ها در فصل قبل توضیح داده شده است -بعنوان نمونه با استفاده از اسپایدر Burp Suite-).
اکسپلویت کردن XSS
همانگونه که در قسمت یافتن XSS گفته شد، اولین گام در فرایند اکسپلویت کردن و اجرای XSS، آن است که نقطه مستعد XSS (یعنی جایی که ورودی کاربر گرفته می شود) از لحاظ پاکسازی کردن/نکردن ورودی کاربر مورد بررسی قرار گیرد. اگر ورودی کاربر پاکسازی نشود، آنگاه بعنوان نمونه می توان اسکریپت زیر را تست کرد که یک پیام با محتوای XSS Example را در مرورگر نمایش می دهد:
این قطعه کد در سمت وب اپلیکیشن بصورت زیر رندر و پردازش می شود:
با بررسی کد منبع صفحه، اگر این عبارت را به شکل فوق در کد مشاهده کردیم، یعنی کد به درستی تزریق شده است. اما این کد بعلت وجود کاراکترهای مشکوک ممکن است اجرا نشود و بنابراین می توانیم از قطعه کد زیر بجای آن استفاده نماییم:
به طور کلی تگ Body برای انتقال Payloadهای XSS بسیار مفید و کارامد می باشد:
اما درباره این کد چطور؟
در این صورت خواهیم داشت:
با توجه به این که DOM Eventها امکان استفاده از کاراکترهای مشکوک < و > را دارند بنابراین استفاده از آنها نیز می تواند بسیار کارساز باشد.
در صورتی که روتین های بررسی و اعتبارسنجی ورودی برقرار باشد، بایستی کمترین میزان کاراکتر مشکوک را استفاده نمود. در این حالت، در رویداد onload می توانیم javascript: را به شکل زیر تغییر دهیم:
همچنین برای تغییر بیشتر می توانیم کد زیر را استفاده کنیم:
نکته قابل ذکر آنکه، مرورگرهایی نظیر کروم و IE برای تست این آسیب پذیری ها چندان مناسب نیستند چرا که خود ممکن است این ورودی ها را فیلتر کنند و بنابراین استفاده از فایرفاکس بهتر است.
به طور کلی مهاجم می تواند موارد زیر را با استفاده از XSS انجام دهد:
- ربایش کوکی
- تغییر صفحه
- فیشینگ/بدافزار
- کرم های XSS
که در ادامه به سه مورد از مهمترین ها یعنی ربایش کوکی و دیفیس و فیشینگ می پردازیم.
ربایش کوکی
ربایش کوکی از آنجا مهم است که می تواند منجر به ربایش نشست شود که در مقابل، بکارگیری SOP (که در فصل مقدمه شرح داده شد) جلوی این ربایش را می گیرد. در مقابل، XSS به ما امکان این ربایش را می دهد. مراحل ربایش کوکی یک کاربر (و در نتیجه نشست او) و ارسال آن به سرور راه اندازی شده مهاجم به شرح زیر است:
- یافتن یک آسیب پذیری XSS در هدف مورد نظر (که می تواند بازتابی یا دائم باشد)؛ مثلا در سرچ باکس هدف.
- استفاده از پی لود صحیح؛ مثال:
که در آن:
URL و پارامتر آسیب پذیر،
آغاز و پایان اسکریپت تزریقی جاوااسکریپت و
ایجاد یک آبجکت و مقداردهی آن با یک آدرس تحت کنترل مهاجم می باشد.
- رساندن پی لود به کاربر هدف (در صورت استفاده از XSS بازتابی) یا تزریق کد در وب اپلیکیشن در صورت استفاده از XSS دائمی.
- راه اندازی سرور مهاجم برای جمع آوری کوکی ها: سمت سرور مهاجم. محتوای steal.php چیزی شبیه به قطعه کد زیر است:
که در این حالت هرکسی که URL آلوده را مشاهده کند، کوکی او برای مهاجم فرستاده می شود.
دیفیس کردن
در این حمله، قربانی خود وبسایت است و مهاجم نیاز به یک XSS دائمی دارد تا بتواند دیفیس واقعی را اجرا کند. پس بایستی مهاجم در پی ورودی از کاربر باشد که بدون پاکسازی و اعتبارسنجی در دیتابیس وب اپلیکیشن ذخیره می شود (مانند کامنت باکس ها، که باید هم قسمت عنوان کامنت چک شود و هم قسمت متن کامنت). پس از یافتن این XSS دائم، خواهیم توانست ظاهر صفحه وب را با دستکاری DOM تغییر دهیم.
یک نوع ساده دستکاری DOM استفاده از کد زیر است:
آبجکت body در DOM متناظر با تگ BODY است که محتوای صفحه را نگاه می دارد. با تنظیم این مقدار، در اصل محتوای مدنظر خود را با محتوای فعلی جایگزین می کنیم که به این عمل دیفیس گفته می شود.
فیشینگ
به منظور انجام فیشینگ و ربایش Credential یک کاربر، بایستی مهاجم بتواند در صفحه لاگین هدف موردنظر، یک XSS بیابد. در این صورت تنها لازم است که تغییری در FORM لاگین ایجاد نماید: یوزرنیم و پسورد بایستی به دامنه تحت کنترل مهاجم ارسال شود. اصلی ترین کار در این راستا، تغییر پارامتر ACTION در FORM لاگین است. تگ FORM معمولا ساختار زیر را دارد:
که با تزریق قطعه اسکریپت زیر می توان عمل فیشینگ را انجام داد:
گواهینامه های SSL، چک های DNS و ... در مقابل چک های DNS و ... در مقابل XSS بسیار ضعیف عمل می کنند.
پی نوشت: حقوق برخی از تصاویر استفاده شده در متن متعلق به elearnsecurity می باشد.