پرش به محتوای اصلی
آسیب‌پذیری‌های سایت

امنیت WebSocket چیست؟ بررسی حملات و تنظیمات امنیتی WebSocket

امنیت WebSocket شامل مجموعه‌ای از کنترل‌ها برای محافظت از ارتباط دائمی و دوطرفه میان Client و Server است. استفاده از WSS به تنهایی کافی نیست و ضعف‌هایی مانند Cross-Site WebSocket Hijacking، دسترسی غیرمجاز، Injection، Replay و حملات DoS همچنان ممکن است وجود داشته باشند. بررسی Origin، مدیریت صحیح Session، Authorization در سطح هر پیام، Input Validation، Rate Limiting و Logging از مهم‌ترین راهکارهای افزایش امنیت WebSocket هستند.

تیم امنیت رخنه‌کاو ۴۲ دقیقه مطالعه انتشار:

پاسخ کوتاه: امنیت WebSocket مجموعه‌ای از کنترل‌ها برای محافظت از ارتباط دائمی و دوطرفه میان کاربر و سرور است. استفاده از WSS، بررسی Origin، احراز هویت صحیح، کنترل دسترسی در سطح هر پیام، اعتبارسنجی داده‌ها، محدودسازی نرخ و اندازه پیام، مدیریت Session و ثبت رویدادهای امنیتی از مهم‌ترین اجزای آن هستند.

WebSocket یکی از فناوری‌های مهم در برنامه‌های وب مدرن است. چت آنلاین، داشبوردهای لحظه‌ای، سامانه‌های معاملات مالی، بازی‌های تحت وب، اعلان‌های زنده، ابزارهای همکاری گروهی و بسیاری از سرویس‌های Real-Time برای برقراری ارتباط دائمی میان مرورگر و سرور از WebSocket استفاده می‌کنند.

برخلاف الگوی سنتی HTTP که در آن معمولاً کلاینت یک درخواست ارسال می‌کند و سرور پاسخ می‌دهد، WebSocket پس از برقراری اتصال، یک کانال ارتباطی دوطرفه و نسبتاً طولانی‌مدت ایجاد می‌کند. سرور می‌تواند بدون منتظر ماندن برای یک درخواست HTTP جدید، داده را برای کلاینت ارسال کند و کلاینت نیز قادر است در همان اتصال پیام‌های جدیدی به سرور بفرستد.

همین قابلیت، در کنار مزایای عملکردی، سطح حمله متفاوتی ایجاد می‌کند. اگر توسعه‌دهنده تصور کند امن بودن HTTPS یا استفاده از wss:// به‌تنهایی برای تأمین امنیت WebSocket کافی است، ممکن است مشکلاتی مانند Cross-Site WebSocket Hijacking، ضعف احراز هویت، دسترسی غیرمجاز به عملیات، Injection، سرقت Session، Replay، سوءاستفاده از منابع سرور و حملات Denial of Service به وجود بیاید.

RFC 6455 برای WebSocket یک مدل امنیتی مبتنی بر Origin در مرورگر تعریف می‌کند و سرورها می‌توانند هنگام Handshake مقدار Origin را بررسی کنند. در عین حال RFC تأکید می‌کند که کلاینت‌های غیرمرورگری می‌توانند مقدار Origin را جعل کنند؛ بنابراین Origin جایگزین Authentication نیست و نباید به‌عنوان هویت کاربر در نظر گرفته شود.

در این مقاله از رخنه‌کاو بررسی می‌کنیم امنیت WebSocket چیست، اتصال WebSocket چگونه شکل می‌گیرد، مهم‌ترین تهدیدهای آن کدام‌اند و برای طراحی یک معماری امن چه تنظیماتی باید در مرورگر، سرور، Reverse Proxy، WAF و منطق برنامه اعمال شود.

WebSocket چیست و چرا امنیت آن با HTTP تفاوت دارد؟

WebSocket یک پروتکل ارتباطی Full-Duplex است؛ یعنی بعد از ایجاد اتصال، هر دو سمت ارتباط می‌توانند مستقل از یکدیگر داده ارسال کنند.

در یک درخواست HTTP عادی معمولاً چرخه مشخصی داریم:

Client → Request → Server → Response

اما در WebSocket وضعیت به شکل زیر تغییر می‌کند:

Client ↔ Persistent Connection ↔ Server

اتصال ممکن است چند ثانیه، چند دقیقه یا حتی ساعت‌ها فعال بماند. بنابراین کنترل امنیتی فقط در زمان ایجاد اتصال کافی نیست.

این تفاوت بسیار مهم است. در بسیاری از برنامه‌ها هنگام Handshake بررسی می‌شود که کاربر وارد حساب شده است، اما پس از برقراری اتصال، هر پیامی که از همان Socket دریافت شود به‌طور ضمنی مجاز در نظر گرفته می‌شود. چنین طراحی‌ای می‌تواند باعث Broken Access Control شود.

برای مثال تصور کنید یک سامانه مالی WebSocket را برای عملیات زیر استفاده می‌کند:

  • مشاهده قیمت لحظه‌ای
  • دریافت وضعیت سفارش
  • ایجاد سفارش
  • لغو سفارش
  • دریافت موجودی حساب

این عملیات سطح حساسیت یکسانی ندارند. اینکه کاربر اجازه مشاهده قیمت بازار را دارد، به این معنی نیست که هر پیام دیگری که از همان اتصال ارسال می‌کند نیز باید مجاز تلقی شود.

بنابراین یکی از اصول امنیت WebSocket این است که:

Authentication هنگام اتصال انجام می‌شود، اما Authorization باید متناسب با هر عملیات نیز بررسی شود. اتصال WebSocket چگونه برقرار می‌شود؟

اتصال WebSocket چگونه برقرار می‌شود؟

برای درک حملات WebSocket ابتدا باید Handshake آن را بشناسیم.

برقراری ارتباط معمولاً با یک درخواست HTTP آغاز می‌شود. کلاینت از سرور می‌خواهد اتصال معمولی HTTP به WebSocket ارتقا پیدا کند.

درخواست ممکن است از نظر مفهومی شامل موارد زیر باشد:

GET /socket HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13
Origin: https://example.com

در صورتی که سرور درخواست را بپذیرد، معمولاً پاسخ 101 Switching Protocols ارسال می‌شود و از آن لحظه ارتباط وارد پروتکل WebSocket خواهد شد.

RFC 6455 نسخه 13 را به‌عنوان نسخه استاندارد WebSocket تعریف می‌کند. این RFC همچنین استفاده از Origin را برای مشخص کردن منشأ اسکریپتی که از مرورگر اتصال را ایجاد کرده در نظر گرفته است.

بعد از Handshake، دیگر با مجموعه مستقلی از HTTP Request و HTTP Response روبه‌رو نیستیم. داده‌ها در قالب WebSocket Frame میان دو سمت منتقل می‌شوند.

این مسئله روی ابزارهای امنیتی نیز تأثیر می‌گذارد. برای مثال یک Access Log سنتی ممکن است فقط درخواست Upgrade را ثبت کند، در حالی که هزاران پیام بعدی داخل اتصال بدون ثبت شدن در همان لاگ HTTP تبادل شوند.

OWASP به همین دلیل تأکید می‌کند که مانیتورینگ WebSocket باید پیام‌ها، خطاهای احراز هویت، شکست‌های Authorization، محدودیت نرخ و قطع اتصال‌های غیرعادی را نیز پوشش دهد.

امنیت WebSocket از چه لایه‌هایی تشکیل می‌شود؟

امنیت WebSocket را نباید یک تنظیم واحد در نظر گرفت. یک پیاده‌سازی امن معمولاً چند لایه دفاعی دارد.

لایه اول امنیت انتقال است. داده باید با WSS و TLS منتقل شود.

لایه دوم امنیت Handshake است. سرور باید بررسی کند اتصال از Origin مجاز ایجاد شده و در صورت نیاز Authentication و کنترل CSRF مناسب انجام شود.

لایه سوم مربوط به Session است. اتصال WebSocket نباید پس از منقضی شدن Session یا Logout همچنان با دسترسی قبلی فعال بماند.

لایه چهارم Authorization است. هر Action یا Message حساس باید براساس مجوز واقعی همان کاربر ارزیابی شود.

لایه پنجم Input Validation است. تمام داده‌های دریافتی باید ورودی غیرقابل‌اعتماد فرض شوند.

لایه ششم Resource Protection است. تعداد Connectionها، سرعت پیام‌ها، اندازه پیام و مصرف حافظه باید محدود شود.

