یک قابلیت ساده «دریافت تصویر از URL» میتواند سرور را به نماینده ناخواسته مهاجم تبدیل کند؛ یک فایل XML ظاهراً معتبر نیز ممکن است Parser را وادار کند به فایل یا سرویس بیرونی دست بزند. وجه مشترک SSRF و XXE این است: داده غیرقابل اعتماد از مرز Parse/Resolve عبور میکند و نرمافزار به منبعی خارج از حوزه مجاز متصل میشود.
این راهنما توضیح میدهد SSRF چیست، XXE چه تفاوتی با آن دارد، URL و XML attack surface چگونه کشف میشود، تست امن و قابل تکرار چه Evidenceای میخواهد و دفاع لایهای از کد تا Egress چگونه طراحی میشود. مثالها عمداً برای آزمایشگاه کنترلشدهاند؛ تست روی شبکه، Metadata، فایل یا سرویس واقعی بدون مجوز صریح انجام نشود.
آیا SSRF و XXE «فراتر از OWASP Top ۱۰» هستند؟
این صورتبندی دقیق نیست. طبقهبندیها با دوره و سطح انتزاع تغییر میکنند:
- SSRF در OWASP Top ۱۰:۲۰۲۱ دسته مستقل A10 بود.
- مقدمه رسمی OWASP Top ۱۰:۲۰۲۵ میگوید SSRF در A01 Broken Access Control ادغام شده است.
- SSRF همچنان در OWASP API Security Top 10:2023 دسته API7 است.
- XXE در Top ۱۰:۲۰۱۷ دسته مستقل داشت؛ اکنون ضعف پایه CWE-۶۱۱ و معمولاً نمونهای از Security Misconfiguration، Injection یا Insecure Design در زمینه خاص است.
Top ۱۰ یک برنامه تست کامل نیست و «داخل/خارج لیست» شدت یک Finding را تعیین نمیکند. مقاله OWASP Top ۱۰:۲۰۲۵ و روش تست مالک طبقهبندی دهگانه است؛ این مقاله Deep dive فنی مرز URL/XML و کنترل Egress است.
SSRF و XXE چیستند؟
SSRF چیست؟
Server-Side Request Forgery زمانی رخ میدهد که مهاجم بتواند نرمافزار سمت سرور را به ارسال درخواست یا دسترسی به منبعی خارج از مقصد مجاز وادار کند. CWE-۹۱۸ از MITRE این ضعف را ناشی از دریافت URL/Request از جزء بالادستی و خواندن یا تغییر منبع بدون اطمینان از مجازبودن مقصد میداند.
HTTP تنها مسیر نیست. Fetcher، SDK یا Parser ممکن است از Schemeهای دیگر، DNS، Socket، فایل یا Protocol handler پشتیبانی کند. پیامد بسته به Capability سرویس و شبکه میتواند شامل این موارد باشد:
- دسترسی به API یا پنل داخلی که از اینترنت دیده نمیشود؛
- خواندن Metadata یا Credential محیط Cloud؛
- اسکن کور شبکه و کشف Port/Service از روی زمان یا خطا؛
- خواندن فایل یا منبع محلی در صورت فعالبودن Scheme مربوط؛
- ارسال درخواست state-changing با هویت یا اعتماد سرویس؛
- ورود داده مخرب به Parser/Renderer بعدی؛
- مصرف منابع، هزینه یا اختلال در دسترسپذیری.
XXE چیست؟
XML External Entity زمانی رخ میدهد که نرمافزار XML غیرقابل اعتماد دارای مرجع External را پردازش و Resolver آن منبعی خارج از حوزه مجاز را Dereference کند. CWE-۶۱۱ از MITRE پیامدهایی مانند خواندن فایل، درخواست خروجی/SSRF و مصرف CPU یا حافظه را ثبت میکند.
XXE فقط «یک تگ خطرناک» نیست. سطح حمله میتواند External general entity، Parameter entity، External DTD، XInclude، XSLT، Schema import یا زنجیره پردازش غیرمستقیم باشد. XML injection، XPath injection و Unsafe deserialization ضعفهای جداگانهاند، هرچند ممکن است در یک Flow کنار هم رخ دهند.
رابطه SSRF و XXE
XXE میتواند یک مسیر ایجاد SSRF باشد: XML Parser برای Resolve کردن URI بیرونی، از Context و شبکه سرور درخواست میفرستد. اما هر SSRF از XML نمیآید و هر XXE الزاماً روی سرور یا HTTP رخ نمیدهد. Finding را با Root cause دقیق ثبت کنید:
- CWE-918: کنترل ناکافی مقصد درخواست سمت سرور؛
- CWE-611: کنترل ناکافی External entity/reference در XML؛
- CWE/Chain مکمل: Redirect ناامن، URL parser discrepancy، نبود Egress control، احراز هویت ضعیف سرویس داخلی یا مصرف بیحد منابع.
کشف سطح حمله URL و XML
فقط پارامترهایی با نام url را جستوجو نکنید. ابتدا Data flow را از ورودی تا Connection/Parser رسم کنید.
نقاط ورود رایج URL
- دریافت Avatar، لوگو، تصویر، PDF، Feed یا فایل از URL؛
- URL preview، Screenshot، PDF renderer و Document converter؛
- Webhook/Callback registration و «Test connection»؛
- Import از Repository، Cloud storage یا Remote API؛
- OAuth/OIDC discovery، JWKS، SSO و Remote configuration؛
- Proxy، media cache، link unfurling، crawler و health checker؛
- Redirect/return URL که بعداً در Back-end dereference میشود؛
- URL تولیدشده از چند Field مانند scheme/host/path/port؛
- Agent/LLM tool که به دستور کاربر یا محتوای بیرونی URL میخواند.
نقاط ورود پنهان XML
- SOAP، SAML، XML-RPC، RSS/Atom و Importهای B2B؛
- فایل SVG و تصویر/سندی که زیرساخت آن را XML Parse میکند؛
- Office/Archive حاوی XML پس از Decompress؛
- XML داخل Queue، Email attachment، Batch settlement یا ETL؛
- Parser دوم در Antivirus، thumbnailer، validator یا transformer؛
- Schema validation، XSLT transformation و XInclude؛
- Content-type mismatch که یک Handler متفاوت فعال میکند.
یک Endpoint JSON ممکن است URL را به Worker بفرستد و Worker فایل XML را Parse کند؛ مرز امنیتی تا آخر Pipeline ادامه دارد. برای طراحی Request/response و تست سطح API، راهنمای تست API مکمل این Inventory است.
مدل هفتمرحلهای SSRF
- Input: کاربر URL کامل یا بخشی از مقصد را کنترل میکند.
- Parse: Library آن را به scheme، authority، userinfo، host، port و path میشکند.
- Canonicalize: IDN/Punycode، percent encoding، IPv4/IPv6 و case عادی میشوند.
- Resolve: DNS یک یا چند A/AAAA یا CNAME برمیگرداند.
- Connect: Client به IP/port انتخابشده وصل میشود؛ Proxy یا environment variable ممکن است مسیر را عوض کند.
- Redirect: پاسخ میتواند مقصد تازهای معرفی کند و چرخه Parse/Resolve/Policy تکرار شود.
- Consume: Body، header و status به کاربر، Parser یا منطق بعدی میرسد.
اعتبارسنجی فقط در مرحله اول کافی نیست. اگر Policy نام دامنه را بررسی کند اما Client پس از DNS rebinding به IP داخلی وصل شود، تصمیم و اتصال از هم جدا شدهاند. اگر Redirect بدون بازبینی دنبال شود، مقصد اول مجاز میتواند به مقصد دوم غیرمجاز برسد.
چرا Regex و مقایسه رشتهای میشکنند؟
Parserهای Front-end، API gateway، Runtime، HTTP client و Proxy ممکن است یک رشته را متفاوت تفسیر کنند. کلاسهای آزمون مهماند:
- userinfo در authority، علامتهای جداکننده و hostname suffix؛
- case، trailing dot، Unicode/IDN و Punycode؛
- percent encoding یا normalization چندمرحلهای؛
- IPv4 شکلهای جایگزین و IPv4-mapped IPv6؛
- چند A/AAAA، CNAME chain و تغییر پاسخ DNS؛
- Scheme یا port نامعمول و protocol handler ناخواسته؛
- Redirect نسبی/مطلق و تغییر scheme/host/port؛
- Proxy environment، DNS resolver یا connection pool متفاوت.
هدف تست ساخت «فهرست Payload جادویی» نیست؛ باید ثابت کند تمام نمایشهای همارز یک مقصد، تصمیم Policy یکسان میگیرند و همان تصمیم تا Socket اعمال میشود.
قواعد تست ایمن و مجاز
راهنمای تست SSRF در OWASP WSTG هدف را کشف injection point، سنجش exploitability و شدت میداند. این فعالیت میتواند شبکه داخلی یا سرویس ثالث را لمس کند؛ Rules of Engagement لازم است.
حداقل Rules of Engagement
- Target، Environment، Build، Endpoint و حسابهای مجاز؛
- Callback/DNS/HTTP observer تحت کنترل تیم؛
- Mockهای داخلی و Cloud metadata شبیهسازیشده؛
- Scheme، destination class و redirectهای مجاز آزمایش؛
- نرخ، concurrency، timeout و سقف response bytes؛
- ممنوعیت فایل واقعی، Credential، Port scan، DoS و سرویس ثالث؛
- Stop condition برای Error/latency/queue/egress غیرعادی؛
- مسیر نگهداری، Redaction و حذف Evidence.
در مستندات و Fixture از Rangeهای مخصوص مثال استفاده کنید. RFC 5737 سه بلوک TEST-NET را برای Documentation رزرو کرده و میگوید نباید روی اینترنت عمومی Route شوند. برای اثبات Connection واقعی، یک مقصد آزمایشگاهی کنترلشده لازم است؛ TEST-NET بهتنهایی Oracle شبکه نیست.
Oracle امن
بهجای درخواست به Metadata یا IP واقعی سازمان، یک سرویس Mock بسازید که فقط این موارد را ثبت کند: token تصادفی Run، زمان، source workload، method، Host/SNI، مسیر غیرحساس و تعداد Byte. هر Test token یکتا دارد. Observer نباید Body یا Credential واقعی جمع کند.
برنامه تست SSRF
۱. Baseline و Contract قابلیت
ابتدا رفتار مجاز را ثبت کنید: آیا قابلیت فقط تصویر HTTPS از دو Origin مشخص میخواهد یا هر Webhook عمومی را میپذیرد؟ Contract باید scheme، origin/host، port، redirect، DNS، method، header، credential، content type، size، timeout و side effect را مشخص کند.
۲. بررسی ایستا و Data flow
Sourceهای ورودی را تا Sinkهایی مانند HTTP client، DNS lookup، socket، file API، renderer و XML parser دنبال کنید. Wrapper مشترک، Redirect policy، Proxy، cookie jar، auth header forwarding و logging را بررسی کنید. SAST میتواند Source-to-sink را پیدا کند، اما Configuration واقعی Resolver/Egress را ثابت نمیکند. روش Triage در تحلیل استاتیک کد برای QA آمده است.
۳. ماتریس مقصد
| کلاس | نمونه آزمایشگاهی | انتظار |
|---|---|---|
| Origin مجاز | HTTPS observer با گواهی معتبر | اتصال محدود و ثبتشده |
| Origin عمومی نامجاز | دامنه کنترلشده دوم | Block طبق Contract |
| Loopback/private/link-local/reserved | Mock network namespace | پیش از Connect مسدود |
| IPv6 و IPv4-mapped | Listener آزمایشگاهی | همان Policy IPv4 |
| Scheme/port نامجاز | Handler بیخطر در Lab | پیش از Resolve/Connect مسدود |
| دامنه با چند A/AAAA | DNS کنترلشده | همه Answerها معتبر یا کل درخواست Reject |
۴. Canonicalization و اختلاف Parser
برای هر Origin مجاز و نامجاز، جدول نمایشهای همارز بسازید: case، trailing dot، IDN/Punycode، encoding، userinfo، port و IPv4/IPv6. Expected را از خروجی Parser مورد اعتماد و Policy تعیین کنید. سپس همان URL نهایی را در HTTP client و Reverse proxy مشاهده کنید؛ Validator و مصرفکننده نباید Host متفاوت ببینند.
۵. DNS و زمان تصمیم تا اتصال
- دامنهای که هم A و هم AAAA دارد؛
- چند Answer که یکی نامجاز است؛
- CNAME chain با مقصد نامجاز در Lab؛
- تغییر پاسخ بین Validation و Connection؛
- TTL کوتاه و connection reuse؛
- DNS failure/timeout که نباید Fail-open شود.
Evidence باید IP واقعاً Dialشده را نشان دهد، نه فقط نتیجه Lookup اولیه.
۶. Redirect
حالت امنتر برای Fetcher محدود، غیرفعالکردن Redirect است. اگر نیاز کسبوکار دارد، تعداد Hop محدود و هر Location دوباره Parse/Resolve/Policy شود. این انتقالها را در Lab بسنجید: مجاز→مجاز، مجاز→نامجاز، HTTPS→HTTP، تغییر port، loop و زنجیره طولانی. Headerهای حساس نباید به Origin جدید منتقل شوند.
۷. Blind SSRF
در Blind SSRF پاسخ مقصد به کاربر برنمیگردد؛ Connection ممکن است فقط در DNS/HTTP observer یا Egress log دیده شود. نبود پاسخ یا Error یکسان، نبود آسیبپذیری را ثابت نمیکند. token یکتا، بازه زمانی، correlation ID و source workload را ثبت کنید. Callback عمومی فقط با مجوز و بدون داده حساس باشد.
۸. کنترل پاسخ و منابع
- Timeout اتصال/خواندن و Deadline کل؛
- حداکثر Redirect، Byte، decompression ratio و زمان پردازش؛
- Content type و magic bytes متناسب قابلیت؛
- Streaming بهجای Buffer نامحدود؛
- عدم بازگرداندن Header/Body خام به Client؛
- عدم اجرای Active content در Renderer/Parser بعدی؛
- Rate limit، quota و cancellation/cleanup.
معماری پیشگیری از SSRF
OWASP SSRF Prevention Cheat Sheet دو حالت را جدا میکند: مقصدهای شناختهشده که Allowlist ممکن است، و مقصد عمومی دلخواه که کنترل دشوارتر است. دفاع باید Application و Network را با هم پوشش دهد.
۱. Capability را کاهش دهید
- بهجای URL کامل، resource ID یا provider enum بگیرید؛
- scheme/host/port را Server بسازد و کاربر فقط path/key محدود بدهد؛
- اگر Fetch ضروری نیست، Upload مستقیم با Scan امنتر است؛
- Fetcher را Service جدا با Identity و Egress حداقلی اجرا کنید.
۲. Policy در لایه Application
- با یک Parser استاندارد URL را یکبار Parse و Canonicalize کنید.
- scheme را صریحاً به موارد لازم محدود کنید.
- userinfo، fragment و port ناخواسته را رد کنید.
- Origin/host را با تطبیق دقیق Allowlist بسنجید؛ substring یا suffix ساده کافی نیست.
- همه A/AAAAها را با Policy IP سازمان کنترل کنید.
- IP نهایی اتصال را به نتیجه تأییدشده Bind و TOCTOU را حذف کنید.
- Redirect را خاموش یا هر Hop را دوباره اعتبارسنجی کنید.
- Header، Cookie، Authorization و Proxy credential کاربر/سرویس را Forward نکنید.
کتابخانههایی با نام isPrivate یا isGlobal را بدون Test matrix اعتماد نکنید؛ تعریف Rangeها، IPv6 و نسخه Library مهم است. Policy باید علاوه بر Rangeهای استاندارد، شبکههای داخلی واقعی سازمان را بشناسد.
۳. Egress در لایه شبکه
Fetcher فقط به DNS resolver، proxy و مقصدهای لازم دسترسی داشته باشد. Default-deny، Egress gateway/proxy، route/firewall و service identity Blast radius را محدود میکنند. در Kubernetes، مستندات NetworkPolicy هشدار میدهد که Policy فقط وقتی اثر دارد که Plugin شبکه آن را enforce کند؛ وجود YAML بهتنهایی Evidence نیست.
۴. سرویس داخلی را به شبکه اعتماد ندهید
API داخلی نیز Authentication، Authorization، tenant check، rate limit و audit لازم دارد. SSRF نباید صرفاً بهخاطر Source IP سرور به Admin action برسد. Requestهای state-changing باید method/CSRF-like intent، idempotency و business authorization داشته باشند.
۵. دفاع Cloud metadata
Cloud-specific control مکمل است، نه جایگزین رفع SSRF. برای AWS، مستندات Instance Metadata Service امکان اجبار IMDSv2 و تنظیم endpoint/hop limit را توضیح میدهد. در Test فقط Mock metadata استفاده کنید و علاوه بر آن IAM least privilege، credential کوتاهعمر و Egress policy را بیازمایید؛ IMDSv2 دسترسی به سایر سرویسهای داخلی را حل نمیکند.
برنامه تست XXE
هدف این نیست که فایل واقعی سیستم را بخوانید؛ باید ثابت کنید Parser هیچ External resolution ناخواسته ندارد و ورودی غیرعادی Fail-closed میشود.
۱. Inventory دقیق Parser
برای هر مسیر XML این اطلاعات را ثبت کنید:
- Endpoint/queue/file type و Content-Type؛
- Library، Runtime، نسخه و concrete parser implementation؛
- DOM/SAX/StAX یا transformer/validator؛
- DOCTYPE، DTD، external general/parameter entity؛
- XInclude، XSLT، Schema import و Catalog resolver؛
- network/file access، size/depth/entity limits؛
- خطا، retry، partial commit و cleanup.
۲. Fixtureهای بیخطر
| Fixture | انتظار | Oracle |
|---|---|---|
| XML معتبر بدون DTD | پردازش موفق | خروجی کسبوکار |
| DOCTYPE در ورودی غیرقابل اعتماد | رد صریح | Parser error کنترلشده |
| External general/parameter entity به Observer | صفر Resolve/Connect | Resolver spy + DNS/HTTP log |
| External DTD/Schema/XInclude/XSLT در Lab | صفر Fetch | Observer و egress log |
| Entity expansion کوچک و محدود | عبور از Budget ممنوع | CPU/memory/time limit |
| XML malformed/oversized | Fail-closed بدون partial action | business state + resource cleanup |
۳. Blind XXE و Out-of-band
اگر Response داده بیرونی را نشان نمیدهد، Resolver ممکن است باز هم DNS یا HTTP بزند. Observer کنترلشده با token یکتا و داده ثابت استفاده کنید. هیچ مقدار Production را در hostname/path Callback قرار ندهید. نتیجه مثبت به Request log و Build/Parser متصل شود؛ تفاوت زمان بهتنهایی Evidence کافی نیست.
۴. Parserهای غیرمستقیم
همان Fixture را از مسیر Upload، message consumer، thumbnail، validator، transform، archive extraction و batch import اجرا کنید. امنبودن Parser اصلی تضمین نمیکند یک کتابخانه downstream دوباره XML را با تنظیمات پیشفرض ناامن باز کند.
پیشگیری از XXE و XML resource abuse
راهنمای رسمی OWASP XXE Prevention Cheat Sheet تنظیمات را برای Parserها و زبانهای مختلف جدا میکند؛ یک Snippet را بین Runtimeها کورکورانه کپی نکنید.
اگر DTD لازم نیست
- DOCTYPE/DTD را رد کنید؛
- external general و parameter entities را غیرفعال کنید؛
- load external DTD را ببندید؛
- XInclude را غیرفعال کنید؛
- Transformer/Schema factory را از External access منع کنید؛
- هر failure در اعمال Feature را Fail startup/build کنید، نه اینکه فقط Log و ادامه دهید.
اگر DTD یا Schema واقعاً لازم است
Resolver سفارشی فقط Catalog/Schema محلی نسخهدار و Allowlistشده را برگرداند. Network/file resolver عمومی نداشته باشید. Digest، owner و update process منبع محلی را ثبت کنید. Validation ساختاری همچنان Semantic business validation را جایگزین نمیکند.
محدودیت منابع
حداکثر اندازه document، depth، attribute، entity expansion، transform time، decompressed bytes و total processing deadline تعیین کنید. «Secure processing» در برخی Runtimeها مفید است اما رفتار implementation-dependent دارد؛ Test اجرایی لازم است. JSON نیز ذاتاً امن نیست و میتواند depth/size/deserialization ضعف دیگری داشته باشد.
Egress Parser
Worker پردازش XML معمولاً به اینترنت نیاز ندارد. Default-deny egress و filesystem permission حداقلی، شکست Parser config را محدود میکنند. این Controlها را از Pod/VM واقعی با اتصال آزمایشی اثبات کنید، نه از روی IaC plan.
اتوماسیون در CI/CD بدون تبدیل Scanner به Oracle
Unit/Component
- URL policy با table-driven tests برای canonical forms؛
- fake resolver برای A/AAAA/CNAME و DNS change؛
- fake dialer که IP نهایی را ثبت و مقصد نامجاز را Fail میکند؛
- redirect handler با hop-by-hop revalidation؛
- XML parser contract با EntityResolver spy؛
- resource budget و no-partial-side-effect assertions.
Integration
در Network namespace یا محیط ephemeral، DNS/HTTP observer، mock metadata، internal mock و egress policy واقعی بسازید. Expected فقط status code نیست: DNS query، TCP connection، proxy log، outbound bytes و business state باید بررسی شوند.
SAST و DAST
SAST مسیر URL/XML input تا fetch/resolve sink و Parser configuration را پیدا میکند. DAST رفتار endpoint و Blind callback را میسنجد. IAST/telemetry میتواند concrete client و call stack را نشان دهد. هیچکدام پوشش کامل Source، Config، DNS، Network و downstream parser را بهتنهایی ندارند. نقش ابزارها در راهنمای SAST، DAST و SCA تفکیک شده است.
Laneهای پیشنهادی
| Lane | Signal | Gate |
|---|---|---|
| Pull Request | policy/parser unit، static rule، config | هر bypass fixture یا unsupported feature |
| Artifact | Integration با DNS/HTTP observer | هر egress نامجاز یا binding اشتباه |
| Environment | Proxy/firewall/NetworkPolicy actual state | مسیر خروجی خارج Contract |
| Release | Authorized focused DAST + manual review | Finding تأییدشده بر اساس Risk policy |
| Production | Egress/DNS/parser anomaly و asset change | Alert/containment، نه exploit فعال |
ساخت این Laneها در Continuous Testing و پیادهسازی Artifact-bound آن در CI/CD با Jenkins و GitLab توضیح داده شده است.
Evidence و گزارش Finding
برای SSRF/XXE این فیلدها را ثبت کنید:
- Build/commit، Environment، endpoint/worker و account/role؛
- ورودی بهصورت Redacted و کلاس bypass، نه Secret/Payload حساس؛
- Parser/library/config و URL canonical form؛
- DNS answerها، IP/port واقعاً Dialشده و redirect hops؛
- Observer token، timestamp، source workload و correlation ID؛
- response class/size/time و business side effect؛
- Expected policy، Actual، Root cause و failed control layer؛
- Reachable asset/data/credential و Blast radius تأییدشده؛
- Fix، regression fixture، retest و residual risk.
شدت و اولویت
Blind بودن مساوی Low risk نیست. Priority را با Capability و Context تعیین کنید:
- آیا مقصد فقط اینترنت عمومی است یا شبکه/Metadata/Control plane؟
- GET محدود است یا method/body/header و credential قابل کنترلاند؟
- پاسخ دیده میشود، Out-of-band اثر دارد یا state تغییر میکند؟
- سرویس داخلی Authentication/Authorization مستقل دارد؟
- Fetcher چه Identity، tenant و دادهای دارد؟
- Egress و response limits Blast radius را چقدر کم میکنند؟
- بهرهبرداری نیازمند چه نقش، interaction و reliability است؟
Severity فنی با Release decision یکی نیست. ریسک را با روش تست مبتنی بر ریسک به Evidence، Owner، پذیرش و Expiry وصل کنید.
مانیتورینگ و پاسخ عملیاتی
سیگنالهای مفید
- اتصال Workloadهای غیرمنتظره به loopback/private/link-local/reserved ranges؛
- DNS query دامنه نادر، NXDOMAIN burst یا پاسخ A/AAAA غیرعادی؛
- redirect hop، port یا scheme خارج Baseline؛
- افزایش timeout، fetch bytes، decompression یا parser error؛
- DOCTYPE/external entity/XInclude attempt در ورودی untrusted؛
- credential use از سرویس/منبع غیرمنتظره؛
- تغییر NetworkPolicy، proxy allowlist یا resolver config.
Runbook کوتاه
- Alert را با request/build/workload و destination Validate کنید.
- Fetcher/endpoint/egress route را با کمترین اختلال Contain کنید.
- Credential یا token در معرض را Revocation/rotation دهید.
- DNS، proxy، application، cloud audit و internal service log را حفظ کنید.
- مقصدها، داده، action و tenantهای تحت تأثیر را Scope کنید.
- Root cause را در Application و Network هر دو اصلاح کنید.
- Regression fixture و detection را اضافه و Retest end-to-end کنید.
مثال ایرانی: لوگوی فروشنده، Webhook و XML تسویه
سناریو تخیلی است. Marketplace به فروشنده اجازه میدهد لوگو را از URL دریافت و Webhook سفارش ثبت کند؛ Job مالی نیز فایل XML تسویه PSP را میخواند.
تهدیدها
- URL لوگو پس از Redirect به سرویس داخلی یا Mock metadata میرود؛
- دامنه عمومی بین Validation و Fetch به IP آزمایشگاهی داخلی Resolve میشود؛
- Webhook test، response داخلی را به فروشنده نشان میدهد یا Header حساس میفرستد؛
- Fetcher فایل بزرگ/فشرده را بدون Budget پردازش میکند؛
- XML تسویه External entity یا Schema import بیرونی فعال میکند؛
- Parser در خطا بخشی از تراکنش تسویه را Commit میکند.
کنترل و Test pack
- Fetcher لوگو در Service جدا، بدون Credential محصول و با egress proxy اجرا شود.
- فقط HTTPS، port استاندارد، IP عمومی مجاز، response image واقعی و اندازه محدود پذیرفته شود.
- IDN/Punycode، دامنه فارسی، trailing dot، IPv6 و redirect در matrix قرار گیرند؛ نمایش فارسی از identifier canonical جدا باشد.
- Webhook با challenge/ownership و POST محدود تأیید شود؛ test response خام برنگردد.
- قطع CDN یا محدودیت دسترسی باعث wildcard کردن allowlist نشود؛ Origin جایگزین باید مصوب و نسخهدار باشد.
- XML با DTD/External resolution بسته، local schema catalog و resource budget Parse شود.
- مبلغ Canonical ریال، رقم فارسی/لاتین و شناسه PSP بعد از Parse، semantic validation مستقل داشته باشند.
- Parser failure هیچ Ledger/settlement جزئی نسازد و Retry idempotent باشد.
- Observer، proxy log، resolver spy، ledger query و audit event Evidence پذیرش باشند.
این مثال نشان میدهد جلوگیری از XXE تمامیت مبلغ را تضمین نمیکند و URL allowlist نیز مالکیت Webhook را ثابت نمیکند؛ هر Control سؤال محدود خود را پاسخ میدهد.
متریکهای سالم
| متریک | تعریف | ضدالگو |
|---|---|---|
| Fetch-surface coverage | درصد URL/XML sinkهای inventoryشده با Owner/Contract | شمارش endpoint بدون workerهای downstream |
| Policy fixture coverage | کلاسهای canonical/DNS/redirect/parser با Expected | تعداد Payload بهعنوان کیفیت |
| Unauthorized egress | اتصال خارج Contract بر حسب workload/destination | صفرکردن با خاموشکردن Log |
| Decision-to-dial mismatch | IP واقعی اتصال متفاوت از تصمیم Policy | فقط DNS اولیه |
| Parser hardening coverage | درصد مسیرهای XML با executable no-resolution test | وجود config flag |
| Time to triage | Alert/Finding تا Root cause و Scope | بستن خودکار Scanner alert |
| Exception age | عمر allowlist/egress/parser exception | استثنای بیانقضا |
| Regression recurrence | بازگشت همان Root cause پس از Fix | ادغام Findingهای نامرتبط |
برنامه ۳۰روزه
هفته اول: Inventory و Contract
URL/XML sinkها را در یک Domain پرریسک پیدا، Data flow و Parser/client/proxy/resolver را ثبت و Rules of Engagement و observer آزمایشگاهی را آماده کنید.
هفته دوم: Unit و Component
URL policy table، fake resolver/dialer، redirect matrix و XML entity-resolver spy را بسازید. Fixtureهای normal/denied و resource budget را در Pull Request Gate کنید.
هفته سوم: Integration و Egress
Environment موقت با mock metadata/internal service و DNS/HTTP observer بسازید. Actual proxy/firewall/NetworkPolicy و IP واقعاً Dialشده را تأیید کنید.
هفته چهارم: Drill و rollout
Blind SSRF/XXE مجاز را با نرخ کم تمرین، Alert تا Runbook را دنبال، Gapها را رفع و تصمیم Adopt/Adapt/Expand/Stop را با Evidence ثبت کنید.
ضدالگوهای رایج
- نامیدن SSRF/XXE بهعنوان ریسکهای «خارج از OWASP» و ساخت Checklist ثابت؛
- جستوجوی فقط پارامتر
urlو نادیدهگرفتن Worker/renderer/parser؛ - اعتبارسنجی URL با Regex، substring یا denylist کوتاه؛
- بررسی Domain بدون IP نهایی، IPv6، CNAME و DNS change؛
- دنبالکردن Redirect بدون Policy مجدد؛
- اعتماد سرویس داخلی به Source IP یا شبکه؛
- معرفی WAF یا IMDSv2 بهعنوان رفع کامل SSRF؛
- کپی تنظیمات Java/XML به Parser و Runtime دیگر؛
- ادامه startup وقتی hardening feature پشتیبانی نمیشود؛
- تست XXE با فایل، Metadata یا DNS واقعی Production؛
- کمخطر دانستن Blind SSRF/XXE چون Response دیده نمیشود؛
- قبول status ۴۰۰/۵۰۰ بهعنوان اثبات نبود Connection؛
- NetworkPolicy بدون بررسی enforcement شبکه؛
- تعداد Payload/Scanner alert بهعنوان Coverage.
چکلیست انتشار
- همه URL/XML entry pointها و downstream sinkها Owner دارند.
- Capability، scheme/origin/port/DNS/redirect/response Contract شده است.
- Canonicalization و Parser differential برای IPv4/IPv6/IDN تست شدهاند.
- همه A/AAAAها و IP واقعاً Dialشده با Policy تطبیق دارند.
- Redirect هر Hop را دوباره اعتبارسنجی میکند یا غیرفعال است.
- Fetcher credential/header/cookie حساس Forward نمیکند.
- Egress واقعی default-deny/allowlist است و enforcement اثبات شده.
- سرویسهای داخلی Authentication/Authorization مستقل دارند.
- هر XML path آزمون no-external-resolution و resource limit دارد.
- خطا Fail-closed است و partial business action ندارد.
- Blind callback و Evidence فقط در Observer مجاز و بدون داده حساساند.
- Finding با Build، destination، control failure و Retest قابل بازتولید است.
سؤالات متداول
در SSRF، نرمافزار سمت سرور به مقصد ناخواسته درخواست میفرستد و از شبکه/هویت خود استفاده میکند. در CSRF، مرورگر کاربر احرازشده به انجام عمل ناخواسته روی یک سایت وادار میشود. منبع درخواست، مدل اعتماد و کنترلهای این دو متفاوتاند.
خیر. تطبیق باید دقیق و پس از Parse/Canonicalize باشد؛ همه A/AAAAها، IP نهایی اتصال، DNS change و هر Redirect نیز باید بررسی شوند. Egress network و احراز هویت سرویس داخلی لایههای مستقل لازماند.
خیر. TLS از انتقال در برابر برخی شنود/دستکاریها محافظت میکند، اما مجازبودن مقصد یا External resolution Parser را تعیین نمیکند. یک مقصد HTTPS نیز میتواند برای Fetcher نامجاز باشد.
از XML fixture با External reference به DNS/HTTP observer کنترلشده و EntityResolver spy استفاده کنید. انتظار، رد DOCTYPE یا صفرشدن Resolve/Connect است. سپس state کسبوکار و resource cleanup را نیز بررسی کنید.
خیر. SAST برای Source-to-sink و config مفید است و DAST رفتار و Blind callback را میسنجد، اما Parser واقعی، DNS، Redirect، Proxy، Egress، downstream worker و منطق کسبوکار به Evidence ترکیبی نیاز دارند.
جمعبندی
SSRF و XXE را با نام فهرستها مدیریت نکنید؛ مرز اعتماد را مدیریت کنید. سؤال اصلی این است: کدام داده، با کدام Parser و Resolver، تحت هویت کدام Workload، اجازه دارد به کدام Origin/IP/File وصل شود؛ و چه Evidenceای ثابت میکند Redirect، DNS، XML reference یا خطا این Policy را دور نمیزند؟ قابلیت را کوچک، Policy را Canonical و اتصال را محدود کنید؛ سپس از Unit تا Egress و Incident آن را اجرا و اندازهگیری کنید.

