تغییر مسیر باز چیست؟
Open Redirect یا «تغییر مسیر باز» وقتی رخ میدهد که برنامه آدرس مقصدِ یک هدایت را از ورودی تحت کنترل کاربر میخواند و بدون اعتبارسنجی کافی کاربر را به آن آدرس میفرستد. الگوی متعارف آن در پارامترهایی با این نامها دیده میشود: next، return، returnUrl، redirect، continue، url، dest، callback و redirect_uri.
پیادهسازی در سه شکل ظاهر میشود و هر سه باید آزموده شوند:
- هدایت سمت سرور: پاسخ
302با هدرLocationکه مستقیماً از پارامتر ساخته شده. - هدایت در HTML: تگ
<meta http-equiv="refresh">با آدرس تزریقشده. - هدایت سمت کلاینت: جاوااسکریپتی که مقدار پارامتر را به
location.href،location.assign()یاwindow.open()میدهد. این حالت — که در راهنمای آزمون OWASP زیر بخش آزمون سمت کلاینت قرار دارد — اغلب از دید اسکنرهای سمت سرور پنهان میماند.
مورد خاص و پرخطر، هدایت با طرح javascript: یا data: است. اگر مقصد فقط از نظر «همدامنه بودن» بررسی شود اما طرح آدرس بررسی نشود، تغییر مسیر باز مستقیماً به XSS ارتقا پیدا میکند.
چرا «کماهمیت» یک ارزیابی نادرست است
«Open Redirect شدت پایین دارد و ارزش گزارش کردن ندارد.» این ارزیابی، آسیبپذیری را در انزوا میسنجد. در عمل تغییر مسیر باز یک اولیهی زنجیره (Chain Primitive) است: بهتنهایی کاری نمیکند، اما ورودی لازم برای چند حملهی جدی را فراهم میکند. رد کردن آن بدون بررسی زنجیرههای ممکن، اشتباه رایج تیمهای توسعه و برخی گزارشهای تست نفوذ است.
پنج زنجیرهای که باید در هر ارزیابی بررسی شوند:
- سرقت کد مجوز OAuth. اگر یکی از آدرسهای ثبتشده بهعنوان
redirect_uriخودش تغییر مسیر باز داشته باشد، مهاجم کد مجوز را از طریق یک آدرس کاملاً «مجاز» به دامنهی خودش منتقل میکند. این خطرناکترین زنجیره است و به تصاحب حساب ختم میشود. - دور زدن فیلتر SSRF. اگر سرور فقط میزبانهای مجاز را میپذیرد اما تغییر مسیر را دنبال میکند، مهاجم آدرس مجاز را میدهد و آن آدرس با
302به منبع داخلی هدایت میشود. - Gadget برای دور زدن SameSite. هدایتی که خودِ سایت هدف انجام میدهد، درخواست حاصل را «همسایت» جلوه میدهد و محدودیت
Laxرا بیاثر میکند. - دور زدن فهرست سفید و CSP. هر جایی که یک دامنه بهعنوان مقصد یا منبع مورد اعتماد فهرست شده باشد، تغییر مسیر باز روی همان دامنه آن اعتماد را به دامنهی مهاجم منتقل میکند.
- فیشینگ با اعتبار دامنه. لینکی که با دامنهی واقعی سازمان شروع میشود، هم از نظر کاربر و هم از نظر فیلترهای ایمیل قابل اعتمادتر است. این تنها زنجیرهای است که به آسیبپذیری فنی دیگری نیاز ندارد.
دور زدن اعتبارسنجی سادهانگارانه
بیشتر پیادهسازیهای معیوب سعی میکنند با بررسی رشتهای «امن» باشند — و همینجا شکست میخورند. الگوهایی که باید در تست آزموده شوند:
| الگو | چه اعتبارسنجیای را میشکند |
|---|---|
//evil.example | بررسی «با / شروع میشود پس نسبی است» — مرورگر آن را آدرس مطلق بدون طرح میداند |
https://target.example@evil.example | بررسی «شامل دامنهی ماست» — بخش پیش از @ نام کاربری است، نه میزبان |
https://target.example.evil.example | تطبیق پیشوندی یا بررسی «با دامنهی ما شروع میشود» |
https://evil-target.example | الگوی منظم بدون لنگر یا با نقطهی فرارنشده |
https://evil.example#target.example | بررسی «شامل دامنهی ماست» — قطعهی URL هرگز به سرور نمیرود |
https:/\evil.example و /\/evil.example | نرمالسازی متفاوت اسلش وارون در مرورگرها |
| کدگذاری URL و کدگذاری دوگانه | فیلترهایی که پیش از کدگشایی تصمیم میگیرند |
الگوی مشترک همهی اینها یکی است: اختلاف بین تفسیر اعتبارسنج و تفسیر مرورگر از یک رشتهی URL. به همین دلیل هیچ فهرست سیاهی این مسئله را حل نمیکند و راهحل، تجزیهی واقعی آدرس و تطبیق با فهرست سفید است.
سناریوی واقعی و روش کشف در تست نفوذ
سناریو: سامانهای که پس از ورود، کاربر را به مقدار پارامتر returnUrl بازمیگرداند. اعتبارسنجی این است که رشته باید شامل target.example باشد. تیم توسعه این را کافی میداند. در تست، مقدار https://attacker.example/?x=target.example پذیرفته میشود. سپس مشخص میشود همان دامنه در فهرست redirect_uriهای سرور مجوزدهی ثبت شده است — و زنجیرهی سرقت کد مجوز کامل میشود. یافتهای که بهتنهایی «کماهمیت» برچسب خورده بود، به تصاحب حساب رسید.
روش کشف:
- شناسایی نقاط ورود: همهی پارامترهایی که آدرس یا مسیر میگیرند. ابزار ffuf برای کشف نام پارامترها و شناسایی آرشیوی برای یافتن آدرسهای تاریخی که هنوز کار میکنند مفید است.
- آزمون پایه: یک دامنهی تحت کنترل خودتان بگذارید و پاسخ را بررسی کنید — هم هدر
Location، هم بدنهی HTML و هم رفتار جاوااسکریپت. - آزمون الگوهای دور زدن از جدول بالا، بهترتیب.
- آزمون طرح آدرس:
javascript:وdata:برای ارتقا به XSS. - بررسی زنجیرهها: آیا این دامنه در فهرست
redirect_uriسرور مجوزدهی هست؟ آیا اندپوینتی وجود دارد که آدرس میگیرد و آن را واکشی میکند؟ آیا عملیات وضعیتتغییردهندهای وجود دارد که با SameSite محافظت میشود؟
نکتهی گزارشنویسی: شدت یافته را بر پایهی زنجیرهی اثباتشده بنویسید، نه بر پایهی خود تغییر مسیر. اگر زنجیرهای اثبات نشده، یافته را با شدت پایین اما با توضیح صریح زنجیرههای ممکن ثبت کنید.
نمونهی فنی و نگاشت به استانداردها
شکل سادهی اثبات مفهوم:
GET /login?returnUrl=//attacker.example/ HTTP/1.1
Host: app.example.com
HTTP/1.1 302 Found
Location: //attacker.example/و شکل امن پیادهسازی، که بهجای پذیرش آدرس، فقط یک کلید را میپذیرد:
// map, not URL
const DESTS = { dashboard: "/app", billing: "/app/billing" };
res.redirect(DESTS[req.query.to] ?? "/app");نگاشت به استانداردها
- CWE-601 — URL Redirection to Untrusted Site ("Open Redirect") شناسهی استاندارد این ضعف است.
- در OWASP Top 10:2025 دستهی مستقلی برای آن وجود ندارد؛ در گزارشنویسی معمولاً بر پایهی اثر نهایی زنجیره ردهبندی میشود — مثلاً ذیل A01 وقتی به سرقت کد مجوز و دسترسی غیرمجاز میانجامد، یا ذیل A06 وقتی ریشهی مسئله طراحی جریان بازگشت باشد.
- WSTG: حالت سمت کلاینت آن در بخش آزمون سمت کلاینت راهنمای آزمون OWASP (تغییر مسیر URL سمت کلاینت) پوشش داده شده است.
پرسشهای متداول
آیا Open Redirect واقعاً آسیبپذیری محسوب میشود؟
بله، اما ارزش آن در زنجیره است. بهتنهایی فقط کاربر را به سایت دیگری میفرستد؛ اما همان قابلیت، ورودی لازم برای سرقت کد مجوز OAuth، دور زدن فیلتر SSRF، خنثی کردن محدودیت SameSite و دور زدن فهرستهای سفید را فراهم میکند. ارزیابی درست این است که زنجیرههای ممکن را بررسی کنید و شدت را بر پایهی اثر اثباتشده تعیین کنید.
چطور جلوی Open Redirect را بگیریم؟
سادهترین و مؤثرترین راه این است که اصلاً آدرس کامل را از کاربر نپذیرید و بهجای آن یک کلید بگیرید که سمت سرور به مسیر ثابتی نگاشت میشود. اگر آدرس لازم است، آن را با کتابخانهی استاندارد تجزیه کنید و میزبان و طرح را با فهرست سفید مقایسه کنید. جستوجوی رشتهای و الگوی منظم دستساز تقریباً همیشه دور زده میشود.
چرا بررسی «آیا آدرس شامل دامنهی ماست» کافی نیست؟
چون دامنهی شما میتواند در جای بیاثری از آدرس ظاهر شود: https://attacker.example/?x=target.example، https://target.example@attacker.example، یا https://attacker.example#target.example. مرورگر میزبان را از ساختار URL تشخیص میدهد، نه از حضور یک رشته. اعتبارسنجی باید روی نتیجهی تجزیه انجام شود، نه روی متن خام.
آیا Open Redirect میتواند به XSS تبدیل شود؟
در صورتی که برنامه طرح آدرس را محدود نکرده باشد، بله. مقداری مثل javascript: در یک هدایت سمت کلاینت میتواند به اجرای اسکریپت در زمینهی سایت منجر شود. به همین دلیل محدود کردن طرح به http و https یک کنترل جداگانه و ضروری است.