لایه هفتم Monitoring و Logging است. رخدادهای امنیتی WebSocket باید قابل مشاهده و بررسی باشند.

این مدل چندلایه اهمیت زیادی دارد، زیرا شکست یک کنترل نباید مستقیماً باعث دسترسی کامل مهاجم شود.

تفاوت ws و wss چیست؟

دو Scheme رایج برای WebSocket عبارت‌اند از:

ws://
wss://

ws:// را می‌توان از نظر امنیت انتقال تقریباً مشابه HTTP بدون TLS دانست.

wss:// از WebSocket روی TLS استفاده می‌کند و مشابه رابطه HTTPS با HTTP است.

در محیط Production باید از WSS استفاده شود.

OWASP توصیه می‌کند ارتباط WebSocket در محیط عملیاتی با wss:// انجام شود، زیرا اتصال بدون رمزنگاری می‌تواند در برابر شنود یا تغییر ترافیک آسیب‌پذیر باشد. MDN نیز استفاده از WebSocket ناامن در صفحات امن را به دلیل مشکلات Mixed Content نامناسب می‌داند.

اما یک نکته بسیار مهم وجود دارد:

WSS امنیت کامل WebSocket نیست.

TLS از محرمانگی و یکپارچگی داده در مسیر انتقال محافظت می‌کند. اگر سرور به یک کاربر غیرمجاز اجازه اجرای Action حساس بدهد، TLS جلوی آن را نمی‌گیرد.

به همین شکل، اگر برنامه در برابر CSWSH، XSS یا Injection آسیب‌پذیر باشد، استفاده از WSS به تنهایی مشکل را برطرف نمی‌کند.

تنظیم TLS مناسب برای WebSocket

از آنجا که WSS به TLS وابسته است، امنیت TLS مستقیماً بر امنیت WebSocket تأثیر دارد.

در یک محیط مدرن بهتر است TLS 1.3 در اولویت باشد و در صورت نیاز به سازگاری، TLS 1.2 نیز به‌صورت ایمن پشتیبانی شود. OWASP غیرفعال کردن TLS 1.0 و TLS 1.1 را توصیه می‌کند و NIST نیز در SP 800-52 Rev.2 راهنمای تنظیم و انتخاب TLS را ارائه کرده است.

موارد مهم شامل این موارد هستند:

  • استفاده از Certificate معتبر
  • غیرفعال‌سازی پروتکل‌های قدیمی SSL و TLS
  • استفاده از Cipher Suiteهای امن
  • جلوگیری از Downgradeهای ناامن
  • تمدید و مدیریت صحیح Certificate
  • استفاده از WSS برای تمام Endpointهای حساس

اگر خود برنامه HTTPS باشد ولی برای WebSocket از ws:// استفاده شود، علاوه بر ایجاد خطر امنیتی، مرورگرهای مدرن ممکن است چنین ارتباطی را به‌عنوان Mixed Content مسدود کنند. Cross-Site WebSocket Hijacking چیست؟

Cross-Site WebSocket Hijacking چیست؟

یکی از مهم‌ترین حملات مرتبط با امنیت WebSocket، حمله Cross-Site WebSocket Hijacking یا به اختصار CSWSH است.

این آسیب‌پذیری از نظر مفهومی شباهت‌هایی به CSRF دارد.

فرض کنید کاربر وارد سایت example.com شده و مرورگر او Session Cookie معتبر دارد. سایت از WebSocket برای تبادل اطلاعات استفاده می‌کند.

اگر WebSocket Server بدون بررسی Origin هر اتصال دارای Cookie معتبر را بپذیرد، یک سایت دیگر ممکن است بتواند از مرورگر همان کاربر اتصال WebSocket به سرویس اصلی ایجاد کند.

مرورگر در بعضی شرایط Cookieهای مربوط به مقصد را همراه Handshake ارسال می‌کند. اگر سرور فقط وجود Cookie را ملاک اعتماد قرار دهد، احتمال ایجاد یک اتصال معتبر از صفحه‌ای غیرمجاز وجود خواهد داشت.

در این شرایط ممکن است عملیات WebSocket با Session قربانی انجام شود.

OWASP این سناریو را Cross-Site WebSocket Hijacking معرفی می‌کند و بررسی Origin را یکی از کنترل‌های اصلی آن می‌داند.

PortSwigger نیز CSWSH را نوعی سوءاستفاده از ضعف CSRF در Handshake مربوط به WebSocket توصیف می‌کند که بسته به قابلیت‌های Endpoint می‌تواند به انجام عملیات در سطح دسترسی قربانی یا مشاهده داده‌های مرتبط با Session او منجر شود. بررسی Origin؛ یکی از مهم‌ترین تنظیمات امنیت WebSocket

بررسی Origin؛ یکی از مهم‌ترین تنظیمات امنیت WebSocket

مرورگر هنگام ایجاد WebSocket معمولاً Headerای به نام Origin ارسال می‌کند.

برای مثال:

Origin: https://app.example.com

سرور باید این Origin را با لیست مشخصی از Originهای مجاز مقایسه کند.

الگوی پیشنهادی:

Allowed:
https://example.com
https://app.example.com

Rejected:
https://evil.example
https://example.com.attacker.tld

استفاده از Allowlist دقیق بسیار امن‌تر از بررسی‌های مبهم است.

برای مثال بررسی‌هایی شبیه این از نظر طراحی مناسب نیستند:

Origin contains "example.com"

چنین منطقی می‌تواند دامنه‌هایی مانند زیر را به اشتباه بپذیرد:

example.com.attacker.tld

مقایسه باید روی Origin کامل انجام شود.

RFC 6455 صراحتاً بیان می‌کند سرورهایی که قرار نیست از هر صفحه وبی ورودی دریافت کنند باید Origin مورد انتظار را بررسی کنند و در صورت نامعتبر بودن Origin، اتصال را نپذیرند.

آیا Origin نوعی Authentication است؟

خیر.

این اشتباه بسیار مهمی است.

Origin برای محدود کردن Context مرورگری مفید است، اما هویت کاربر را اثبات نمی‌کند.

یک کلاینت غیرمرورگری می‌تواند Headerهای دلخواه، از جمله Origin، تولید کند. خود RFC 6455 نیز درباره این موضوع هشدار می‌دهد.

بنابراین منطق زیر نادرست است:

Origin معتبر است → پس کاربر معتبر است.

ساختار صحیح‌تر:

Origin معتبر
+
Authentication معتبر
+
Session معتبر
+
Authorization متناسب با Action
=
اجازه پردازش

Origin یک لایه دفاعی است، نه جایگزین هویت.

تفاوت CORS و امنیت WebSocket

یکی از اشتباهات رایج این است که توسعه‌دهندگان تصور می‌کنند تنظیم CORS به‌طور خودکار WebSocket را نیز امن می‌کند.

WebSocket در مرورگر همان مدل عادی Fetch/XHR و CORS را دنبال نمی‌کند. Handshake یک HTTP Upgrade است و کنترل Origin در سمت WebSocket Server اهمیت مستقلی دارد.

بنابراین حتی اگر APIهای REST سایت دارای CORS بسیار محدود باشند، Endpoint مربوط به WebSocket باید جداگانه بررسی شود.

تنظیمات CORS خوب نمی‌تواند جای Origin Validation در WebSocket را بگیرد.

همین موضوع باعث می‌شود WebSocket Endpointها هنگام تست امنیت وب به‌صورت مستقل بررسی شوند.

احراز هویت در WebSocket چگونه باید انجام شود؟

پروتکل WebSocket به خودی خود یک سیستم Authentication اختصاصی در اختیار برنامه قرار نمی‌دهد. برنامه باید مدل احراز هویت را طراحی کند.

روش‌های مختلفی ممکن است استفاده شوند:

Session Cookie، Token، Ticket کوتاه‌عمر یا یک مرحله Authentication بعد از ایجاد اتصال.

اگر از Cookie استفاده می‌شود، باید در نظر داشت که مرورگر می‌تواند Cookie مرتبط را در Handshake ارسال کند. همین موضوع یکی از دلایل اهمیت CSWSH است.

اگر از Token استفاده می‌شود نیز محل انتقال Token اهمیت دارد.

قرار دادن Access Token حساس در Query String مانند:

wss://example.com/socket?token=...

ریسک دارد، زیرا URL ممکن است در Proxy، Access Log، Monitoring System یا History ابزارهای داخلی ثبت شود.

OWASP توصیه می‌کند در صورت استفاده از Token در Query String، Logها به شکلی تنظیم شوند که Tokenها Redact شوند و در طراحی‌های حساس‌تر از روش‌هایی استفاده شود که Token در Logهای URL ظاهر نشود.

