XXE چیست و چگونه کار میکند؟
حملهی موجودیت خارجی XML (XML External Entity) که بهاختصار XXE خوانده میشود، زمانی رخ میدهد که یک تجزیهگر XML اجازه دهد سند ورودی، موجودیتهای خارجی تعریف کند و آنها را پردازش کند. مهاجم با تعریف یک موجودیت که به یک فایل محلی (file:///etc/passwd) یا یک URL داخلی اشاره میکند، میتواند به خواندن فایل، SSRF به منابع داخلی، یا منع سرویس (از راه انفجار موجودیتها، معروف به Billion Laughs) برسد.
ریشهی مشکل، ویژگیهای قدیمی DTD در استاندارد XML است. اگر تجزیهگر بارگذاری DTD خارجی و بسط موجودیت خارجی را فعال داشته باشد، ورودی مهاجم به دستور تبدیل میشود.
واقعیت امروز: کدام اکوسیستم هنوز ناامن است؟
مهمترین نکتهای که محتوای قدیمی از دست میدهد این است که پیشفرض تجزیهگرها تغییر کرده و XXE بهطور چشمگیری کاهش یافته است.
«XXE یک ریسک بزرگ و جاری در PHP و Python است.» قدیمی است. طبق راهنمای OWASP: libxml2 نسخهی ۲٫۹ به بعد XXE را بهصورت پیشفرض غیرفعال کرده (موتور پشت PHP، lxml پایتون و Nokogiri روبی)، PHP نسخهی ۸٫۰ به بعد از XXE پیشگیری میکند، و تجزیهگرهای استاندارد Python 3 امناند. اکوسیستمی که هنوز بهصورت پیشفرض ناامن است، جاوا (JAXP) است: کلاسهایی مثل DocumentBuilderFactory، SAXParserFactory، XMLInputFactory و TransformerFactory بهصورت پیشفرض XXE فعال دارند و باید صریحاً غیرفعال شوند.
پس تمرکز شکار در سال ۲۰۲۶ باید روی پشتههای جاوا و نقاط پردازش XML باشد، نه فرض ناامنی همهجانبه.
کجا باید XXE را شکار کرد؟
XXE از فرمهای XML آشکار به نقاط کمترمعلوم منتقل شده است. جاهایی که هنوز زنده است:
- تجزیهگرهای آپلود فایل: SVG، اسناد OOXML (فایلهای
docx/xlsx/pptxکه در واقع XML فشردهاند)، متادیتای XMP در تصاویر، و PDF/XFA. - SAML در جریانهای احراز هویت، که ادعاهای XML امضاشده دارد.
- اندپوینتهای SOAP/WSDL و ورودیهای RSS/Atom و نقشهی سایت XML.
- گیجی نوع محتوا (Content-type confusion): اندپوینتی که JSON انتظار دارد اما
Content-Type: application/xmlرا هم میپذیرد و به تجزیهگر XML میسپارد. - XXE کور/خارجباند: وقتی خروجی بازتاب نمیشود، تشخیص نیازمند یک DTD خارجی و یک دامنهی تحت کنترل تستر (OAST) است.
- حملات XInclude: وقتی تستر فقط بخشی از سند XML را کنترل میکند و نمیتواند DOCTYPE تعریف کند.
ابزار Burp Suite با قابلیت OAST برای شناسایی نوع کور بسیار مؤثر است. یک خانوادهی مرتبط اما متمایز، حملهی منع سرویس با انفجار موجودیت (معروف به «Billion Laughs» یا بمب XML) است که با تعریف موجودیتهای تودرتو، حافظهی تجزیهگر را تخلیه میکند؛ این حمله حتی وقتی موجودیت خارجی غیرفعال است میتواند رخ دهد و رفع آن محدودسازی بسط موجودیت است.
چرا این جابهجایی محل شکار مهم است؟ چون یک تیم توسعه که با شنیدن «XXE در PHP امن شده» خیالش راحت میشود، ممکن است یک اندپوینت آپلود SVG یا یک سرویس SAML جاوا را کاملاً نادیده بگیرد — دقیقاً جایی که XXE هنوز زنده است. ارزش این صفحه در همین هدایت درست انرژی شکار است.
نمونهی فنی و کشف در تست نفوذ
شکل یک سند XXE تشخیصی برای خواندن فایل:
<?xml version="1.0"?>
<!DOCTYPE r [
<!ENTITY x SYSTEM "file:///etc/passwd">
]>
<r>&x;</r>در تست نفوذ وب، تستر ابتدا نقاط پردازش XML را مییابد (حتی جایی که ظاهراً JSON است)، سپس با یک موجودیت به فایل یا به دامنهی OAST خود پروب میزند. برای فرمهای کور، از موجودیت پارامتری و DTD خارجی برای استخراج استفاده میشود. بازبینی کد منبع پیکربندی تجزیهگر — بهویژه در جاوا — مکمل قدرتمندی است.
شکار هدفمند XXE در پشتههای جاوا و نقاط آپلود، بخشی از تست نفوذ وب است.
چرا XXE در OWASP 2025 زیر A02 است، نه تزریق
برخلاف تصور رایج که XXE را زیر «تزریق» میگذارد، در OWASP Top 10:2025 شناسهی CWE-611 (XXE) زیر دستهی A02:2025 پیکربندی نادرست (Security Misconfiguration) قرار دارد، نه A05 تزریق. منطق این جایگذاری روشن است: XXE در بنیاد یک مسئلهی پیکربندی نادرستِ تجزیهگر است — ویژگیای که باید خاموش باشد، روشن مانده است.
این تمایز در گزارش تست نفوذ اهمیت دارد؛ دستهبندی درست یافته با تاکسونومی جاری، هم در ممیزی انطباق و هم در مقایسهی گزارشها مهم است. مرور کامل دستهها در صفحهی OWASP و مقالهی OWASP Top 10 نسخه ۲۰۲۵.
پرسشهای متداول
آیا XXE هنوز در PHP و Python خطرناک است؟
عمدتاً نه. libxml2 نسخهی ۲٫۹ به بعد XXE را پیشفرض غیرفعال کرده، PHP 8.0 به بعد از آن پیشگیری میکند و تجزیهگرهای استاندارد Python 3 امناند. اکوسیستمی که هنوز بهطور پیشفرض ناامن است، جاوا (JAXP) است.
XXE را امروز کجا باید جستوجو کرد؟
در پشتههای جاوا، تجزیهگرهای آپلود (SVG، OOXML مثل docx/xlsx، PDF)، ادعاهای SAML، اندپوینتهای SOAP، و موارد گیجی نوع محتوا که یک اندپوینت JSON، ورودی XML را هم میپذیرد.
چرا XXE در OWASP Top 10:2025 زیر تزریق نیست؟
چون در بنیاد یک پیکربندی نادرست تجزیهگر است. شناسهی CWE-611 در نسخهی ۲۰۲۵ زیر دستهی A02 پیکربندی نادرست قرار دارد، نه A05 تزریق.
XXE کور چطور کشف میشود؟
وقتی خروجی بازتاب نمیشود، با یک DTD خارجی و یک دامنهی تحت کنترل تستر (OAST مثل Burp Collaborator) تعامل خارجباند ایجاد و از موجودیت پارامتری برای استخراج داده استفاده میشود.