آموزش جلوگیری از حملات CSRF در FortiWeb 7.6 با GUI و CLI
آموزش جلوگیری از حملات CSRF در FortiWeb 7.6 با GUI و CLI
حمله Cross-Site Request Forgery یا CSRF زمانی رخ میدهد که مهاجم مرورگر یک کاربر احراز هویتشده را فریب میدهد تا بدون اطلاع او، در یک وبسایت معتبر درخواست ناخواستهای ارسال کند. چون مرورگر معمولاً کوکی نشست را بهصورت خودکار همراه درخواست میفرستد، برنامه آسیبپذیر ممکن است درخواست جعلی را مانند درخواست واقعی کاربر پردازش کند.
FortiWeb برای کاهش این ریسک، روی صفحات مشخصشده یک اسکریپت قرار میدهد تا پارامتر ضد CSRF با نام tknfv به لینکها، فرمها و در صورت فعالبودن قابلیت مربوطه، درخواستهای XMLHttpRequest اضافه شود. سپس FortiWeb در URLهای حساس، وجود و درستی این توکن را با اطلاعات نشست کاربر بررسی میکند.
این مقاله از مرحله شناخت حمله تا طراحی Rule، پیکربندی در GUI و CLI، تست، عیبیابی و انتقال امن از حالت مانیتورینگ به حالت Block را توضیح میدهد تا برای ادمینهای تازهکار و کارشناسان باتجربه قابل استفاده باشد.
این مقاله بر اساس FortiWeb 7.6 نوشته شده است. در نسخههای دیگر ممکن است مسیرهای GUI، نام فیلدها یا رفتار برخی قابلیتها متفاوت باشد.
نکته نسخه: در مستندات و برخی Buildهای شاخه 7.6، گزینه مربوط به محافظت از درخواستهای AJAX با عنوان JS Request Status یا Ajaxcheck Status نمایش داده میشود. عملکرد موردنظر، افزودن توکن tknfv به درخواستهای مبتنی بر XMLHttpRequest است.
مروری بر این مقاله
- حمله CSRF چیست و چگونه اجرا میشود؟
- FortiWeb چگونه از درخواستها محافظت میکند؟
- پیشنیازها و محدودیتهای مهم
- طراحی Page List و URL List
- سناریوی نمونه کانفیگ
- پیکربندی CSRF در GUI
- پیکربندی CSRF در CLI
- استفاده از Parameter Filter
- روش تست و اعتبارسنجی
- خطاهای رایج و Troubleshooting
- Best Practiceهای عملیاتی
- چکلیست اجرایی
1. حمله CSRF چیست و چگونه اجرا میشود؟
فرض کنید کاربر وارد پنل بانکی، سامانه سازمانی یا پرتال مدیریت شده و کوکی نشست معتبر در مرورگر او وجود دارد. مهاجم لینکی برای کاربر ارسال میکند یا کدی را در یک سایت دیگر قرار میدهد که مرورگر قربانی را وادار میکند در پسزمینه درخواستی به سامانه هدف ارسال کند. اگر برنامه فقط به کوکی نشست اعتماد کند و منشأ یا توکن اختصاصی درخواست را بررسی نکند، ممکن است عملیات ناخواسته اجرا شود.
نمونه اثرهای احتمالی
- تغییر ایمیل، شماره تماس یا گذرواژه حساب کاربری
- ایجاد کاربر، تغییر سطح دسترسی یا حذف یک رکورد
- ثبت تراکنش، انتقال وجه یا تغییر اطلاعات پرداخت
- فعال یا غیرفعالکردن یک قابلیت مدیریتی
- ارسال درخواست از طرف کاربر بدون اطلاع او
هشدار: استفاده از متد POST بهتنهایی جلوی CSRF را نمیگیرد. اگر مرورگر بتواند درخواست را همراه کوکی معتبر ارسال کند و برنامه هیچ توکن یا کنترل تکمیلی نداشته باشد، درخواست POST نیز میتواند در معرض CSRF قرار بگیرد.
بر اساس راهنمای OWASP، دفاع اصلی باید در خود برنامه شامل توکن ضد CSRF، کنترل مجدد مجوزها و طراحی صحیح نشست باشد. FortiWeb یک لایه دفاعی تکمیلی در جلوی برنامه ایجاد میکند و نباید جایگزین کنترلهای امنیتی داخل Application در نظر گرفته شود.
2. FortiWeb چگونه از درخواستها محافظت میکند؟
قابلیت CSRF Protection در FortiWeb بر اساس ارتباط میان دو فهرست کار میکند:
| فهرست |
وظیفه |
نمونه |
| Page List Table |
صفحاتی که FortiWeb باید اسکریپت افزودن توکن را در پاسخ HTML آنها قرار دهد. |
/account/profile |
| URL List Table |
URLهایی که درخواست به آنها باید دارای توکن معتبر tknfv باشد. |
/api/account/email |
هنگامی که کاربر صفحهای از Page List را دریافت میکند، FortiWeb در پاسخ HTML اسکریپتی قرار میدهد که مقدار tknfv را به لینکها و فرمهای صفحه اضافه میکند. مقدار توکن با کوکی صادرشده توسط Client Management مرتبط است. وقتی مرورگر درخواستی به یکی از URLهای موجود در URL List ارسال میکند، FortiWeb مقدار توکن و نشست را بررسی میکند.
اگر توکن وجود نداشته باشد یا با مقدار مورد انتظار نشست تطبیق نکند، FortiWeb بر اساس Action تنظیمشده میتواند فقط Log ایجاد کند، درخواست را مسدود کند، بدون Log آن را رد کند یا برای یک بازه زمانی Client را Block کند.
محافظت از درخواستهای AJAX در FortiWeb 7.6
در FortiWeb 7.6 امکان افزودن توکن به درخواستهای JavaScript مبتنی بر XMLHttpRequest وجود دارد. برای این کار باید گزینه JS Request Status یا Ajaxcheck Status فعال باشد. مستند رسمی بهطور مشخص از تابع بومی XMLHttpRequest نام میبرد؛ بنابراین در برنامههایی که از fetch، کتابخانههای سفارشی، WebSocket، Mobile Client یا API Clientهای بدون مرورگر استفاده میکنند، حتماً رفتار واقعی برنامه را آزمایش کنید.
3. پیشنیازها و محدودیتهای مهم
پیشنیازهای اصلی
- ترافیک باید از یک Inline Protection Profile عبور کند.
- Client Management در Web Protection Profile فعال باشد.
- Web Protection Profile موردنظر روی Server Policy فعال و در مسیر واقعی ترافیک باشد.
- صفحات Page List و درخواستهای URL List دقیقاً با جریان واقعی برنامه تطبیق داده شوند.
- در صورت استفاده از Host Status، ابتدا Protected Host مربوط به دامنه یا IP تعریف شده باشد.
محدودیت حالت استقرار
طبق مستند Fortinet، این قابلیت در حالتهای Offline Protection و Transparent Inspection پشتیبانی نمیشود. علت عملیاتی این محدودیت آن است که FortiWeb برای این مکانیزم باید پاسخ HTML را تغییر دهد و کوکی نشست موردنیاز Client Management را مدیریت کند.
هشدار مهم: اگر یک URL را در URL List قرار دهید اما FortiWeb پیش از آن اسکریپت را از طریق صفحه متناظر در Page List به مرورگر تزریق نکرده باشد، درخواست Legitimate نیز ممکن است بدون توکن ارسال و Block شود.
4. طراحی Page List و URL List
مهمترین بخش کانفیگ، شناخت Flow واقعی برنامه است. قبل از ساخت Rule مشخص کنید هر عملیات حساس از کدام صفحه آغاز میشود و به کدام Endpoint درخواست میفرستد.
| سؤال طراحی |
پاسخ موردنیاز |
| کاربر از کدام صفحه عملیات را شروع میکند؟ |
این URL معمولاً باید در Page List قرار بگیرد. |
| فرم یا JavaScript درخواست را به کدام URL میفرستد؟ |
این Endpoint معمولاً باید در URL List قرار بگیرد. |
| آیا صفحه و Endpoint یک URL مشترک دارند؟ |
از Parameter Filter برای تفکیک درخواست نمایش صفحه و درخواست عملیاتی استفاده کنید. |
| آیا Endpoint توسط Mobile App یا API Client نیز مصرف میشود؟ |
Scope را با Host، URL و Parameter Filter محدود کنید یا Flow جداگانهای طراحی کنید. |
| آیا درخواست با XMLHttpRequest ارسال میشود؟ |
JS Request Status یا Ajaxcheck Status را فعال و نتیجه را در Browser DevTools بررسی کنید. |
Simple String یا Regular Expression؟
برای URLهای مشخص و ثابت از Simple String استفاده کنید. استفاده بیدلیل از Regular Expression میتواند Scope Rule را بیش از حد گسترده کند و احتمال False Positive را افزایش دهد. Regular Expression زمانی مناسب است که ساختار URL متغیر است و الگوی آن دقیقاً شناخته شده باشد.
5. سناریوی نمونه کانفیگ
در این سناریو، کاربر از صفحه پروفایل وارد فرم تغییر ایمیل میشود و فرم یک درخواست POST به Endpoint تغییر ایمیل ارسال میکند:
| مورد |
مقدار نمونه |
| دامنه برنامه |
portal.example.com |
| صفحه آغاز عملیات |
/account/profile |
| Endpoint حساس |
/api/account/email |
| نام Rule |
PARTIAN-CSRF |
| اقدام اولیه |
Alert |
| اقدام پس از Tune |
Alert & Deny |
در مرحله اول Rule را روی Alert قرار میدهیم تا درخواستهای واقعی، Endpointهای فراموششده و Clientهای غیرمرورگری مشخص شوند. پس از بررسی Logها و رفع False Positiveها، Action به Alert & Deny تغییر میکند.
6. پیکربندی CSRF در GUI
مرحله اول: ساخت CSRF Protection Rule
Web Protection > Advanced Protection > CSRF Protection
- روی Create New کلیک کنید.
- در قسمت Name مقدار PARTIAN-CSRF را وارد کنید.
- در شروع Tune، Action را روی Alert قرار دهید.
- Severity را متناسب با سیاست Log سازمان انتخاب کنید؛ برای شروع مقدار Medium مناسب است.
- در صورت نیاز Trigger Action را برای ارسال Alert یا اجرای Trigger Policy انتخاب کنید.
- برای برنامههای دارای درخواست AJAX مبتنی بر XMLHttpRequest، گزینه JS Request Status یا Ajaxcheck Status را فعال کنید.
- تنظیمات را ذخیره کنید.
مرحله دوم: افزودن صفحه به Page List Table
در داخل Rule و در بخش Page List Table روی Create New کلیک کنید و مقادیر زیر را وارد کنید:
| فیلد |
مقدار پیشنهادی سناریو |
| Host Status |
در صورت وجود چند Host روی یک Policy فعال شود؛ در سناریوی ساده میتواند غیرفعال باشد. |
| Host |
portal.example.com یا نام Protected Host از قبل ساختهشده |
| Request Type |
Simple String |
| Full URL |
/account/profile |
| Parameter Filter |
برای این سناریو غیرفعال |
مرحله سوم: افزودن Endpoint به URL List Table
در بخش URL List Table روی Create New کلیک کنید:
| فیلد |
مقدار پیشنهادی سناریو |
| Host Status |
مشابه Page List و متناسب با معماری Host |
| Request Type |
Simple String |
| Full URL |
/api/account/email |
| Parameter Filter |
در صورت نیاز برای محدودکردن Match فعال شود. |
مرحله چهارم: فعالکردن Rule در Inline Protection Profile
Policy > Web Protection Profile > Inline Protection Profile
- Profile متصل به Server Policy برنامه را Edit کنید.
- Client Management را فعال کنید.
- در فیلد CSRF Protection، Rule با نام PARTIAN-CSRF را انتخاب کنید.
- Profile را ذخیره کنید.
- اطمینان حاصل کنید همین Web Protection Profile در Server Policy فعال برنامه استفاده شده است.
نکته عملیاتی: اگر از Profile از پیش تعریفشده استفاده میکنید و امکان Edit آن وجود ندارد، آن را Clone کنید، Client Management و CSRF Protection را روی نسخه Cloneشده فعال کنید و سپس Profile جدید را به Server Policy اختصاص دهید.
7. پیکربندی CSRF در CLI
ساخت Rule در حالت Alert
config waf csrf-protection
edit "PARTIAN-CSRF"
set action alert
set severity Medium
set ajaxcheck enable
config csrf-page-list
edit 1
set request-url "/account/profile"
set request-type plain
next
end
config csrf-url-list
edit 1
set request-url "/api/account/email"
set request-type plain
next
end
next
end
در CLI مقدار plain معادل Simple String و مقدار regular معادل Regular Expression است. گزینه ajaxcheck enable برای افزودن توکن به درخواستهای XMLHttpRequest استفاده میشود.
اتصال Rule به Inline Protection Profile
config waf web-protection-profile inline-protection
edit "PARTIAN-INLINE-PROFILE"
set client-management enable
set csrf-protection "PARTIAN-CSRF"
next
end
نام PARTIAN-INLINE-PROFILE را با نام واقعی Web Protection Profile متصل به Server Policy جایگزین کنید.
محدودکردن Rule به Protected Host
اگر یک Profile برای چند دامنه استفاده میشود، بهتر است Page List و URL List را به Protected Host مشخص محدود کنید. نام Host باید از قبل در Protected Host Names تعریف شده باشد.
config waf csrf-protection
edit "PARTIAN-CSRF"
config csrf-page-list
edit 1
set host-status enable
set host "portal.example.com"
set request-url "/account/profile"
set request-type plain
next
end
config csrf-url-list
edit 1
set host-status enable
set host "portal.example.com"
set request-url "/api/account/email"
set request-type plain
next
end
next
end
تغییر Action به Alert & Deny پس از Tune
config waf csrf-protection
edit "PARTIAN-CSRF"
set action alert_deny
next
end
گزینههای Action در CLI
| مقدار CLI |
رفتار |
| alert |
درخواست پذیرفته میشود و در صورت فعالبودن Log یا Alert، رویداد ثبت میشود. |
| alert_deny |
درخواست Block میشود و Log یا Alert تولید میشود. |
| deny_no_log |
درخواست بدون تولید Log رد میشود. |
| block-period |
Client برای بازه 1 تا 3600 ثانیه Block میشود؛ مقدار پیشفرض CLI برای Block Period برابر 600 ثانیه است. |
8. استفاده از Parameter Filter
گاهی URL نمایش صفحه و URL دریافت فرم یکسان است. برای مثال درخواست GET به /post.asp صفحه را نمایش میدهد و درخواست POST به همان URL فایل را آپلود میکند. در این وضعیت FortiWeb باید تشخیص دهد کدام درخواست برای تزریق JavaScript و کدام درخواست برای بررسی توکن است.
Parameter Filter امکان میدهد Match علاوه بر URL، بر اساس یک پارامتر موجود در Query String یا HTTP Body انجام شود. در مثال زیر، وجود پارامتر SUB1 با هر مقداری نشان میدهد که درخواست مربوط به Submit فرم است:
config waf csrf-protection
edit "PARTIAN-CSRF-UPLOAD"
set action alert
config csrf-page-list
edit 1
set request-url "/post.asp"
set request-type plain
next
end
config csrf-url-list
edit 1
set request-url "/post.asp"
set request-type plain
set parameter-filter enable
set parameter-name "SUB1"
set parameter-value-type regular
set parameter-value "*"
next
end
next
end
نکته: Parameter Filter را تا حد ممکن بر اساس پارامتر پایدار و مشخص عملیات انتخاب کنید. انتخاب پارامتر عمومی یا Regex بیش از حد گسترده ممکن است درخواستهای نامرتبط را وارد Scope Rule کند.
9. روش تست و اعتبارسنجی
مرحله اول: تست تزریق توکن
- Rule را ابتدا روی Alert قرار دهید.
- با یک Browser جدید یا Private Window وارد برنامه شوید تا نشست تازه ساخته شود.
- صفحه /account/profile را از مسیر FortiWeb باز کنید.
- در Browser DevTools، تب Network را باز کنید.
- فرم تغییر ایمیل را ارسال کنید.
- در Request مربوط به /api/account/email وجود پارامتر
tknfv را در Query String یا Request Body بررسی کنید.
مرحله دوم: تست تطبیق توکن
- یک درخواست سالم را با ابزار تست مجاز سازمان یا Browser DevTools ثبت کنید.
- در محیط آزمایش، همان درخواست را بدون پارامتر
tknfv یا با مقدار تغییرکرده ارسال کنید.
- در حالت Alert باید درخواست عبور کند اما Attack Log مربوط به CSRF ایجاد شود.
- پس از فعالکردن Alert & Deny، همان درخواست ناقص باید Block شود.
مرحله سوم: تست Flowهای جانبی
- تمام دکمهها و فرمهای صفحه، نه فقط مسیر اصلی، آزمایش شوند.
- درخواستهای AJAX در Chrome، Firefox و Edge بررسی شوند.
- Login مجدد، Session Timeout، Logout و بازکردن صفحه در Tab جدید آزمایش شود.
- Mobile App، API Client، Integration و Jobهای خودکار که Endpoint یکسان را مصرف میکنند تست شوند.
- در صورت وجود CDN، Reverse Proxy یا Load Balancer جلوی FortiWeb، مسیر واقعی کوکی و Host Header بررسی شود.
هشدار تست: تغییر یا Replay درخواست فقط روی سامانهای انجام شود که مجوز تست آن را دارید. بهترین محل برای این بررسی، محیط Test یا Staging با داده غیرحساس است.
10. خطاهای رایج و Troubleshooting
| نشانه |
علت محتمل |
اقدام پیشنهادی |
| توکن tknfv به درخواست اضافه نمیشود. |
صفحه با Page List Match نشده، Client Management غیرفعال است یا پاسخ HTML شرایط لازم را ندارد. |
URL، Host، نوع Match و فعالبودن Client Management را بررسی کنید. |
| فرم سالم پس از فعالکردن Block قطع میشود. |
Endpoint در URL List است اما صفحه مبدأ در Page List وجود ندارد یا کاربر Endpoint را مستقیم فراخوانی میکند. |
Flow را کامل Mapping کنید و Rule را با Host یا Parameter Filter محدود کنید. |
| درخواست AJAX بدون توکن است. |
JS Request Status/Ajaxcheck غیرفعال است یا برنامه از سازوکاری غیر از native XMLHttpRequest استفاده میکند. |
گزینه را فعال و نوع واقعی Request API را در DevTools بررسی کنید. |
| FortiWeb اسکریپت را در صفحه قرار نمیدهد. |
پاسخ HTML معتبر نیست، تگهای <html> وجود ندارند، Status Code برابر 200 نیست یا پاسخ فشرده است. |
ساختار پاسخ، کد 200 و Uncompress Policy را بررسی کنید. |
| صفحه بزرگ محافظت نمیشود. |
مقدار Maximum Body Cache Size از اندازه صفحه کوچکتر است. |
اندازه پاسخ را اندازهگیری و مقدار Body Cache را متناسب تنظیم کنید. |
| روی یک دامنه درست و روی دامنه دیگر False Positive وجود دارد. |
Profile مشترک است و Rule فقط بر اساس URL Match میشود. |
Host Status را فعال و Protected Host صحیح را انتخاب کنید. |
| API Client یا Mobile App Block میشود. |
Client غیرمرورگری صفحه HTML را دریافت نمیکند و در نتیجه توکن FortiWeb را ندارد. |
Endpoint مشترک را از Scope عمومی خارج نکنید؛ ابتدا معماری را تفکیک یا Match را دقیقتر کنید. |
شرایط رسمی Fortinet برای تزریق صحیح اسکریپت
- نوع صفحه باید HTML باشد و تگهای <html> و </html> را داشته باشد.
- HTTP Response Code صفحه باید 200 OK باشد.
- برای پاسخ فشرده، Uncompress Policy متناظر تنظیم شده باشد.
- مقدار Maximum Body Cache Size از اندازه صفحه بزرگتر باشد.
11. Best Practiceهای عملیاتی
- از Alert شروع کنید: ابتدا رفتار واقعی سامانه را مشاهده و سپس Block را فعال کنید.
- Scope را کوچک نگه دارید: فقط عملیاتهای State-Changing و حساس را وارد URL List کنید.
- Page و URL را مستند کنید: برای هر Endpoint حساس، صفحه یا Flow تولیدکننده درخواست مشخص باشد.
- Host Status را در محیط Multi-Tenant فعال کنید: URL مشابه در دامنههای مختلف نباید ناخواسته Match شود.
- Regex را محدود کنید: Simple String برای URL ثابت امنتر و قابلپیشبینیتر است.
- Clientهای غیرمرورگری را فراموش نکنید: Mobile App، Integration و API Client ممکن است توکن تزریقشده به HTML را دریافت نکنند.
- همه Browserها را تست کنید: JavaScript، Cookie Policy و Extensionهای مرورگر میتوانند روی Flow اثر بگذارند.
- Application-Level CSRF را حفظ کنید: توکن داخلی Framework، SameSite Cookie، کنترل Origin/Referer و Authorization را حذف نکنید.
- Log و Trigger را فعال کنید: بدون Log کافی، Tune و تشخیص False Positive دشوار میشود.
- پس از تغییر برنامه Regression Test انجام دهید: تغییر Frontend، Form Action یا API Route میتواند Mapping قبلی را نامعتبر کند.
دفاع چندلایه: بهترین نتیجه زمانی به دست میآید که FortiWeb در کنار توکن ضد CSRF خود برنامه، تنظیم صحیح کوکیهای Session، کنترل دسترسی سمت سرور و مانیتورینگ امنیتی استفاده شود.
12. چکلیست اجرایی
- نسخه و Build دقیق FortiWeb ثبت شده است.
- Deployment Mode از CSRF Protection پشتیبانی میکند.
- Server Policy و Inline Protection Profile صحیح شناسایی شدهاند.
- Client Management فعال است.
- تمام Pageهای تولیدکننده درخواست حساس شناسایی شدهاند.
- تمام Endpointهای نیازمند توکن در URL List قرار گرفتهاند.
- Host Status در محیط چنددامنهای بررسی شده است.
- برای URLهای مشترک، Parameter Filter طراحی شده است.
- JS Request Status/Ajaxcheck برای XMLHttpRequest بررسی شده است.
- Rule ابتدا در حالت Alert آزمایش شده است.
- وجود tknfv در درخواست سالم تأیید شده است.
- درخواست بدون توکن در Log شناسایی شده است.
- مرورگرها، Mobile Appها و Integrationها Regression Test شدهاند.
- پس از Tune، Action به Alert & Deny تغییر کرده است.
- Attack Log و Trigger Policy مانیتور میشوند.
- مستندات Application Flow پس از هر Release بهروزرسانی میشوند.
<grammarly-desktop-integration data-grammarly-shadow-root="true" style="visibility: visible !important;"></grammarly-desktop-integration>