در Browser WebSocket API نیز توسعه‌دهنده مانند Fetch نمی‌تواند آزادانه هر Header سفارشی، از جمله Authorization، را هنگام ساخت اتصال اضافه کند. به همین دلیل معماری Authentication باید از ابتدا با محدودیت‌های محیط مرورگر طراحی شود.

چرا احراز هویت فقط هنگام Handshake کافی نیست؟

WebSocket ممکن است مدت زیادی باز بماند.

فرض کنید:

  1. کاربر وارد حساب می‌شود.
  2. WebSocket ایجاد می‌شود.
  3. سرور Session را هنگام Handshake معتبر می‌داند.
  4. سی دقیقه بعد Session منقضی می‌شود.
  5. WebSocket هنوز باز است.
  6. سرور بدون بررسی مجدد پیام‌ها را می‌پذیرد.

در این شرایط ممکن است اتصال از عمر Session بیشتر شود.

همین مشکل هنگام Logout نیز دیده می‌شود.

اگر کاربر روی Logout کلیک کند اما WebSocket فعال باقی بماند، از دید کاربر Session تمام شده ولی در Backend ممکن است کانال قدیمی هنوز توان انجام عملیات داشته باشد.

برای رفع این مشکل باید ارتباط میان Lifecycle نشست و Lifecycle اتصال WebSocket برقرار شود.

OWASP توصیه می‌کند اعتبار Session در اتصال‌های طولانی دوباره بررسی شود و هنگام Logout اتصال‌های مرتبط با Session بسته شوند.

در معماری‌های حساس بهتر است Backend بتواند Session یا User را به Active WebSocket Connectionهای او نگاشت کند تا هنگام Revocation، Logout یا تغییر دسترسی، Connectionهای مربوطه نیز بسته شوند.

Authorization در سطح پیام

یکی از مهم‌ترین اصول امنیت WebSocket این است:

باز بودن Socket به معنی مجاز بودن تمام پیام‌ها نیست.

فرض کنید پس از Login یک WebSocket ایجاد شده است و پیام‌ها دارای ساختاری مانند این هستند:

{
  "action": "view_order",
  "order_id": 2718
}

اگر سرور فقط بررسی کند کاربر Login است و سپس order_id را اجرا کند، احتمال بروز IDOR یا Broken Object Level Authorization وجود دارد.

سرور باید بررسی کند:

  • این Action برای Role کاربر مجاز است؟
  • Object مورد درخواست متعلق به همین کاربر است؟
  • حساب کاربر اجازه این عملیات را دارد؟
  • وضعیت فعلی Resource اجازه Action را می‌دهد؟
  • عملیات از نظر Business Logic معتبر است؟

همین قاعده درباره پیام‌هایی مانند حذف کاربر، تغییر تنظیمات، ارسال پیام، تغییر سفارش، انتقال دارایی یا عملیات مدیریتی نیز وجود دارد.

OWASP توصیه می‌کند Authorization برای Actionهای WebSocket در سطح پیام انجام شود و صرف برقراری اتصال، مجوز کامل تلقی نشود.

Input Validation در WebSocket

تمام داده‌ای که از WebSocket دریافت می‌شود باید Untrusted Input فرض شود.

استفاده از WebSocket هیچ‌کدام از آسیب‌پذیری‌های کلاسیک Input را حذف نمی‌کند.

اگر پیام دریافت‌شده بدون کنترل وارد Query پایگاه داده شود، SQL Injection همچنان ممکن است.

اگر داده بدون Encoding در DOM نمایش داده شود، XSS همچنان ممکن است.

اگر ورودی وارد Shell یا Process سیستم‌عامل شود، Command Injection همچنان یک تهدید است.

اگر Objectهای پیچیده بدون محدودیت Deserialize شوند، آسیب‌پذیری‌های Deserialization ممکن است مطرح شوند.

پس WebSocket فقط روش انتقال داده است؛ امنیت داده همچنان مسئولیت Application است.

اعتبارسنجی ساختار پیام

بهتر است سرور برای هر نوع Message یک Schema مشخص داشته باشد.

برای نمونه:

{
  "type": "send_message",
  "room_id": 25,
  "message": "..."
}

سرور باید تعیین کند:

type چه مقادیری می‌تواند داشته باشد؟

room_id باید عدد باشد یا String؟

حداکثر طول message چقدر است؟

آیا Field اضافی پذیرفته می‌شود؟

آیا کاربر عضو room_id است؟

آیا Unicode و Encoding پیام به‌درستی کنترل می‌شود؟

به جای اعتماد به ساختار ورودی، می‌توان Schema Validation را در Backend اعمال کرد.

در سامانه‌های JSON، استفاده از JSON Parser استاندارد ضروری است. استفاده از روش‌هایی مانند eval() برای پردازش داده JSON می‌تواند امکان اجرای کد ناخواسته ایجاد کند و نباید انجام شود. OWASP نیز استفاده از Parser امن و اعتبارسنجی ساختار پیام را توصیه می‌کند.

XSS از طریق پیام‌های WebSocket

گاهی توسعه‌دهنده فکر می‌کند چون داده از WebSocket دریافت شده است، دیگر ورودی کاربر محسوب نمی‌شود.

اما فرض کنید سیستم Chat یک پیام را از WebSocket دریافت کرده و مستقیم وارد صفحه کند.

اگر داده بدون Context-Aware Output Encoding یا Sanitization مناسب وارد HTML شود، XSS می‌تواند ایجاد شود.

بنابراین در سمت Client نیز داده‌های دریافتی از WebSocket قابل اعتماد نیستند.

PortSwigger توصیه می‌کند داده دریافت‌شده از WebSocket در هر دو سمت Client و Server غیرقابل‌اعتماد در نظر گرفته شود تا آسیب‌پذیری‌هایی مانند XSS و SQL Injection شکل نگیرند.

راهکار کلی مشابه سایر بخش‌های امنیت وب است:

در HTML از Output Encoding مناسب استفاده شود.

در صورت نیاز به HTML محدود، Sanitizer معتبر به کار رود.

داده از WebSocket مستقیماً به innerHTML یا APIهای مشابه تزریق نشود.

سمت Backend نیز ورودی براساس Schema و نوع داده بررسی شود.

SQL Injection و Command Injection

WebSocket هیچ حفاظ داخلی در مقابل SQL Injection ندارد.

اگر Backend پیامی مانند:

{
  "action": "search",
  "query": "..."
}

را دریافت کند و مقدار ورودی مستقیماً در Query ساخته شود، خطر SQL Injection مشابه یک API عادی خواهد بود.

همین موضوع درباره Command Injection نیز صدق می‌کند.

بنابراین باید از:

Parameterized Queries

Prepared Statements

Allowlist Validation

Safe APIها

و جداسازی ورودی کاربر از Command یا Query استفاده شود.

نکته کلیدی این است که فیلتر امنیتی نباید صرفاً بر HTTP Endpointها متمرکز باشد. اگر WAF درخواست‌های HTTP را بررسی کند ولی Frameهای WebSocket از کنترل Application عبور کنند، مسیر دیگری برای رسیدن ورودی مخرب به Backend ایجاد می‌شود.

حملات Replay در WebSocket

در برخی پروتکل‌های Application-Level، ارسال دوباره یک پیام معتبر می‌تواند باعث تکرار یک عملیات حساس شود.

برای مثال یک پیام ممکن است معنای زیر را داشته باشد:

Approve transaction

اگر برنامه نتواند تشخیص دهد این پیام قبلاً پردازش شده، امکان Replay منطقی مطرح می‌شود.

بسته به نوع سیستم، می‌توان از:

Nonce

Timestamp

Sequence Number

Idempotency Key

شناسه یکتای درخواست

برای جلوگیری از تکرار عملیات حساس استفاده کرد.

البته این کنترل باید در Backend انجام شود و نباید فقط به ترتیب ظاهری پیام‌ها در Client اعتماد کرد.

OWASP نیز استفاده از Timestamp یا Nonce را برای سناریوهایی که Replay اهمیت دارد پیشنهاد می‌کند. Denial of Service در WebSocket

Denial of Service در WebSocket

ویژگی Persistent Connection باعث می‌شود مدیریت منابع یکی از بخش‌های مهم امنیت WebSocket باشد.

در HTTP معمولاً Request ایجاد، پردازش و پایان می‌یابد. در WebSocket ممکن است هزاران Connection به‌صورت هم‌زمان باز بمانند.

