تصور کنید یک کاربر فقط یک متن را داخل یک فرم وارد میکند؛ اما مرورگر بهجای نمایش آن متن، آن را بهعنوان کد اجرا میکند! 😳
اینجاست که با یکی از معروفترین آسیبپذیریهای امنیت وب یعنی XSS یا Cross-Site Scripting روبهرو میشویم.
در این آموزش قرار است XSS را فقط بهصورت تئوری بررسی نکنیم؛ بلکه یک آزمایشگاه کاملاً قانونی با Kali Linux، DVWA و Burp Suite میسازیم و قدمبهقدم بررسی میکنیم که XSS چگونه ایجاد میشود، چطور آن را شناسایی کنیم و مهمتر از همه، چگونه جلوی آن را بگیریم.
⚠️ هشدار: تمام تستهای این مقاله باید فقط روی DVWA، سیستم شخصی یا محیطهایی انجام شوند که اجازه تست آنها را دارید. هرگز این آزمایشها را روی سایتها و حسابهای واقعی بدون مجوز انجام ندهید.
XSS چیست؟
Cross-Site Scripting که معمولاً با نام XSS شناخته میشود، نوعی آسیبپذیری در برنامههای وب است که در آن دادهای که توسط کاربر کنترل میشود، بدون خروجیسازی امن در صفحه قرار میگیرد.
به زبان ساده:
ورودی کاربر
↓
Web Application
↓
پردازش ناامن
↓
صفحه وب
↓
مرورگر
↓
اجرای کد
مشکل اصلی زمانی ایجاد میشود که برنامه نتواند بین:
Data
و
Executable Code
بهدرستی تفاوت ایجاد کند.
یک مثال ساده
فرض کنید یک سایت از کاربر نامش را دریافت میکند:
Reza
و آن را داخل صفحه قرار میدهد:
<h2>Hello Reza</h2>
این رفتار طبیعی است.
اما اگر برنامه ورودی کاربر را بدون Escape یا Sanitization مناسب وارد HTML کند، ممکن است یک ورودی حاوی HTML/JavaScript بهجای متن، توسط مرورگر تفسیر شود.
در نتیجه:
User Input
↓
HTML
↓
Browser Parser
↓
Unexpected Script Execution
این اساس XSS است.
انواع اصلی XSS
XSS معمولاً در سه دسته اصلی بررسی میشود:
1. Reflected XSS
در این حالت ورودی مهاجم معمولاً در همان Request ارسال شده و در Response برنامه بازتاب داده میشود.
ساختار کلی:
Attacker Input
↓
HTTP Request
↓
Web Application
↓
HTTP Response
↓
Browser
این نوع XSS معمولاً به تعامل کاربر با یک لینک یا Request خاص وابسته است.
2. Stored XSS
در Stored XSS، داده مخرب در سمت سرور یا Database ذخیره میشود.
مثلاً در:
- Comment
- Forum Post
- Profile
- Message
- نام کاربری
ساختار:
User Input
↓
Server
↓
Database
↓
Web Page
↓
Browser
مزیت مهم برای مهاجم این است که لازم نیست در هر بار اجرای آسیبپذیری، ورودی را مجدداً ارسال کند؛ چون داده در برنامه ذخیره شده است.
3. DOM-Based XSS
در DOM-Based XSS، مشکل اصلی میتواند در JavaScript سمت Client باشد.
برای مثال، یک اسکریپت ممکن است اطلاعات موجود در URL را گرفته و مستقیماً وارد DOM کند.
ساختار:
URL / User Input
↓
Client-Side JavaScript
↓
DOM
↓
Browser
در این نوع آسیبپذیری، بررسی کد JavaScript و نحوه استفاده از منابعی مانند URL بسیار مهم است.
چرا XSS خطرناک است؟
شدت XSS به نوع آسیبپذیری و Context اجرای آن بستگی دارد.
پیامدهای احتمالی میتوانند شامل:
- تغییر محتوای صفحه
- اجرای JavaScript در Context سایت
- فیشینگ داخل صفحه
- دستکاری رابط کاربری
- انجام اقدامات از طرف کاربر در شرایط خاص
- افشای برخی اطلاعات قابل دسترسی به اسکریپت
باشند.
بنابراین XSS فقط یک «Popup» ساده نیست.
Popup صرفاً یک روش آموزشی برای اثبات اجرای JavaScript در آزمایشگاه است.
ساخت آزمایشگاه XSS
برای این آموزش از این ساختار استفاده میکنیم:
┌─────────────────────────┐
│ Kali Linux │
│ │
│ Browser │
│ Burp Suite │
│ Nmap │
└────────────┬────────────┘
│
Host-Only Network
│
┌────────────▼────────────┐
│ DVWA │
│ │
│ 192.168.56.20 │
└─────────────────────────┘
IP بالا فقط نمونه است و باید IP واقعی DVWA خودتان را جایگزین کنید.
نکته: DVWA را روی اینترنت عمومی قرار ندهید.
مرحله اول: بررسی ارتباط با DVWA
ابتدا IP آزمایشگاه را بررسی کنید:
ip addr
سپس ارتباط با DVWA را تست کنید:
ping 192.168.56.20
اگر پاسخ دریافت کردید، ارتباط شبکهای برقرار است.
حالا سرویس وب را بررسی کنید:
nmap -sV -p 80,443 192.168.56.20
اگر HTTP روی پورت 80 فعال باشد، میتوانیم DVWA را از طریق مرورگر باز کنیم.
مرحله دوم: ورود به DVWA
در مرورگر Kali آدرس آزمایشگاه را باز کنید:
http://192.168.56.20
پس از ورود به DVWA، بخشهای مرتبط با XSS را مشاهده خواهید کرد.
در نسخههای رایج DVWA معمولاً گزینههایی مانند:
XSS (Reflected)
XSS (Stored)
وجود دارند.
برای شروع بهتر است سطح امنیتی روی:
Low
باشد.
مرحله سوم: XSS Reflected
ابتدا وارد بخش:
XSS (Reflected)
شوید.
معمولاً صفحه یک ورودی برای Name دارد.
ابتدا یک مقدار عادی وارد کنید:
Reza
و نتیجه را مشاهده کنید.
مثلاً:
Hello Reza
حالا میدانیم برنامه ورودی ما را در صفحه نمایش میدهد.
این دقیقاً همان چیزی است که هنگام تست باید به آن توجه کنیم:
ورودی کاربر کجا و چگونه در Response قرار میگیرد؟
مرحله چهارم: اولین تست XSS
در محیط DVWA میتوانیم یک تست بسیار ساده انجام دهیم:
<script>alert('XSS')</script>
اگر محیط آزمایشگاهی آسیبپذیر باشد، مرورگر ممکن است یک Alert نمایش دهد.
این یعنی:
Input
↓
Application
↓
HTML Response
↓
Browser
↓
JavaScript Execution
در این مرحله هدف ما فقط اثبات اجرای JavaScript در محیط آزمایشگاهی است.
چرا Alert مهم است؟
Alert خودش آسیبپذیری نیست.
Alert فقط یک Proof of Concept ساده برای نشان دادن این موضوع است که:
ورودی کاربر توانسته است بهعنوان کد در مرورگر تفسیر شود.
در یک گزارش امنیتی حرفهای بهتر است این موضوع را بهعنوان:
Proof of Concept
ثبت کنیم.
مرحله پنجم: مشاهده Request با Burp Suite
حالا Burp Suite را اجرا کنید.
در Proxy، درخواست مربوط به صفحه XSS را مشاهده کنید.
برای مثال ممکن است چیزی شبیه این ببینید:
GET /dvwa/vulnerabilities/xss_r/?name=Reza&Submit=Submit HTTP/1.1
Host: 192.168.56.20
Cookie: PHPSESSID=...
پارامتر مهم:
name=Reza
است.
این یعنی:
name
تحت کنترل کاربر است.
مرحله ششم: ارسال Request به Repeater
Request را به:
Repeater
ارسال کنید.
حالا میتوانیم مقدار پارامتر را تغییر دهیم.
مثلاً:
name=Reza
را با ورودی آزمایشگاهی XSS جایگزین کنیم.
سپس:
Send
را بزنید و Response را بررسی کنید.
چه چیزی را در Response بررسی کنیم؟
به دنبال این موارد باشید:
HTML Context
Input Reflection
Encoding
Response Body
Content-Type
Security Headers
مهمترین سؤال:
آیا ورودی من بهعنوان متن نمایش داده شده یا بهعنوان HTML تفسیر شده است؟
این سؤال یکی از پایههای مهم تحلیل XSS است.
مرحله هفتم: XSS Stored
حالا سراغ:
XSS (Stored)
میرویم.
در این بخش معمولاً فرمهایی برای وارد کردن نام و پیام وجود دارد.
مثلاً:
Name:
Reza
Message:
Hello
داده واردشده ممکن است در Database ذخیره شود.
اگر برنامه خروجی را بهدرستی Encode نکند، محتوای ذخیرهشده هنگام مشاهده صفحه میتواند در Browser تفسیر شود.
ساختار:
Input
↓
Database
↓
Page
↓
Browser
↓
Execution
این تفاوت اصلی Stored XSS با Reflected XSS است.
یک تست ساده در آزمایشگاه
در قسمت Message میتوانیم از PoC ساده زیر استفاده کنیم:
<script>alert('Stored XSS')</script>
اگر DVWA در سطح آسیبپذیر باشد، بعد از ذخیره و نمایش پیام، JavaScript اجرا خواهد شد.
این یعنی ورودی:
User Input
نهتنها دریافت شده، بلکه:
Stored
و سپس در صفحه Render شده است.
تفاوت Reflected و Stored XSS
| ویژگی | Reflected XSS | Stored XSS |
|---|---|---|
| ذخیره در سرور | معمولاً خیر | معمولاً بله |
| نیاز به Request خاص | معمولاً دارد | ممکن است نداشته باشد |
| محل قرارگیری | Response | داده ذخیرهشده |
| تعامل کاربر | معمولاً مهم | ممکن است با مشاهده صفحه رخ دهد |
| تحلیل | Request/Response | Storage + Rendering |
مرحله هشتم: DOM-Based XSS
حالا به بخش Client-Side نگاه کنیم.
فرض کنید JavaScript برنامه چنین کاری انجام دهد:
document.getElementById("output").innerHTML =
location.hash.substring(1);
مشکل اینجاست که اطلاعات کنترلشده توسط کاربر مستقیماً وارد:
innerHTML
شده است.
اگر داده بدون کنترل مناسب وارد DOM شود، ممکن است XSS ایجاد شود.
این نوع آسیبپذیری را باید بیشتر در کد JavaScript سمت Client جستوجو کرد.
Source و Sink در DOM XSS
دو مفهوم مهم وجود دارد:
Source
محلی که داده از آن دریافت میشود.
مثلاً:
location.hash
یا:
location.search
Sink
محلی که داده در آن وارد یک Context حساس میشود.
مثلاً:
innerHTML
بنابراین یک مدل ساده:
Source
↓
User-Controlled Data
↓
Unsafe Sink
↓
DOM XSS
این مدل ذهنی برای تحلیل DOM XSS بسیار مهم است.
مرحله نهم: بررسی XSS با Burp Suite
Burp Suite در تحلیل XSS بسیار کاربردی است.
هنگام بررسی Request به این موارد توجه کنید:
Parameter
Cookie
Header
POST Body
GET Parameter
JSON
ممکن است یک ورودی در ظاهر ساده باشد:
name=Reza
اما در Response به شکل زیر قرار بگیرد:
<div>Reza</div>
یا در یک Attribute:
<input value="Reza">
یا داخل JavaScript:
var name = "Reza";
این Context بسیار مهم است.
چون Payload مناسب برای هر Context میتواند متفاوت باشد.
Context در XSS یعنی چه؟
یکی از مهمترین نکات حرفهای در XSS این است که فقط به Input نگاه نکنیم.
باید ببینیم Input در کجا قرار گرفته است.
مثلاً:
<div>INPUT</div>
با:
<input value="INPUT">
یکسان نیست.
همچنین:
var x = "INPUT";
Context کاملاً متفاوتی دارد.
بنابراین تست XSS باید بر اساس Context انجام شود.
XSS و Cookie
یکی از مباحث معروف در XSS، Cookieها هستند.
اما یک نکته مهم وجود دارد:
اگر Cookie دارای ویژگی:
HttpOnly
باشد، JavaScript سمت مرورگر نباید بتواند آن Cookie را از طریق:
document.cookie
بخواند.
به همین دلیل تنظیمات امنیتی Cookie اهمیت زیادی دارند.
ویژگیهای مهم:
HttpOnly
Secure
SameSite
هستند.
چگونه XSS را برطرف کنیم؟
۱. Output Encoding
یکی از مهمترین راهکارها این است که داده کاربر قبل از نمایش در HTML، متناسب با Context موردنظر Encode شود.
برای مثال:
< → <
> → >
" → "
' → '
۲. استفاده صحیح از APIهای DOM
در JavaScript، بهجای قرار دادن مستقیم داده غیرقابل اعتماد در:
innerHTML
در بسیاری از سناریوها میتوان از روشهایی مانند:
textContent
استفاده کرد.
مثلاً:
element.textContent = userInput;
در این حالت داده بهعنوان متن قرار میگیرد، نه HTML قابل تفسیر.
۳. اعتبارسنجی ورودی
Validation میتواند مفید باشد، اما نباید تنها دفاع شما در برابر XSS باشد.
چرا؟
چون XSS میتواند در Contextهای مختلفی اتفاق بیفتد.
بنابراین:
Validation
+
Output Encoding
+
Safe APIs
+
Security Headers
رویکرد مناسبتری است.
۴. Content Security Policy
CSP یا Content Security Policy میتواند یک لایه دفاعی مهم در برابر برخی سناریوهای XSS باشد.
یک CSP مناسب میتواند مشخص کند مرورگر چه منابعی را اجازه اجرا یا بارگذاری دارد.
اما:
CSP جایگزین اصلاح کد آسیبپذیر نیست.
بلکه یک لایه دفاعی اضافه است.
۵. Cookieهای امن
برای کاهش ریسک سرقت Cookie از طریق JavaScript، تنظیمات Cookie اهمیت زیادی دارند:
HttpOnly
Secure
SameSite
هرکدام نقش متفاوتی در امنیت Session و Cookie دارند.
XSS در برابر SQL Injection
حالا که SQL Injection و XSS را یاد گرفتهایم، تفاوت آنها را ببینیم:
| ویژگی | SQL Injection | XSS |
|---|---|---|
| هدف اصلی | Database | Browser |
| Context | SQL | HTML/JS/DOM |
| محل اجرای اصلی | Database/Backend | Client/Browser |
| ورودی خطرناک | Query | Web Content |
| ابزار تحلیل | Burp / DB | Browser / Burp |
| دفاع مهم | Prepared Statement | Output Encoding |
به زبان ساده:
SQL Injection
↓
Database
در حالی که:
XSS
↓
Browser
🧠 روش درست یادگیری XSS
اگر تازه وارد Web Pentesting شدهاید، فقط Payload حفظ نکنید.
این مسیر را دنبال کنید:
Input
↓
Request
↓
Server Processing
↓
Response
↓
Browser Context
↓
Execution
↓
Impact
↓
Remediation
وقتی این زنجیره را بفهمید، یادگیری XSS بسیار سادهتر میشود.
🧪 تمرین عملی
حالا یک تمرین برای شما:
مرحله ۱
DVWA را اجرا کنید.
مرحله ۲
سطح امنیتی را روی Low قرار دهید.
مرحله ۳
XSS Reflected را باز کنید.
مرحله ۴
یک ورودی عادی ارسال کنید.
مرحله ۵
Request را با Burp Suite مشاهده کنید.
مرحله ۶
پارامتر قابل کنترل را پیدا کنید.
مرحله ۷
یک PoC ساده و غیرمخرب در آزمایشگاه اجرا کنید.
مرحله ۸
Response را بررسی کنید.
مرحله ۹
XSS Stored را امتحان کنید.
مرحله ۱۰
سطح امنیتی DVWA را افزایش دهید و تفاوت رفتار را بررسی کنید.
📋 قالب گزارش آسیبپذیری XSS
برای ثبت نتیجه آزمایش میتوانید از این قالب استفاده کنید:
Target:
DVWA
Target IP:
192.168.56.20
Vulnerability:
Cross-Site Scripting
XSS Type:
Reflected / Stored / DOM-Based
Endpoint:
...
Parameter:
...
HTTP Method:
GET / POST
Security Level:
Low
Proof of Concept:
...
Observed Behavior:
...
Impact:
...
Root Cause:
Unsafe Output Handling
Recommended Remediation:
Output Encoding
Safe DOM APIs
Input Validation
CSP
Secure Cookie Configuration
🔥 اشتباهات رایج در یادگیری XSS
اشتباه اول: فکر کردن XSS یعنی فقط Alert
Alert تنها یک PoC ساده است.
هدف اصلی شناخت Execution Context و اثر آسیبپذیری است.
اشتباه دوم: حفظ کردن Payloadها
Payload بدون درک Context کمک زیادی نمیکند.
اشتباه سوم: بیتوجهی به Output Encoding
باید بفهمیم داده در چه Contextی Render میشود.
اشتباه چهارم: تست روی سایت واقعی
برای یادگیری، DVWA یک محیط بسیار مناسب و قانونی است.
اشتباه پنجم: نادیده گرفتن بخش دفاعی
یک متخصص امنیت باید بتواند علاوه بر کشف آسیبپذیری، راهکار اصلاح آن را نیز ارائه دهد.
🎯 جمعبندی
در این آموزش با مفهوم Cross-Site Scripting آشنا شدیم و در محیط آزمایشگاهی بررسی کردیم که چگونه یک ورودی کنترلشده توسط کاربر میتواند در شرایط ناامن توسط Browser تفسیر شود.
مسیر یادگیری ما:
Kali Linux
↓
DVWA
↓
Nmap
↓
Burp Suite
↓
HTTP Request
↓
Input Analysis
↓
Reflected XSS
↓
Stored XSS
↓
DOM XSS
↓
Response Analysis
↓
Remediation
اما مهمترین چیزی که باید به خاطر بسپارید این است:
XSS فقط یک Payload نیست؛ XSS یعنی درک مسیر حرکت داده از ورودی کاربر تا Contextی که مرورگر آن را تفسیر میکند.
اگر این مسیر را بفهمید، قدم مهمی در مسیر Web Application Penetration Testing برداشتهاید.

دیدگاه شما