هر Connection می‌تواند منابعی مانند:

Memory

Socket Descriptor

Connection State

Queue

Buffer

Thread یا Event Loop Capacity

مصرف کند.

اگر محدودیت مناسبی وجود نداشته باشد، مهاجم می‌تواند تعداد زیادی اتصال ایجاد کند یا حجم بالایی از پیام ارسال کند.

Connection Exhaustion

در این سناریو تعداد زیادی اتصال WebSocket باز می‌شود تا ظرفیت سرور، Proxy یا Load Balancer مصرف شود.

برای کاهش خطر باید محدودیت‌هایی بر موارد زیر اعمال شود:

تعداد کل Connectionها

تعداد Connection برای هر User

تعداد Connection برای IP

تعداد Connection ناشناس

و مدت زمان اتصال‌های بدون فعالیت.

محدودیت per-user در بسیاری از سامانه‌ها از per-IP دقیق‌تر است، زیرا تعداد زیادی کاربر ممکن است پشت NAT مشترک قرار داشته باشند.

Message Flooding

در Message Flooding مهاجم تعداد بسیار زیادی Message در یک اتصال یا چند اتصال ارسال می‌کند.

حتی اگر هر Message کوچک باشد، پردازش JSON، Validation، دسترسی پایگاه داده، ارسال Event یا Logging ممکن است منابع قابل توجهی مصرف کند.

بنابراین Rate Limiting باید فقط روی Handshake اعمال نشود.

Rate Limiting در سطح Message نیز اهمیت دارد.

برای مثال ممکن است برای Actionهای متفاوت سقف متفاوتی تعیین شود:

پیام Chat: محدودیت متناسب با رفتار کاربر

Search: محدودیت سخت‌تر به دلیل هزینه Query

Operation مالی: محدودیت بسیار پایین‌تر و کنترل Idempotency

Heartbeat: سیاست جداگانه

نباید یک عدد ثابت برای تمام برنامه‌ها در نظر گرفت. میزان مناسب به معماری، ظرفیت Backend و ماهیت سرویس بستگی دارد.

Oversized Message و مصرف حافظه

WebSocket می‌تواند Payloadهای نسبتاً بزرگ حمل کند.

اگر Server بدون محدودیت Payload را در حافظه Buffer کند، ارسال پیام‌های بسیار بزرگ می‌تواند باعث Memory Exhaustion شود.

به همین دلیل یکی از کنترل‌های مهم:

Maximum Message Size

است.

حد مناسب باید براساس کاربرد واقعی سیستم مشخص شود.

اگر پیام‌های برنامه معمولاً چند کیلوبایت هستند، پذیرش پیام چندصد مگابایتی منطقی نیست.

OWASP توصیه می‌کند اندازه پیام محدود شود و در راهنمای عمومی خود 64KB را به‌عنوان یک نقطه شروع رایج برای بسیاری از کاربردها ذکر می‌کند؛ اما مقدار واقعی باید براساس نیاز برنامه انتخاب شود.

هنگام عبور داده Binary نیز علاوه بر اندازه باید نوع واقعی فایل بررسی شود. اعتماد صرف به MIME Type یا نام فایل مناسب نیست و در کاربردهای آپلود باید Content واقعی و در صورت لزوم Magic Number بررسی شود.

Backpressure چیست و چه ارتباطی با امنیت دارد؟

Backpressure زمانی مطرح می‌شود که تولید داده سریع‌تر از ظرفیت پردازش یا ارسال آن باشد.

فرض کنید کلاینت با سرعت بسیار زیاد پیام ارسال می‌کند ولی Backend هر پیام را با عملیات پرهزینه‌ای پردازش می‌کند.

Queue به تدریج بزرگ‌تر می‌شود.

در نتیجه:

Memory افزایش پیدا می‌کند.

Latency بالا می‌رود.

Event Loop یا Workerها درگیر می‌شوند.

سرویس برای کاربران عادی کند می‌شود.

این مسئله می‌تواند از یک مشکل Performance به یک بردار DoS تبدیل شود.

OWASP به کنترل Backpressure در پیاده‌سازی WebSocket اشاره می‌کند، زیرا بعضی Libraryها Flow Control کافی را به‌صورت پیش‌فرض اعمال نمی‌کنند.

Idle Timeout و Heartbeat

Connectionهای مرده یا رهاشده نباید برای همیشه باز بمانند.

فرض کنید اینترنت کاربر قطع می‌شود، موبایل او شبکه را عوض می‌کند یا Client بدون Close Handshake صحیح از بین می‌رود.

سرور باید بتواند این Connectionها را تشخیص دهد.

برای این کار معمولاً از:

Ping

Pong

Heartbeat

Idle Timeout

استفاده می‌شود.

اگر Client در مدت مشخصی پاسخ ندهد، Connection بسته می‌شود.

این کار هم منابع سرور را آزاد می‌کند و هم مدیریت اتصال‌های غیرطبیعی را آسان‌تر می‌کند.

Timeout بسیار کوتاه می‌تواند کاربران شبکه‌های ضعیف را دچار مشکل کند و Timeout بسیار بلند ممکن است Resourceهای بی‌استفاده را برای مدت طولانی نگه دارد. بنابراین مقدار آن باید با الگوی واقعی سرویس تنظیم شود.

اگر WebSocket به Cookie Authentication وابسته است، تنظیم Cookie اهمیت زیادی دارد.

ویژگی‌های معمول Cookie امنیتی شامل:

Secure

HttpOnly

SameSite

هستند.

Secure باعث می‌شود Cookie فقط روی ارتباط امن ارسال شود.

HttpOnly دسترسی مستقیم JavaScript به Cookie را محدود می‌کند و در برابر برخی سناریوهای سرقت Cookie از طریق XSS یک لایه دفاعی ایجاد می‌کند.

SameSite رفتار ارسال Cookie در Contextهای Cross-Site را محدود می‌کند.

OWASP استفاده از SameSite=Lax یا SameSite=Strict را در بسیاری از سناریوها به‌عنوان بخشی از دفاع در عمق توصیه می‌کند. با این حال SameSite نباید در تمام معماری‌ها جایگزین کنترل اصلی CSRF یا Origin Validation شود.

به‌خصوص مفهوم Same-Site و Same-Origin یکسان نیست.

برای نمونه دو Subdomain می‌توانند از نظر Site به یکدیگر نزدیک باشند ولی Origin متفاوتی داشته باشند.

اگر یکی از Subdomainها به‌طور کامل تحت کنترل سازمان نباشد، اعتماد گسترده به تمام Subdomainها ممکن است سطح حمله را افزایش دهد.

آیا برای WebSocket به CSRF Token نیاز داریم؟

پاسخ وابسته به معماری Authentication است.

اگر WebSocket با Cookie احراز هویت می‌شود، کنترل Origin یکی از دفاع‌های اصلی در برابر CSWSH است.

در سیستم‌های حساس می‌توان علاوه بر Origin Validation از Anti-CSRF Token یا یک Ticket یک‌بارمصرف/کوتاه‌عمر برای Handshake نیز استفاده کرد.

هدف این است که صرف وجود Session Cookie برای ایجاد Connection حساس کافی نباشد.

OWASP در کنار Origin Validation، استفاده از CSRF Token را در معماری‌هایی که چنین مکانیسمی دارند به‌عنوان دفاع اضافه مطرح می‌کند.

با این حال Token باید:

به Session مناسب وابسته باشد؛

به شکل امن ایجاد شود؛

قابل حدس نباشد؛

در Log افشا نشود؛

و Lifecycle مناسبی داشته باشد. Authentication و Authorization در WebSocket

Authentication Token در Query String؛ چرا باید محتاط بود؟

یکی از راهکارهای ساده برای اتصال WebSocket این است:

wss://example.com/socket?access_token=SECRET

از نظر فنی این روش در بعضی معماری‌ها کار می‌کند، اما از دید امنیتی مشکل مهمی دارد:

URLها معمولاً بیشتر از Body یا Frame لاگ می‌شوند.

ممکن است URL در:

Reverse Proxy Log

Load Balancer

APM

Error Tracking

Analytics

Debug Log

یا سیستم مانیتورینگ ثبت شود.

در نتیجه Token حساس ممکن است در محیطی ذخیره شود که افراد یا سرویس‌های بیشتری به آن دسترسی دارند.

در صورت اجبار به چنین الگویی، Token بهتر است بسیار کوتاه‌عمر و ترجیحاً یک‌بارمصرف باشد و زیرساخت Logging نیز آن را Redact کند.

مدیریت Logout و Revocation

Logout نباید فقط Cookie مرورگر را حذف کند.

فرض کنید کاربر سه WebSocket فعال روی سه Tab دارد.

اگر Logout انجام شود ولی Connectionها باز بمانند، Backend ممکن است همچنان پیام‌ها را معتبر بداند.

بنابراین Logout امن باید در صورت نیاز شامل این مراحل باشد:

Invalid کردن Session

Invalid کردن Token یا Refresh State

شناسایی WebSocketهای مرتبط

بستن Connectionهای فعال

پاک‌سازی State مربوط به User در Connection Manager

همین مسئله هنگام تغییر Password، مسدود شدن حساب یا حذف Permission حساس نیز مطرح است.

اگر Role کاربر از Admin به User تغییر کرد، Socket قدیمی نباید ساعت‌ها Permission قبلی را Cache کند.

امنیت Subprotocol در WebSocket

WebSocket از Sec-WebSocket-Protocol برای مذاکره درباره Subprotocol پشتیبانی می‌کند.

برای مثال ممکن است Client اعلام کند از یک Protocol مشخص پشتیبانی می‌کند و Server یکی از Protocolهای مجاز را انتخاب کند.

اگر برنامه چند Subprotocol دارد، Server نباید مقدار دلخواه را بدون Validation قبول کند.

هر Subprotocol ممکن است:

Schema متفاوت

قوانین Authentication متفاوت

Commandهای متفاوت

و سطح دسترسی متفاوت

داشته باشد.

بنابراین انتخاب Subprotocol نیز بخشی از Boundary امنیتی است.

تنها Protocolهایی که Server واقعاً می‌شناسد و اجازه استفاده از آن‌ها را دارد باید پذیرفته شوند.

Compression و permessage-deflate

WebSocket می‌تواند از Extensionهایی مانند permessage-deflate برای Compression پیام استفاده کند.

Compression می‌تواند Bandwidth را کاهش دهد، اما در بعضی سناریوهایی که Secret و داده کنترل‌شده توسط مهاجم در محتوای فشرده‌شده ترکیب می‌شوند، تحلیل اندازه خروجی فشرده‌شده می‌تواند به Side-Channelهای مشابه خانواده حملات Compression منجر شود.

OWASP توصیه می‌کند permessage-deflate در صورتی که نیاز مشخصی به آن وجود ندارد غیرفعال شود و اگر فعال است، ریسک امنیتی آن در Threat Model بررسی شود.

به عبارت دیگر:

فعال کردن Feature صرفاً به دلیل وجود آن در Library تصمیم مناسبی نیست.

Performance Benefit باید در برابر Complexity و Security Risk ارزیابی شود.

Masking در WebSocket چیست؟

در RFC 6455 فریم‌هایی که Client برای Server می‌فرستد باید Mask شوند.

این Masking با Encryption متفاوت است.

هدف اصلی Masking جلوگیری از برخی حملات علیه Intermediaryهای شبکه، به‌خصوص Proxyهای ناسازگار، بوده است.

RFC مشخص می‌کند Client باید برای هر Frame یک Masking Key جدید و غیرقابل پیش‌بینی انتخاب کند و Server در صورت دریافت Frame بدون Mask از Client باید Connection را به‌عنوان Protocol Error مدیریت کند.

اما نکته بسیار مهم:

WebSocket Masking جای TLS را نمی‌گیرد.

Masking برای محرمانگی طراحی نشده و نباید آن را نوعی Encryption در نظر گرفت.

برای محافظت از داده در مسیر باید از WSS/TLS استفاده شود.

Reverse Proxy و WebSocket

در بسیاری از معماری‌ها WebSocket Server مستقیماً در معرض اینترنت نیست.

مسیر ممکن است چنین باشد:

Client
↓
CDN
↓
WAF
↓
Reverse Proxy
↓
Application Server

در این معماری باید تمام اجزا WebSocket را به‌درستی پشتیبانی کنند.

برای HTTP/1.1، Headerهای مربوط به Upgrade اهمیت دارند.

NGINX توضیح می‌دهد که Upgrade و Connection از نوع Hop-by-Hop هستند و برای WebSocket Proxying باید تنظیم Proxy به شکلی باشد که Upgrade به Backend منتقل شود.

یک تنظیم ناقص ممکن است دو نوع مشکل ایجاد کند:

Connection اصلاً کار نکند؛

یا بخشی از کنترل‌های امنیتی در لایه‌ای انجام شود که بعد از Upgrade دیگر ترافیک را بررسی نمی‌کند.

بنابراین در تست امنیت WebSocket باید معماری کامل مسیر شبکه بررسی شود، نه فقط Application Code.

WAF و WebSocket

وجود WAF به معنی بررسی کامل WebSocket نیست.

بعضی WAFها تنها HTTP Handshake را تحلیل می‌کنند و بعد از 101 Switching Protocols دید محدودی نسبت به Frameهای داخل Connection دارند.

برخی محصولات قابلیت WebSocket Inspection دارند، اما نحوه عملکرد آن‌ها متفاوت است.

در نتیجه هنگام استفاده از WAF باید مشخص شود:

آیا فقط Handshake بررسی می‌شود؟

آیا Messageهای Text بررسی می‌شوند؟

آیا Binary Frameها بررسی می‌شوند؟

آیا محدودیت Size وجود دارد؟

آیا Rate Limiting پیام‌ها پشتیبانی می‌شود؟

آیا TLS در نقطه‌ای Terminate می‌شود که WAF بتواند ترافیک را مشاهده کند؟

حتی با وجود WAF، Validation و Authorization سمت Application نباید حذف شود.

WAF یک Defense-in-Depth Control است، نه جایگزین Secure Coding.

Logging در WebSocket

یکی از مشکلات امنیت WebSocket این است که Logging سنتی HTTP ممکن است تصویر ناقصی ارائه دهد.

ممکن است Access Log فقط این را نشان دهد:

GET /socket → 101

اما پس از آن هزاران Action از همان Connection انجام شده باشد.

برای Incident Response این اطلاعات کافی نیست.

سیستم Logging بهتر است رویدادهای مهمی مانند موارد زیر را ثبت کند:

زمان Connection

شناسه User

Session یا Connection ID غیرحساس

Origin

IP و اطلاعات Proxy معتبر

Subprotocol

نتیجه Authentication

شکست Authorization

Validation Error

Rate Limit Event

Oversized Message

Protocol Error

زمان Disconnect

Close Code

مدت Connection

البته نباید تمام Payloadها بدون فکر ذخیره شوند.

ثبت کامل پیام ممکن است اطلاعات حساس مانند:

Token

Password

اطلاعات شخصی

پیام خصوصی

کلید API

داده مالی

را وارد Log کند.

OWASP تأکید می‌کند اطلاعات حساس مانند Authentication Token، Session ID یا محتوای خصوصی نباید بدون ضرورت در Logging ذخیره شوند.

مانیتورینگ رفتار غیرعادی

Logging زمانی ارزش امنیتی واقعی پیدا می‌کند که بتوان از آن برای Detection استفاده کرد.

برای مثال رفتارهای زیر ممکن است نیازمند Alert باشند:

یک User با تعداد بسیار زیادی Connection هم‌زمان

یک IP با نرخ Handshake غیرعادی

تعداد بالای Origin ردشده

افزایش ناگهانی پیام Invalid

تعداد زیاد Authorization Failure

پیام‌های بسیار بزرگ

اتصال‌هایی با مدت بسیار طولانی غیرعادی

Reconnectهای سریع و متوالی

تعداد زیاد Protocol Error

افزایش غیرعادی مصرف Memory مرتبط با WebSocket

این داده‌ها می‌توانند وارد SIEM یا Monitoring Platform شوند.

هدف این نیست که هر خطا Attack تلقی شود؛ بلکه باید Baseline رفتار عادی مشخص شود و انحراف‌های معنادار قابل بررسی باشند.

امنیت WebSocket در معماری Microservice

در معماری Microservice معمولاً WebSocket Gateway در لبه سیستم قرار دارد و پیام‌ها را به سرویس‌های داخلی منتقل می‌کند.

در این معماری یک خطر رایج این است که Authentication در Gateway انجام شود و سرویس داخلی تمام اطلاعات دریافتی از Gateway را بدون کنترل بپذیرد.

برای کاهش ریسک، Trust Boundaryها باید مشخص باشند.

Gateway باید هویت کاربر را به شکل قابل اعتماد منتقل کند.

سرویس‌های داخلی باید Authorization مربوط به Resourceهای حساس را حفظ کنند.

شناسه User نباید از فیلدی گرفته شود که Client خودش کنترل می‌کند.

برای مثال:

{
  "user_id": 100,
  "action": "get_balance"
}

اگر user_id از Client دریافت شود و Backend به آن اعتماد کند، خطر جدی وجود دارد.

هویت باید از Context احراز هویت‌شده Connection استخراج شود، نه از مقدار ادعایی داخل Message.

امنیت WebSocket و Business Logic

بسیاری از آسیب‌پذیری‌های WebSocket نه در خود پروتکل، بلکه در منطق برنامه قرار دارند.

فرض کنید پیام زیر برای خرید محصول استفاده می‌شود:

{
  "action": "purchase",
  "product_id": 52,
  "price": 1
}

اگر Server قیمت را از پیام Client بپذیرد، مشکل WebSocket نیست؛ مشکل Trust Boundary و Business Logic است.

Server باید اطلاعات حساس را خودش از منبع معتبر استخراج کند.

در مثال بالا:

Client فقط product_id و اطلاعات لازم را ارسال می‌کند.

Server قیمت واقعی را از Database دریافت می‌کند.

مجوز خرید بررسی می‌شود.

موجودی بررسی می‌شود.

عملیات با کنترل Atomicity انجام می‌شود.

نتیجه معتبر برای Client ارسال می‌شود.

WebSocket همان اصول Secure Design سایر APIها را نیاز دارد.

پیام‌های Binary چگونه امن شوند؟

WebSocket علاوه بر Text Frame می‌تواند داده Binary نیز منتقل کند.

اگر Binary Message برای آپلود تصویر، فایل، صوت یا داده اختصاصی استفاده می‌شود، باید کنترل‌های مربوط به File Security اعمال شود.

فقط به File Extension اعتماد نکنید.

فقط به MIME Type اعلام‌شده توسط Client اعتماد نکنید.

اندازه فایل را محدود کنید.

در صورت مرتبط بودن Magic Number را بررسی کنید.

فایل‌های پرخطر را خارج از Web Root نگه دارید.

در صورت نیاز Malware Scanning انجام دهید.

Parserهای Binary را به‌روز نگه دارید.

فرمت‌های پیچیده ممکن است آسیب‌پذیری Parser داشته باشند.

اگر از Protobuf، MessagePack یا Serializationهای دیگر استفاده می‌شود، Schema و Type Validation همچنان لازم است.

Dependency Security

امنیت WebSocket فقط به کدی که تیم توسعه نوشته محدود نیست.

Libraryهای WebSocket، Frameworkها، Reverse Proxyها و Gatewayها نیز ممکن است دارای Vulnerability باشند.

OWASP به سابقه آسیب‌پذیری‌های امنیتی در کتابخانه‌ها و Frameworkهای مرتبط با WebSocket اشاره می‌کند و توصیه می‌کند Dependencyها به‌روز نگه داشته شوند و Advisoryهای امنیتی بررسی شوند.

یک فرایند مناسب می‌تواند شامل موارد زیر باشد:

Software Composition Analysis

Dependency Scanning

بررسی CVE

Pin کردن نسخه‌ها

به‌روزرسانی منظم

تست Regression

و حذف Libraryهای بدون نگهداری.

در محیط Production نباید صرفاً به این دلیل که سرویس فعلاً کار می‌کند، نسخه‌های قدیمی برای سال‌ها بدون Patch باقی بمانند.

تست امنیت WebSocket باید شامل چه مواردی باشد؟

تست WebSocket باید در کنار سایر بخش‌های تست امنیت برنامه انجام شود، اما سناریوهای اختصاصی خودش را دارد.

یک چک‌لیست دفاعی مناسب شامل این موارد است:

  1. بررسی استفاده از wss:// در Production.
  2. بررسی Certificate و تنظیم TLS.
  3. بررسی Origin Validation با Allowlist دقیق.
  4. بررسی رفتار Server هنگام Origin نامعتبر یا فقدان Origin.
  5. بررسی Authentication در Handshake یا Protocol برنامه.
  6. بررسی پایان دسترسی پس از Logout.
  7. بررسی Session Expiration هنگام باز بودن Connection.
  8. بررسی Revocation Token یا Session.
  9. بررسی Authorization برای هر Action حساس.
  10. بررسی IDOR و دسترسی به Object متعلق به کاربر دیگر.
  11. بررسی Schema Validation پیام‌ها.
  12. بررسی محدودیت طول Stringها و Arrayها.
  13. بررسی Maximum Message Size.
  14. بررسی Rate Limit در سطح Connection و Message.
  15. بررسی تعداد Connection مجاز برای هر User.
  16. بررسی Idle Timeout و Heartbeat.
  17. بررسی Replay Protection برای عملیات حساس.
  18. بررسی XSS در پیام‌های نمایش‌داده‌شده.
  19. بررسی SQL Injection، Command Injection و سایر Injectionها در Backend.
  20. بررسی Binary Payload و File Validation.
  21. بررسی Backpressure و Queue Size.
  22. بررسی رفتار Server در برابر Frameهای نامعتبر.
  23. بررسی Subprotocolهای قابل قبول.
  24. بررسی نیاز واقعی به Compression.
  25. بررسی WebSocket Inspection در WAF و Proxy.
  26. بررسی اینکه اطلاعات حساس وارد Access Log نمی‌شوند.
  27. بررسی مانیتورینگ Security Eventها.
  28. بررسی Dependencyهای WebSocket و CVEهای مرتبط.
  29. بررسی محدودیت Resource در Load Balancer و Reverse Proxy.
  30. بررسی Fail-Safe بودن سیستم هنگام بروز Exception.

این تست‌ها باید در محیط مجاز و کنترل‌شده انجام شوند و هدف آن‌ها کشف نقاط ضعف پیش از سوءاستفاده واقعی باشد.

اشتباهات رایج در امنیت WebSocket

اشتباه اول: WSS یعنی WebSocket کاملاً امن است

WSS فقط کانال انتقال را با TLS محافظت می‌کند.

Authentication، Authorization، Validation و Business Logic همچنان باید جداگانه ایمن شوند.

اشتباه دوم: Origin را با Authentication اشتباه گرفتن

Origin می‌تواند از حملات Cross-Origin مرورگری جلوگیری کند، اما هویت User را اثبات نمی‌کند.

کلاینت‌های غیرمرورگری می‌توانند Origin دلخواه ایجاد کنند.

اشتباه سوم: بررسی دسترسی فقط هنگام اتصال

اینکه کاربر هنگام Handshake مجاز بوده، دلیل نمی‌شود تمام Actionهای بعدی مجاز باشند.

Authorization باید در سطح عملیات انجام شود.

اشتباه چهارم: باز ماندن اتصال پس از Logout

WebSocket باید با Session Lifecycle هماهنگ باشد.

Logout، Session Revocation یا تغییر Permission ممکن است نیازمند قطع Connection باشد.

اشتباه پنجم: نبود محدودیت اندازه پیام

یک Message بزرگ می‌تواند Memory و Parser را تحت فشار قرار دهد.

Maximum Payload باید مشخص باشد.

اشتباه ششم: Rate Limiting فقط روی HTTP

Message Flooding بعد از Upgrade اتفاق می‌افتد.

Rate Limiting در سطح WebSocket Message نیز لازم است.

اشتباه هفتم: اعتماد به داده دریافتی از WebSocket

WebSocket یک کانال امنِ ذاتی برای داده قابل اعتماد نیست.

پیام باید مانند هر Input دیگری Validation شود.

اشتباه هشتم: ذخیره Token در Log

استفاده از Token در URL یا Logging کامل Handshake می‌تواند Secret را در Logها افشا کند.

اشتباه نهم: اعتماد کامل به WAF

ممکن است WAF فقط Handshake را ببیند و Frameهای بعدی را تحلیل نکند.

کنترل امنیتی باید در Application نیز وجود داشته باشد.

اشتباه دهم: نداشتن Monitoring اختصاصی

اگر فقط Access Log مربوط به Upgrade ثبت شود، بسیاری از رخدادهای داخل Connection دیده نمی‌شوند. نمونه معماری امن WebSocket

نمونه معماری امن WebSocket

یک معماری منطقی می‌تواند چنین جریان امنیتی داشته باشد:

Client
   ↓
HTTPS / WSS
   ↓
CDN / DDoS Protection
   ↓
WAF
   ↓
Reverse Proxy
   ↓
WebSocket Gateway
   │
   ├── Origin Validation
   ├── Authentication
   ├── Session Validation
   ├── Connection Limits
   ├── Message Size Limits
   ├── Rate Limiting
   └── Schema Validation
   ↓
Authorization Layer
   ↓
Business Logic
   ↓
Database / Internal Services

در این مدل هیچ لایه‌ای به تنهایی مسئول تمام امنیت نیست.

حتی اگر WAF از کار بیفتد، Backend همچنان Message Validation دارد.

حتی اگر کاربر Authentication معتبر داشته باشد، Authorization هر Action بررسی می‌شود.

حتی اگر مهاجم بتواند تعداد زیادی پیام تولید کند، Rate Limit و Backpressure از Backend محافظت می‌کنند.

این رویکرد همان Defense in Depth است.

تنظیم Reverse Proxy برای WebSocket چه اهمیتی دارد؟

Reverse Proxy باید Upgrade را به شکل صحیح مدیریت کند.

در HTTP/1.1، Headerهای Upgrade و Connection به شکل عادی End-to-End نیستند و Proxy باید رفتار مورد نیاز WebSocket را به‌درستی پیاده کند. مستندات رسمی NGINX نیز این موضوع را توضیح می‌دهد.

علاوه بر این موارد عملیاتی باید بررسی شوند:

Proxy Read Timeout

Maximum Connection

Idle Timeout

Buffering Behavior

TLS Termination

Client IP Forwarding

Rate Limiting

و Logging.

یک Timeout اشتباه ممکن است Connectionهای سالم را قطع کند.

در مقابل Timeout بسیار بالا و بدون Heartbeat می‌تواند Connectionهای مرده را برای مدت طولانی نگه دارد.

امنیت IP و Headerهای Forwarded

در معماری پشت Reverse Proxy، Application معمولاً IP مستقیم کاربر را نمی‌بیند و ممکن است از Headerهایی مانند X-Forwarded-For استفاده کند.

اما نباید هر Header ارسال‌شده توسط Client را معتبر دانست.

Proxy مورد اعتماد باید Headerهای Forwarded را پاک‌سازی یا بازنویسی کند و Application فقط Proxyهای مورد اعتماد را به‌عنوان منبع این اطلاعات بپذیرد.

در غیر این صورت مهاجم ممکن است IP جعلی به برنامه ارائه کند و کنترل‌هایی مانند:

Rate Limit

Audit Log

Geo Restriction

Abuse Detection

را تحت تأثیر قرار دهد.

این موضوع مخصوص WebSocket نیست، اما در سرویس‌های طولانی‌مدت WebSocket اهمیت بیشتری پیدا می‌کند.

Close Code و مدیریت خطا

WebSocket برای بستن Connection دارای Close Frame و Close Code است.

برنامه باید خطاها را به شکل کنترل‌شده مدیریت کند.

در صورت:

Session Expired

Unauthorized Action

Invalid Message

Oversized Message

Protocol Violation

می‌توان Connection یا Message را براساس سیاست سیستم رد کرد.

اما Error Message نباید اطلاعات داخلی غیرضروری افشا کند.

برای مثال نمایش مواردی مانند:

Database Error

Stack Trace

Internal File Path

Secret Configuration

یا جزئیات داخلی Authorization

برای Client مناسب نیست.

در Production بهتر است Client یک Error عمومی دریافت کند و جزئیات لازم برای Debugging در Log امن Server ثبت شود.

Fail Open یا Fail Closed در WebSocket

کنترل‌های امنیتی باید رفتار مشخصی هنگام خطا داشته باشند.

فرض کنید سرویس Authorization داخلی از دسترس خارج شود.

آیا Gateway باید پیام را قبول کند یا رد کند؟

برای Actionهای حساس، رفتار Fail Open می‌تواند خطرناک باشد.

در بسیاری از سناریوهای امنیتی بهتر است اگر سیستم نتواند مجوز را با اطمینان تأیید کند، عملیات حساس انجام نشود.

همین اصل درباره Origin Validation، Token Validation و Schema Validation نیز مطرح است.

Undefined State نباید به طور ناخواسته معادل Allowed State شود.

امنیت ارتباط داخلی WebSocket

گاهی WebSocket فقط بین Browser و Gateway استفاده نمی‌شود و سرویس‌های داخلی نیز از WebSocket استفاده می‌کنند.

اینکه یک Endpoint روی Private Network قرار دارد، به تنهایی Authentication را غیرضروری نمی‌کند.

در محیط‌های Zero Trust یا Microservice بهتر است هویت Serviceها مشخص باشد و Communication حساس با کنترل مناسب محافظت شود.

بسته به معماری می‌توان از:

TLS

mTLS

Service Identity

Network Policy

Firewall

و Application-Level Authorization

استفاده کرد.

قرار داشتن در VLAN یا VPC نباید تنها معیار اعتماد باشد.

WebSocket در سایت‌های وردپرسی

هسته WordPress معمولاً برای عملکرد استاندارد خود وابستگی مستقیم گسترده‌ای به WebSocket ندارد، اما Pluginها، سرویس‌های Push، Chat، Notification، داشبوردهای Real-Time و Integrationهای خارجی می‌توانند از WebSocket استفاده کنند.

مدیر سایت وردپرسی باید مشخص کند WebSocket توسط چه مؤلفه‌ای ایجاد شده است:

Plugin؟

سرویس SaaS؟

Node.js Backend؟

Reverse Proxy؟

Cloudflare یا CDN؟

سرویس Chat؟

اگر WebSocket Endpoint خارج از PHP/WordPress اجرا می‌شود، نصب افزونه امنیتی وردپرس الزاماً تمام ترافیک آن را کنترل نمی‌کند.

برای مثال ممکن است WordPress پشت Apache باشد ولی WebSocket روی Node.js و پورت جداگانه اجرا شود.

در چنین حالتی باید امنیت Node.js Service، Reverse Proxy و مسیر WebSocket نیز جداگانه بررسی شود.

WebSocket در فروشگاه‌های اینترنتی

در WooCommerce یا سایر فروشگاه‌ها ممکن است WebSocket برای:

اعلان سفارش

داشبورد مدیر

Chat پشتیبانی

موجودی لحظه‌ای

قیمت‌گذاری Real-Time

یا Integrationهای پرداخت

استفاده شود.

هرچه داده حساس‌تر باشد، Authorization اهمیت بیشتری پیدا می‌کند.

کانالی که وضعیت سفارش را به Client می‌فرستد نباید صرفاً با تغییر order_id اطلاعات سفارش مشتری دیگر را نمایش دهد.

همچنین Notification Channel نباید اطلاعات شخصی بیش از نیاز ارسال کند.

اصل Data Minimization در WebSocket نیز کاربرد دارد:

فقط داده‌ای را برای Client بفرستید که واقعاً به آن نیاز دارد.

تفاوت WebSocket امن و WebSocket ناامن

بخشپیاده‌سازی ناامنپیاده‌سازی امن
Transportws://wss://
Originپذیرش همه OriginهاAllowlist دقیق
Authenticationاعتماد به اتصالAuthentication معتبر
Sessionبدون بررسی مجددهماهنگ با Expiration و Logout
Authorizationفقط زمان اتصالبررسی هر Action حساس
Inputاعتماد به MessageSchema Validation
Message Sizeنامحدودمحدودیت متناسب
Rate Limitنداردper-user / per-IP / per-action
Idle Connectionباز برای همیشهHeartbeat و Timeout
Tokenقابل مشاهده در LogToken محافظت‌شده و Redaction
Loggingفقط HTTP UpgradeEventهای WebSocket
WAFاعتماد کاملDefense in Depth
Compressionهمیشه فعالفقط در صورت نیاز و ارزیابی
Dependencyنسخه قدیمیPatch و Monitoring مداوم

چک‌لیست نهایی امنیت WebSocket

قبل از انتشار یک WebSocket Endpoint در محیط Production باید حداقل پاسخ روشنی برای این پرسش‌ها وجود داشته باشد:

آیا تمام ارتباطات حساس با WSS انجام می‌شوند؟

آیا TLS به شکل امن تنظیم شده است؟

چه Originهایی اجازه اتصال دارند؟

اگر Origin نامعتبر باشد چه اتفاقی می‌افتد؟

کاربر چگونه Authentication می‌شود؟

Session چه زمانی منقضی می‌شود؟

پس از Logout چه اتفاقی برای Socket می‌افتد؟

Permission هر Message در کجا بررسی می‌شود؟

آیا کاربر می‌تواند ID مربوط به Resource کاربر دیگری را ارسال کند؟

Schema هر Message چیست؟

حداکثر Payload چقدر است؟

Rate Limit چگونه اعمال می‌شود؟

حداکثر Connection هر User چقدر است؟

Heartbeat چگونه انجام می‌شود؟

Idle Timeout چقدر است؟

آیا Messageهای حساس در برابر Replay محافظت می‌شوند؟

آیا پیام‌های خروجی در Client به شکل امن Render می‌شوند؟

آیا Queryهای Backend Parameterized هستند؟

آیا Binary Payload بررسی می‌شود؟

آیا Compression واقعاً لازم است؟

آیا Proxy و Load Balancer WebSocket را درست مدیریت می‌کنند؟

آیا WAF بعد از Upgrade نیز ترافیک را مشاهده می‌کند؟

چه چیزهایی Log می‌شوند؟

چه اطلاعاتی نباید Log شوند؟

چه Eventهایی Alert ایجاد می‌کنند؟

آیا Dependencyهای WebSocket به‌روز هستند؟

اگر پاسخ هرکدام نامشخص باشد، همان بخش می‌تواند نقطه شروع Audit باشد.

سؤالات متداول درباره امنیت WebSocket

آیا WebSocket از HTTP امن‌تر است؟

خیر. نمی‌توان WebSocket و HTTP را به‌طور کلی از نظر امنیت رتبه‌بندی کرد. امنیت به نحوه پیاده‌سازی بستگی دارد. WebSocket روی WSS می‌تواند ارتباط رمزنگاری‌شده داشته باشد، اما همچنان به Authentication، Authorization، Input Validation و سایر کنترل‌های امنیت برنامه نیاز دارد.

آیا استفاده از wss:// برای امنیت WebSocket کافی است؟

خیر. WSS داده در حال انتقال را با TLS محافظت می‌کند، اما مشکلاتی مانند Broken Access Control، CSWSH، XSS، SQL Injection، Replay یا ضعف Session Management را به تنهایی رفع نمی‌کند.

مهم‌ترین حمله مخصوص WebSocket چیست؟

Cross-Site WebSocket Hijacking یا CSWSH یکی از شناخته‌شده‌ترین تهدیدهای مخصوص WebSocket در برنامه‌های مرورگری است. این مشکل معمولاً زمانی اهمیت پیدا می‌کند که WebSocket با Cookie احراز هویت شود و Server Origin را به‌درستی بررسی نکند.

آیا CORS از WebSocket محافظت می‌کند؟

نباید به CORS به‌عنوان کنترل اصلی WebSocket تکیه کرد. Server باید Origin مربوط به Handshake WebSocket را خودش بررسی کند و سیاست مستقلی برای Originهای مجاز داشته باشد.

آیا Origin Header قابل اعتماد است؟

در Context مرورگر، Origin یک سیگنال مهم برای جلوگیری از اتصال Cross-Origin ناخواسته است. اما کلاینت‌های غیرمرورگری می‌توانند Origin جعلی ارسال کنند. بنابراین Origin جای Authentication را نمی‌گیرد.

آیا WebSocket در برابر CSRF آسیب‌پذیر است؟

مدل حمله دقیقاً مشابه درخواست HTTP سنتی نیست، اما WebSocketهایی که به Cookie متکی هستند و Handshake را بدون کنترل مناسب می‌پذیرند می‌توانند در معرض Cross-Site WebSocket Hijacking قرار بگیرند؛ حمله‌ای که از نظر مفهومی با CSRF ارتباط نزدیکی دارد.

هر دو مدل می‌توانند به شکل امن یا ناامن پیاده‌سازی شوند. انتخاب به معماری بستگی دارد. Cookie نیازمند توجه ویژه به Origin، SameSite و CSWSH است. Token نیز باید به شکلی منتقل شود که در URL، Log یا سایر نقاط ناخواسته افشا نشود.

آیا Token را می‌توان داخل URL WebSocket قرار داد؟

از نظر فنی در برخی معماری‌ها امکان‌پذیر است، اما Token ممکن است وارد Access Log، Proxy Log یا Monitoring شود. در صورت استفاده، بهتر است Token کوتاه‌عمر یا یک‌بارمصرف باشد و Logها Secret را Redact کنند.

WebSocket چگونه در برابر DoS محافظت می‌شود؟

با ترکیبی از Connection Limit، Rate Limiting، Maximum Message Size، Idle Timeout، Heartbeat، Backpressure، محدودیت Queue و Monitoring منابع می‌توان ریسک DoS را کاهش داد.

آیا WAF می‌تواند WebSocket را بررسی کند؟

بعضی WAFها قابلیت WebSocket Inspection دارند و برخی فقط Handshake اولیه را تحلیل می‌کنند. قابلیت محصول و تنظیم واقعی آن باید بررسی شود. حتی با WAF، Validation و Authorization سمت برنامه ضروری است.

آیا Messageهای دریافتی WebSocket قابل اعتماد هستند؟

خیر. تمام Messageها باید Untrusted Input در نظر گرفته شوند و براساس نوع، اندازه، Schema، Permission و Business Logic اعتبارسنجی شوند.

بعد از Logout باید WebSocket بسته شود؟

برای Connectionهای احراز هویت‌شده، در بسیاری از معماری‌ها بله. Backend باید بتواند Session یا Token را Revocation کند و اتصال‌هایی را که دیگر مجاز نیستند ببندد.

آیا WebSocket به Rate Limit نیاز دارد؟

بله. Rate Limiting Handshake به تنهایی کافی نیست. تعداد Messageها و Actionهای پرهزینه نیز باید محدود شوند تا Message Flooding باعث مصرف بیش از حد منابع نشود.

آیا WebSocket Masking همان Encryption است؟

خیر. Masking تعریف‌شده در RFC 6455 برای محافظت از برخی Intermediaryهای شبکه طراحی شده و محرمانگی ایجاد نمی‌کند. Encryption واقعی مسیر ارتباط با TLS و WSS انجام می‌شود.

امنیت WebSocket را از کجا شروع کنیم؟

بهترین نقطه شروع، ترسیم مسیر کامل Connection از Client تا Backend است. سپس WSS، Origin Validation، Authentication، Session Management، Message-Level Authorization، Input Validation، Rate Limiting، Payload Limit، Logging و Dependency Security را به ترتیب بررسی کنید.

جمع‌بندی

امنیت WebSocket فقط به انتخاب wss:// محدود نمی‌شود. WebSocket یک کانال ارتباطی دائمی و دوطرفه ایجاد می‌کند و همین ویژگی باعث می‌شود مدل امنیتی آن نسبت به Request/Responseهای سنتی HTTP نیازمند کنترل‌های بیشتری باشد.

اولین لایه، استفاده از WSS و TLS امن است تا داده در مسیر در برابر شنود و تغییر محافظت شود. پس از آن، Handshake باید با Origin Validation، Authentication مناسب و در صورت نیاز کنترل‌های تکمیلی CSRF محافظت شود.

با برقراری Connection، وظیفه امنیت تمام نمی‌شود. Session باید در طول عمر اتصال معتبر باقی بماند و Logout، Expiration یا Revocation باید روی WebSocket نیز اثر بگذارد.

هر Message باید مانند یک درخواست مستقل از نظر Authorization بررسی شود. داده ورودی نیز باید غیرقابل‌اعتماد فرض شود و با Schema Validation، محدودیت طول و Type Validation کنترل شود.

برای جلوگیری از حملات Resource Exhaustion باید تعداد Connection، نرخ Message، اندازه Payload، Queue، Idle Connection و Backpressure مدیریت شوند.

در کنار این کنترل‌ها، Logging و Monitoring اختصاصی WebSocket اهمیت زیادی دارد، زیرا Logهای HTTP ممکن است فقط Handshake اولیه را نمایش دهند و هیچ اطلاعاتی از صدها یا هزاران پیام بعدی نداشته باشند.

در نهایت، WebSocket امن نتیجه یک تنظیم واحد نیست؛ بلکه حاصل مجموعه‌ای از کنترل‌های هماهنگ در TLS، Browser، Reverse Proxy، WAF، Authentication، Authorization، Session Management و Application Logic است.

اگر امنیت WebSocket از ابتدا در معماری طراحی شود، این فناوری می‌تواند برای سرویس‌های Real-Time، چت، داشبورد، سیستم‌های مالی و برنامه‌های تعاملی با سطح امنیت بسیار مناسبی استفاده شود. اما اگر اتصال دائمی به معنی «اعتماد دائمی» تلقی شود، همان ویژگی‌ای که WebSocket را سریع و کاربردی کرده است می‌تواند به یک سطح حمله مهم تبدیل شود.

مطالب مرتبط