آکادمی بای‌باگ مرجع آموزش‌های آنلاین
جهت درخواست مشاوره از طریق بخش پروفایل خود اقدام کنید

HTTP از دید یک توسعه‌دهنده و متخصص امنیت: معماری Request/Response، Headerها، Cookieها و نقاط حمله

avatar user image
علی رضا راخداپور
1405/06/05 13 دقیقه برای خواندن

HTTP چیست و چگونه کار می‌کند؟ در این مقاله معماری Request/Response، Headerها، Cookieها و مهم‌ترین نقاط حمله HTTP را از دید یک توسعه‌دهنده و متخصص امنیت بررسی می‌کنیم.

ByeBug article image

HTTP از دید یک توسعه‌دهنده و متخصص امنیت؛ معماری Request/Response، Headerها، Cookieها و نقاط حمله

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

برای یک توسعه‌دهنده، HTTP فقط مجموعه‌ای از متدهای GET و POST نیست. برای یک متخصص امنیت نیز HTTP صرفاً راهی برای انتقال اطلاعات محسوب نمی‌شود؛ بلکه سطح بزرگی از حملات وب در همین لایه شکل می‌گیرد. درک دقیق Request، Response، Headerها، Cookieها، Status Codeها و نحوه پردازش آن‌ها، یکی از پایه‌های مهم توسعه وب امن است.

در این مقاله HTTP را از دو زاویه بررسی می‌کنیم: ابتدا مانند یک توسعه‌دهنده یاد می‌گیریم که ارتباط مرورگر و سرور چگونه ساخته و پردازش می‌شود و سپس با نگاه امنیتی بررسی می‌کنیم که همین اجزا چگونه می‌توانند به نقطه‌ای برای سوءاستفاده تبدیل شوند.


فهرست مطالب


```

HTTP چیست؟

HTTP مخفف HyperText Transfer Protocol است و یکی از پروتکل‌های اصلی ارتباط در وب محسوب می‌شود. وظیفه HTTP تعریف نحوه ارسال درخواست از سمت Client و نحوه پاسخ‌گویی Server است.

وقتی وارد یک وب‌سایت می‌شوید، مرورگر شما در نقش Client قرار می‌گیرد و برای دریافت منابع موردنیاز مانند HTML، CSS، JavaScript، تصویر یا داده‌های API، درخواست‌هایی را به Server ارسال می‌کند. Server نیز پس از پردازش درخواست، یک Response برمی‌گرداند.

نکته مهم این است که HTTP خودش مسئول همه چیز نیست. DNS می‌تواند نام دامنه را به IP تبدیل کند، TCP یا QUIC مسئول انتقال داده در لایه‌های پایین‌تر هستند و TLS در حالت HTTPS وظیفه ایجاد ارتباط رمزنگاری‌شده را بر عهده دارد. HTTP بیشتر مشخص می‌کند که پیام وب چه ساختاری داشته باشد و Client و Server چگونه درباره منابع و عملیات با یکدیگر صحبت کنند.

یک مثال ساده

فرض کنید کاربر آدرس زیر را باز می‌کند:

https://example.com/products

مرورگر ابتدا باید مقصد را پیدا کند و سپس یک ارتباط مناسب با سرور برقرار کند. در ادامه یک درخواست HTTP برای مسیر /products ارسال می‌شود. سرور این درخواست را دریافت کرده، آن را پردازش می‌کند و در نهایت Response مناسب را برمی‌گرداند.

این Response ممکن است شامل HTML باشد، یا در یک Web API شامل JSON، یا حتی یک Status Code مانند 404 یا 500 باشد.

```
```

معماری ارتباط HTTP چگونه است؟

یکی از مهم‌ترین مفاهیمی که یک توسعه‌دهنده وب باید به‌خوبی درک کند، مدل Client → Request → Server → Response → Client است.

در ساده‌ترین حالت، Client یک درخواست ایجاد می‌کند. درخواست به Server می‌رسد، Server آن را پردازش می‌کند و نتیجه را در قالب Response ارسال می‌کند.

Client
```

|
| HTTP Request
v
Server
|
| HTTP Response
v
Client
```

اما در پروژه‌های واقعی، معماری معمولاً پیچیده‌تر است. ممکن است درخواست ابتدا به CDN، Reverse Proxy، Load Balancer یا Web Application Firewall برسد و سپس به Application Server منتقل شود.

Browser
```

|
v
DNS
|
v
CDN / Reverse Proxy
|
v
Load Balancer
|
v
Web Application
|
+------> Database
|
+------> Cache
|
+------> External API
```

این موضوع از دید امنیت اهمیت زیادی دارد؛ زیرا هر لایه ممکن است Headerها را تغییر دهد، درخواست را فیلتر کند، اطلاعاتی به آن اضافه کند یا حتی تصمیم بگیرد که درخواست اصلاً به Application نرسد.

HTTP Stateless است؛ یعنی چه؟

HTTP به‌صورت ذاتی یک پروتکل Stateless است. یعنی هر Request به‌طور مستقل از Request قبلی در نظر گرفته می‌شود و پروتکل HTTP به‌تنهایی حافظه‌ای از وضعیت Client نگه نمی‌دارد.

اما برنامه‌های وب معمولاً Stateful به نظر می‌رسند؛ برای مثال وقتی وارد حساب کاربری خود می‌شوید، در صفحات مختلف همچنان شناسایی می‌شوید.

این وضعیت معمولاً با مکانیزم‌هایی مانند Cookie، Session، Token و سایر روش‌های مدیریت هویت ایجاد می‌شود؛ موضوعی که در ادامه مقاله از نظر امنیتی بررسی خواهیم کرد.

```
```

Request و Response دقیقاً چه هستند؟

اگر بخواهیم HTTP را در ساده‌ترین شکل ممکن توضیح دهیم، باید دو مفهوم اصلی آن را بشناسیم: Request و Response.

HTTP Request

Request پیامی است که Client برای درخواست یک منبع یا انجام یک عملیات به Server ارسال می‌کند. این پیام می‌تواند مشخص کند که چه متدی استفاده شده، چه مسیری درخواست شده، چه Headerهایی وجود دارند و آیا داده‌ای در Body ارسال شده است یا خیر.

HTTP Response

Response پاسخی است که Server در مقابل Request ارسال می‌کند. این پاسخ معمولاً شامل Status Code، Headerها و در بسیاری از موارد Body است.

برای مثال، اگر Client درخواست دریافت صفحه اصلی را ارسال کند، Server ممکن است پاسخی مانند زیر تولید کند:

HTTP/1.1 200 OK
```

Content-Type: text/html



Welcome

```

در این مثال 200 OK نشان می‌دهد که درخواست با موفقیت پردازش شده و Content-Type نوع داده موجود در Response Body را مشخص می‌کند.

```
```

ساختار یک HTTP Request

برای اینکه بتوانیم رفتار HTTP را تحلیل کنیم، باید Request را از نزدیک بررسی کنیم. یک HTTP Request معمولاً از بخش‌های زیر تشکیل می‌شود:

  • Request Line
  • HTTP Headers
  • خط خالی برای جدا کردن Headerها از Body
  • Request Body در صورت نیاز

یک نمونه Request ساده:

GET /products?id=15 HTTP/1.1
```

Host: example.com
User-Agent: Mozilla/5.0
Accept: application/json
Accept-Language: fa-IR
Connection: keep-alive
```

Request Line

خط اول مشخص می‌کند که Client چه عملیاتی را روی چه Resourceای درخواست کرده و از چه نسخه‌ای از HTTP استفاده می‌کند.

GET /products?id=15 HTTP/1.1
  • GET متد درخواست است.
  • /products?id=15 مسیر و Query String است.
  • HTTP/1.1 نسخه پروتکل است.

Query String چیست؟

بخش بعد از علامت ? معمولاً Query String نام دارد.

/products?id=15&sort=price

در این مثال دو پارامتر به سرور ارسال شده‌اند:

  • id=15
  • sort=price

از دید توسعه‌دهنده، Query String برای فیلتر، جست‌وجو، مرتب‌سازی و موارد مشابه بسیار کاربردی است. اما از دید امنیتی نباید تصور کرد که داده موجود در URL قابل اعتماد است.

هر چیزی که Client ارسال می‌کند، از جمله Query Parameter، باید ورودی غیرقابل اعتماد (Untrusted Input) در نظر گرفته شود.

مثال امنیتی

GET /profile?id=15 HTTP/1.1

برنامه نباید صرفاً بر اساس مقدار id تصمیم بگیرد که کاربر اجازه مشاهده اطلاعات چه حسابی را دارد.

فرض کنید کاربر فعلی صاحب حساب شماره 15 است و برنامه این URL را می‌پذیرد:

/profile?id=15

اگر کاربر مقدار را به شکل زیر تغییر دهد:

/profile?id=16

Application باید علاوه بر معتبر بودن ID، مجوز دسترسی کاربر فعلی به Resource شماره 16 را نیز بررسی کند.

اینجا یک اصل مهم امنیتی مطرح می‌شود: Authentication به‌تنهایی کافی نیست؛ Authorization نیز باید در سمت Server اعمال شود.

```
```

ساختار یک HTTP Response

Response نیز ساختار مشخصی دارد و معمولاً از Status Line، Headerها و Body تشکیل می‌شود.

HTTP/1.1 200 OK
```

Content-Type: application/json
Content-Length: 48

{
"id": 15,
"name": "Ali"
}
```

Status Line

اولین خط Response معمولاً شامل نسخه HTTP، کد وضعیت و عبارت توضیحی آن است.

HTTP/1.1 200 OK

مهم‌ترین بخش این خط برای توسعه‌دهنده معمولاً Status Code است.

Response Body

Body حاوی داده‌ای است که Server قصد دارد به Client برگرداند. این داده می‌تواند HTML، JSON، XML، فایل، تصویر یا نوع دیگری از محتوا باشد.

برای مثال یک API ممکن است Response زیر را برگرداند:

HTTP/1.1 200 OK
```

Content-Type: application/json

{
"success": true,
"user": {
"id": 15,
"name": "Ali"
}
}
```

نکته امنیتی مهم این است که Response نیز می‌تواند اطلاعات حساسی را افشا کند. برای مثال ارسال اطلاعات داخلی سیستم، Stack Trace، مسیر فایل‌ها، Connection String یا جزئیات بیش از حد درباره خطاها می‌تواند به مهاجم برای شناسایی ساختار برنامه کمک کند.

```
```

متدهای HTTP و کاربرد آن‌ها

HTTP Method مشخص می‌کند Client چه نوع عملیاتی را از Server درخواست کرده است. متدها صرفاً نام‌هایی مانند GET و POST نیستند؛ انتخاب صحیح Method روی طراحی API، Cache، رفتار مرورگر و حتی امنیت برنامه تأثیر می‌گذارد.

GET

GET معمولاً برای دریافت Resource استفاده می‌شود.

GET /api/products/15 HTTP/1.1
```

Host: example.com
```

در طراحی صحیح، GET نباید باعث تغییر وضعیت مهم یا عملیات مخرب روی Server شود.

POST

POST معمولاً برای ارسال داده یا ایجاد یک عملیات در سمت Server استفاده می‌شود.

POST /api/users HTTP/1.1
```

Host: example.com
Content-Type: application/json

{
"name": "Ali",
"email": "[ali@example.com](mailto:ali@example.com)"
}
```

PUT

PUT معمولاً برای ایجاد یا جایگزینی کامل یک Resource در یک URI مشخص استفاده می‌شود. معنای دقیق آن به طراحی API نیز وابسته است.

PATCH

PATCH معمولاً برای اعمال تغییرات جزئی روی یک Resource استفاده می‌شود.

PATCH /api/users/15 HTTP/1.1
```

Content-Type: application/json

{
"name": "Reza"
}
```

DELETE

DELETE برای درخواست حذف یک Resource استفاده می‌شود.

DELETE /api/users/15 HTTP/1.1

HEAD

HEAD مشابه GET است، با این تفاوت که Server معمولاً Body را ارسال نمی‌کند و اطلاعات مربوط به Response را از طریق Headerها در اختیار Client قرار می‌دهد.

OPTIONS

OPTIONS برای دریافت اطلاعاتی درباره قابلیت‌ها و متدهای پشتیبانی‌شده توسط یک Resource کاربرد دارد و در سازوکار CORS نیز نقش مهمی دارد.

نکته امنیتی درباره HTTP Methodها

یکی از اشتباهات رایج این است که توسعه‌دهنده تصور کند استفاده از POST به‌تنهایی یک عملیات را امن می‌کند. امنیت عملیات به کنترل دسترسی، اعتبارسنجی ورودی، مدیریت Session، CSRF Protection و سایر کنترل‌های امنیتی وابسته است، نه صرفاً به نام Method.

```
```

HTTP Status Codeها و مفهوم آن‌ها

Status Code به Client اعلام می‌کند که نتیجه پردازش Request چه بوده است. این کدها در پنج گروه اصلی قرار می‌گیرند.

گروه مفهوم
1xx اطلاعاتی
2xx موفقیت
3xx Redirect
4xx خطای سمت Client یا درخواست نامعتبر
5xx خطای سمت Server

200 OK

درخواست با موفقیت پردازش شده است.

201 Created

معمولاً زمانی استفاده می‌شود که یک Resource جدید ایجاد شده باشد.

204 No Content

درخواست با موفقیت پردازش شده اما Response Body محتوایی ندارد.

301 و 302

این Status Codeها برای Redirect استفاده می‌شوند و تفاوت‌های معنایی و رفتاری مهمی دارند. در طراحی امنیتی، Redirectها باید با دقت کنترل شوند.

400 Bad Request

Server نتوانسته Request را به‌عنوان یک درخواست معتبر پردازش کند.

401 Unauthorized

معمولاً زمانی استفاده می‌شود که Client برای دسترسی به Resource نیاز به احراز هویت دارد یا اعتبارنامه ارائه‌شده معتبر نیست.

403 Forbidden

Server درخواست را درک کرده اما اجازه انجام عملیات یا دسترسی به Resource را نمی‌دهد.

404 Not Found

Resource موردنظر پیدا نشده است.

405 Method Not Allowed

Method مورد استفاده برای Resource موردنظر مجاز نیست.

429 Too Many Requests

معمولاً برای زمانی استفاده می‌شود که Client در یک بازه زمانی تعداد زیادی درخواست ارسال کرده و Rate Limiting فعال شده است.

500 Internal Server Error

Server در پردازش درخواست با یک خطای داخلی مواجه شده است.

502 Bad Gateway و 503 Service Unavailable

این کدها در معماری‌های چندلایه و سرویس‌های توزیع‌شده اهمیت زیادی دارند و می‌توانند نشانه‌ای از مشکل در سرویس بالادستی یا در دسترس نبودن موقت سرویس باشند.

```
```

Headerهای HTTP چیستند؟

Headerها یکی از مهم‌ترین قسمت‌های HTTP هستند. آن‌ها اطلاعاتی درباره Request یا Response منتقل می‌کنند و می‌توانند روی نحوه پردازش، Cache، Content Negotiation، Authentication، امنیت مرورگر و بسیاری از رفتارهای دیگر تأثیر بگذارند.

یک Header معمولاً ساختاری شبیه زیر دارد:

Header-Name: Header-Value

برای مثال:

Content-Type: application/json

در اینجا Server اعلام می‌کند محتوای Body از نوع JSON است.

Host

Header مربوط به Host مشخص می‌کند درخواست برای کدام Host ارسال شده است و در HTTP/1.1 بخش مهمی از Request محسوب می‌شود.

Host: example.com

User-Agent

User-Agent معمولاً اطلاعاتی درباره Client یا نرم‌افزاری که Request را ارسال کرده ارائه می‌دهد.

User-Agent: Mozilla/5.0

نکته امنیتی مهم: User-Agent را نباید یک هویت قابل اعتماد یا مکانیزم احراز هویت در نظر گرفت؛ Client می‌تواند مقدار آن را تغییر دهد.

Accept

این Header مشخص می‌کند Client چه نوع Contentهایی را ترجیح می‌دهد.

Accept: application/json

Content-Type

Content-Type نوع داده موجود در Body را مشخص می‌کند.

Content-Type: application/json

این Header در APIها اهمیت زیادی دارد؛ زیرا Server باید داده ورودی را بر اساس نوع محتوای مورد انتظار پردازش کند و در صورت نیاز، داده‌های نامعتبر را رد کند.

Authorization

Authorization معمولاً برای ارسال Credential یا Token به Server استفاده می‌شود.

Authorization: Bearer eyJhbGciOi...

Tokenهای احراز هویت باید مانند اطلاعات حساس در نظر گرفته شوند. ثبت کردن آن‌ها در Log، نمایش آن‌ها در URL یا ارسال آن‌ها از طریق کانال ناامن می‌تواند پیامدهای جدی داشته باشد.

Referer

این Header می‌تواند اطلاعاتی درباره صفحه‌ای که درخواست از آنجا ایجاد شده ارائه کند. مقدار آن در بعضی شرایط ممکن است شامل URL یا بخشی از اطلاعات مسیر باشد؛ بنابراین نباید اطلاعات حساس را بدون توجه در URL قرار داد.

```
```

HTTP از دید یک متخصص امنیت

یک متخصص امنیت به HTTP فقط به‌عنوان یک پروتکل انتقال داده نگاه نمی‌کند. تقریباً هر بخشی از Request و Response می‌تواند بخشی از Attack Surface یک برنامه باشد.

مهاجم می‌تواند Request را مشاهده و در محیط‌های مجاز تست امنیتی تغییر دهد، پارامترها را دستکاری کند، Headerهای مختلف را آزمایش کند و رفتار Application را در شرایط غیرعادی بررسی کند.

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

هر داده‌ای که از Client وارد Server می‌شود، بالقوه غیرقابل اعتماد است.

این داده‌ها فقط شامل Form Input نیستند. موارد زیر نیز باید در مدل تهدید در نظر گرفته شوند:

  • Query Parameter
  • Path Parameter
  • Request Body
  • HTTP Header
  • Cookie
  • File Upload
  • Authentication Token
  • اطلاعات ارسال‌شده توسط Client

یک مثال مهم از اعتماد اشتباه به Header

تصور کنید Application بر اساس یک Header سفارشی تصمیم بگیرد کاربر داخلی است:

X-Internal-User: true

اگر Server مستقیماً به مقدار این Header اعتماد کند، مهاجم می‌تواند همان Header را در Request قرار دهد و در صورت نبود کنترل مناسب، مسیر امنیتی برنامه را دور بزند.

Headerهایی که از سمت Client دریافت می‌شوند، به‌صورت پیش‌فرض قابل اعتماد نیستند. اگر معماری برنامه به Header خاصی اعتماد می‌کند، باید مشخص باشد این Header توسط چه مؤلفه‌ای تولید شده، در چه مرزی معتبر است و چگونه از جعل آن جلوگیری می‌شود.

مرز اعتماد یا Trust Boundary

در یک معماری واقعی ممکن است Request از چندین مؤلفه عبور کند. برای مثال:

Internet
```

↓
Reverse Proxy
↓
Load Balancer
↓
Application
↓
Database
```

یکی از پرسش‌های مهم امنیتی این است که Application به کدام اطلاعاتی که از لایه‌های قبلی دریافت می‌کند اعتماد دارد.

برای نمونه Headerهایی مانند X-Forwarded-For یا X-Forwarded-Proto در معماری‌های پشت Proxy کاربرد زیادی دارند، اما نحوه اعتماد به آن‌ها باید متناسب با معماری و تنظیمات Proxy انجام شود.

```
```

سه اصل مهم برای تحلیل HTTP در توسعه امن

۱. Client را قابل اعتماد فرض نکنید

Client تحت کنترل کامل شما نیست. حتی اگر درخواست از مرورگر رسمی برنامه شما آمده باشد، کاربر یا ابزارهای تست می‌توانند Request را تغییر دهند.

۲. Validation و Authorization را از هم جدا کنید

Validation بررسی می‌کند داده از نظر شکل و قوانین قابل قبول است یا خیر؛ Authorization بررسی می‌کند آیا این کاربر اجازه انجام عملیات موردنظر را دارد یا خیر.

۳. خطاها را بیش از حد افشا نکنید

خطای مناسب برای کاربر همیشه همان اطلاعاتی نیست که برای توسعه‌دهنده مفید است. نمایش Stack Trace، مسیر فایل‌ها، نام کلاس‌ها یا جزئیات داخلی Database در محیط Production می‌تواند اطلاعات ارزشمندی در اختیار مهاجم قرار دهد.

```

```
معماری HTTP Request و Response و ارتباط امن بین Client و Server
نمایی مفهومی از چرخه HTTP Request و Response بین Client و Server
```
ByeBug article image

Cookie چیست و چگونه کار می‌کند؟

HTTP به‌صورت ذاتی Stateless است؛ یعنی سرور بین درخواست‌های مختلف، وضعیت Client را به‌صورت خودکار حفظ نمی‌کند. اما یک برنامه وب معمولاً باید بتواند تشخیص دهد که چند Request مختلف متعلق به یک کاربر یا یک Session هستند. یکی از مهم‌ترین ابزارهایی که برای این کار استفاده می‌شود، Cookie است.

Cookie یک قطعه داده کوچک است که معمولاً Server از طریق Header به مرورگر ارسال می‌کند و مرورگر آن را ذخیره کرده و در درخواست‌های بعدی، در شرایطی که قوانین Cookie اجازه دهند، برای همان سایت ارسال می‌کند.

Server چگونه Cookie ایجاد می‌کند؟

Server می‌تواند با استفاده از Header به نام Set-Cookie یک Cookie ایجاد کند:

HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax

مرورگر این Cookie را ذخیره می‌کند و در Requestهای بعدی، در صورت برقرار بودن شرایط مربوط به Domain، Path، Secure و SameSite، آن را در Header دیگری با نام Cookie ارسال می‌کند.

GET /dashboard HTTP/1.1
Host: example.com
Cookie: session_id=abc123

در سمت Server، برنامه می‌تواند مقدار session_id را بررسی کند و بفهمد Request مربوط به کدام Session است.

Cookie چه چیزی را باید ذخیره کند؟

یک اشتباه رایج این است که اطلاعات حساس کاربر مستقیماً داخل Cookie قرار داده شود. Cookie معمولاً باید حداقل اطلاعات لازم برای شناسایی Session یا وضعیت موردنیاز برنامه را حمل کند.

برای مثال، به‌جای اینکه اطلاعاتی مانند رمز عبور یا اطلاعات کامل حساب کاربر داخل Cookie قرار بگیرد، معمولاً یک Session Identifier تصادفی و غیرقابل حدس ذخیره می‌شود:

Set-Cookie: session_id=RANDOM_LONG_VALUE; HttpOnly; Secure; SameSite=Lax

سپس Server مقدار Session ID را در سمت خود به اطلاعات Session مرتبط می‌کند.

Session ID
    ↓
Server-side Session
    ↓
User ID
    ↓
Permissions
    ↓
Session Metadata

در چنین معماری، Cookie به‌تنهایی شامل اطلاعات کامل کاربر نیست؛ بلکه مانند یک شناسه برای پیدا کردن وضعیت Session در Server عمل می‌کند.

Session چیست و چه تفاوتی با Cookie دارد؟

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

  • Cookie: داده‌ای است که User Agent معمولاً در سمت Client ذخیره می‌کند.
  • Session: مفهومی برای نگهداری وضعیت تعامل کاربر با Application است.

یک معماری رایج به این شکل است:

Browser
   |
   | Cookie: session_id=XYZ
   v
Web Server
   |
   | Lookup Session
   v
Session Store
   |
   +--> User ID
   +--> Authentication State
   +--> Expiration
   +--> Permissions

بنابراین مهاجم معمولاً به‌دنبال خود Session Server نیست؛ بلکه ممکن است تلاش کند Session Identifier را به دست آورد.

Session Hijacking چیست؟

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

اگر برنامه چنین Cookieای داشته باشد:

Cookie: session_id=abc123

و مهاجم somehow به مقدار معتبر آن دست پیدا کند، ممکن است بتواند Requestهایی با همان Session ایجاد کند.

به همین دلیل Session ID باید طول مناسب، تصادفی، غیرقابل حدس، دارای عمر منطقی و دارای سازوکار ابطال باشد.

Session Fixation چیست؟

در Session Fixation، مهاجم تلاش می‌کند قربانی را به استفاده از یک Session Identifier مشخص و تحت کنترل یا شناخته‌شده هدایت کند؛ سپس اگر Application پس از Login همان Session را حفظ کند، ممکن است مهاجم بتواند از آن وضعیت سوءاستفاده کند.

یکی از دفاع‌های مهم این است که پس از تغییر سطح دسترسی یا Login موفق، Session Identifier بازتولید شود.

Before Login
Session ID = A

       ↓ Login

After Login
Session ID = B

یعنی ورود موفق کاربر نباید الزاماً با همان Session Identifier قبل از Authentication ادامه پیدا کند.

Headerهای امنیتی HTTP

Headerها فقط برای اعلام نوع Content یا مدیریت Cache نیستند. برخی Response Headerها به مرورگر اعلام می‌کنند که منابع را چگونه بارگذاری کند، آیا صفحه اجازه اجرا در Frame دارد یا چگونه با MIME Type برخورد کند.

Headerهای امنیتی باید بر اساس معماری واقعی برنامه تنظیم شوند؛ قرار دادن تعداد زیادی Header بدون درک رفتار آن‌ها الزاماً به معنای امنیت بیشتر نیست.

Content-Security-Policy

Content-Security-Policy یا CSP یکی از مهم‌ترین مکانیزم‌های دفاعی در سمت مرورگر است. CSP مشخص می‌کند مرورگر چه منابعی را برای صفحه مجاز به بارگذاری یا اجرا بداند.

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  object-src 'none';

هدف CSP کاهش سطح حملاتی مانند XSS و محدود کردن منابعی است که صفحه می‌تواند اجرا یا بارگذاری کند. البته CSP جایگزین Output Encoding و Secure Coding نیست؛ بلکه یک لایه دفاعی اضافه محسوب می‌شود.

X-Content-Type-Options

Header زیر به مرورگر می‌گوید به Content-Type اعلام‌شده احترام بگذارد و تلاش نکند MIME Type را به شکل دلخواه تشخیص دهد:

X-Content-Type-Options: nosniff

این Header می‌تواند در برابر برخی سناریوهای MIME Confusion و MIME Sniffing نقش دفاعی داشته باشد.

Strict-Transport-Security

Header معروف HSTS با نام Strict-Transport-Security به مرورگر اعلام می‌کند که سایت باید از طریق HTTPS استفاده شود.

Strict-Transport-Security: max-age=31536000; includeSubDomains

تنظیم HSTS باید با توجه به وضعیت واقعی HTTPS، Subdomainها و زیرساخت سایت انجام شود؛ زیرا فعال‌سازی نادرست آن می‌تواند دسترسی به برخی Subdomainها را تحت تأثیر قرار دهد.

Referrer-Policy

Referrer-Policy کنترل می‌کند مرورگر چه مقدار از اطلاعات مربوط به URL صفحه مبدأ را هنگام ایجاد درخواست‌های بعدی در اختیار مقصد قرار دهد.

Referrer-Policy: strict-origin-when-cross-origin

این موضوع مخصوصاً زمانی اهمیت پیدا می‌کند که URLهای سایت شامل اطلاعاتی باشند که نباید در Referrer به سرویس‌های دیگر منتقل شوند.

Permissions-Policy

Permissions-Policy می‌تواند استفاده از برخی قابلیت‌های مرورگر را برای سایت یا Frameها محدود کند. این Header نیز بخشی از استراتژی کاهش سطح حمله مرورگر محسوب می‌شود.

X-Frame-Options و Clickjacking

یکی از حملات رایج سمت مرورگر Clickjacking است؛ در این حمله ممکن است رابط کاربری یک سایت در Frame دیگری قرار گرفته و کاربر بدون اطلاع، عملیاتی را روی سایت اصلی انجام دهد.

X-Frame-Options: DENY

در معماری‌های جدید، CSP و دستور frame-ancestors می‌تواند انتخاب دقیق‌تری برای کنترل اینکه چه Originهایی اجازه Frame کردن صفحه را دارند فراهم کند.

CORS چیست و چرا با HTTP ارتباط مستقیم دارد؟

Cross-Origin Resource Sharing یا CORS مکانیزمی است که به مرورگر اجازه می‌دهد درخواست‌های Cross-Origin را بر اساس سیاستی که Server اعلام می‌کند مدیریت کند.

برای مثال فرض کنید Frontend روی دامنه زیر باشد:

https://app.example.com

و API روی:

https://api.example.com

مرورگر ممکن است برای درخواست Cross-Origin، سیاست CORS را در نظر بگیرد.

Origin: https://app.example.com

Server می‌تواند در Response اعلام کند چه Originای مجاز است:

Access-Control-Allow-Origin: https://app.example.com

اشتباه خطرناک در CORS

یکی از خطاهای رایج، باز گذاشتن بیش از حد Originها بدون درک دقیق نیاز برنامه است.

Access-Control-Allow-Origin: *

مقدار * برای همه سناریوها مناسب نیست، مخصوصاً زمانی که برنامه با Credentialها، Cookieها یا داده‌های حساس کار می‌کند.

CORS یک مکانیزم امنیتی سمت Browser است و نباید جایگزین Authentication و Authorization در سمت Server شود.

CSRF؛ وقتی مرورگر به‌جای کاربر درخواست می‌فرستد

Cross-Site Request Forgery یا CSRF یکی از حملاتی است که به نحوه ارسال Credentialها توسط مرورگر و اعتماد Application به درخواست‌ها مرتبط است.

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

یک الگوی دفاعی رایج استفاده از CSRF Token است:

POST /transfer HTTP/1.1
Cookie: session_id=ABC123
Content-Type: application/x-www-form-urlencoded

amount=1000&csrf_token=RANDOM_TOKEN

Server باید Token را با Session یا Context معتبر کاربر تطبیق دهد و درخواست‌هایی که فاقد Token معتبر هستند را رد کند.

تنظیم صحیح SameSite Cookie نیز می‌تواند در کاهش برخی سناریوهای Cross-Site Request نقش داشته باشد، اما انتخاب روش دفاعی باید با توجه به معماری برنامه انجام شود.

XSS و ارتباط آن با HTTP

Cross-Site Scripting یا XSS زمانی رخ می‌دهد که داده کنترل‌شده توسط مهاجم در Contextی قرار گیرد که مرورگر آن را به‌عنوان کد یا Markup قابل اجرا تفسیر کند.

تصور کنید Application این URL را دریافت می‌کند:

/search?q=developer

اگر مقدار q بدون Encoding مناسب در HTML قرار گیرد، ممکن است Application در برابر XSS آسیب‌پذیر شود.

راهکار صحیح این نیست که صرفاً چند کاراکتر خاص را حذف کنیم. باید Context خروجی مشخص باشد و Encoding مناسب همان Context انجام شود.

  • HTML Context
  • HTML Attribute Context
  • JavaScript Context
  • CSS Context
  • URL Context

علاوه بر Output Encoding، استفاده از CSP نیز می‌تواند یک لایه دفاعی مهم در برابر پیامدهای برخی سناریوهای XSS ایجاد کند.

نقاط حمله در HTTP

وقتی یک متخصص امنیت یک Web Application را بررسی می‌کند، تنها صفحه Login را بررسی نمی‌کند. تمام ورودی‌ها و رفتارهای HTTP می‌توانند بخشی از Attack Surface باشند.

۱. Query Parameters

/products?id=15
/search?q=laptop
/orders?sort=price

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

۲. Path Parameters

/users/15
/orders/7821
/files/report.pdf

وجود یک ID معتبر به معنای داشتن Permission برای دسترسی به Resource نیست.

۳. Request Body

{
  "userId": 15,
  "role": "admin"
}

اگر Backend بدون بررسی Authorization مقدار role را قبول کند، یک مشکل جدی در طراحی امنیتی ایجاد می‌شود.

۴. Headerها

Headerهای ورودی نیز داده Client هستند. حتی اگر نام Header شبیه یک Header داخلی باشد، نباید بدون مشخص کردن Trust Boundary به آن اعتماد کرد.

۵. Cookieها

Cookieهای Session، Tokenها و سایر داده‌های حساس باید با تنظیمات امنیتی مناسب محافظت شوند.

۶. File Upload

Upload فایل یکی از نقاط مهم Attack Surface است. صرفاً بررسی پسوند فایل کافی نیست و باید Content Type، حجم، نام فایل، محل ذخیره‌سازی و نحوه ارائه فایل به کاربر نیز کنترل شود.

IDOR؛ وقتی HTTP یک شناسه ساده را به یک مشکل امنیتی تبدیل می‌کند

یکی از مثال‌های بسیار خوب برای درک تفاوت Authentication و Authorization، آسیب‌پذیری Insecure Direct Object Reference یا IDOR است.

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

GET /api/orders/5001 HTTP/1.1
Cookie: session_id=ABC

اگر کاربر مقدار را تغییر دهد:

GET /api/orders/5002 HTTP/1.1
Cookie: session_id=ABC

Server نباید فقط به معتبر بودن Session و وجود Order شماره 5002 اکتفا کند. باید بررسی کند آیا کاربر فعلی مالک Order شماره 5002 است یا Permission لازم برای مشاهده آن را دارد.

Authenticated?
      |
      +-- Yes
           |
           v
      Authorized for Order 5002?
           |
        +--+--+
        |     |
       Yes    No
        |      |
      Allow   403

این مثال نشان می‌دهد چرا تغییر یک عدد ساده در URL می‌تواند به یک آسیب‌پذیری جدی تبدیل شود؛ مشکل در HTTP نیست، بلکه در اعتماد نادرست Application به داده‌ای است که از HTTP دریافت کرده است.

SSRF؛ وقتی Server به مقصد اشتباه درخواست می‌فرستد

Server-Side Request Forgery یا SSRF زمانی رخ می‌دهد که Application به کاربر اجازه دهد مقصد یک Request سمت Server را کنترل کند، بدون اینکه مقصد به‌درستی اعتبارسنجی شود.

فرض کنید API زیر وجود دارد:

GET /fetch?url=https://example.com/image.jpg

اگر Backend واقعاً URL را از کاربر دریافت کرده و خودش به آن URL Request بزند، باید مشخص شود چه مقصدهایی مجاز هستند.

در غیر این صورت، ورودی کاربر می‌تواند Server را به سمت منابعی ببرد که از اینترنت عمومی قابل دسترسی نیستند.

دفاع در برابر SSRF معمولاً نیازمند ترکیبی از Allowlist مقصدها، محدودسازی Network Egress، جلوگیری از دسترسی غیرضروری به Networkهای داخلی و اعتبارسنجی دقیق URL است.

HTTP Request Smuggling؛ وقتی Proxy و Backend یک Request را متفاوت می‌فهمند

یکی از موضوعات پیشرفته‌تر امنیت HTTP، HTTP Request Smuggling است. این کلاس از حملات زمانی اهمیت پیدا می‌کند که چند مؤلفه مانند Reverse Proxy، Load Balancer و Backend Server، مرزهای Request را به شکل متفاوتی تفسیر کنند.

Client
  |
  v
Reverse Proxy
  |
  v
Load Balancer
  |
  v
Backend

اگر Frontend و Backend درباره نحوه تفسیر برخی Headerهای مربوط به طول یا انتقال پیام اختلاف داشته باشند، ممکن است مهاجم بتواند ساختار پیام‌ها را به شکلی ایجاد کند که دو مؤلفه برداشت متفاوتی از Request داشته باشند.

این موضوع نشان می‌دهد که امنیت HTTP فقط در Controllerهای Application خلاصه نمی‌شود؛ پیکربندی Proxy، Load Balancer و Server نیز بخشی از سطح حمله هستند.

Open Redirect؛ یک Redirect ساده اما پرریسک

Redirect در HTTP با Status Codeهایی مانند 301، 302، 303، 307 و 308 انجام می‌شود. مشکل زمانی ایجاد می‌شود که Application مقصد Redirect را مستقیماً از کاربر دریافت کند.

برای مثال:

/login?returnUrl=https://trusted.example

اگر Server بدون بررسی اجازه دهد هر URL خارجی به‌عنوان مقصد استفاده شود، ممکن است برنامه به Open Redirect آسیب‌پذیر شود.

در طراحی امن بهتر است مقصدهای مجاز مشخص باشند و Application از Redirect کردن کاربر به مقصدهای ناشناخته یا غیرمجاز جلوگیری کند.

Information Disclosure؛ وقتی Response بیش از حد حرف می‌زند

یکی از اشتباهات رایج توسعه‌دهندگان این است که Response خطا را برای Debugging بسیار کامل طراحی می‌کنند اما همان Response را در Production نیز نمایش می‌دهند.

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

{
  "error": "SqlException",
  "message": "Login failed for user 'sa'",
  "server": "DB01",
  "database": "ProductionDB",
  "stackTrace": "..."
}

این اطلاعات می‌تواند جزئیات داخلی سیستم را افشا کند.

بهتر است Response عمومی اطلاعات حداقلی داشته باشد:

{
  "error": "internal_error",
  "message": "خطایی در پردازش درخواست رخ داد.",
  "requestId": "7f81c..."
}

جزئیات فنی باید در سیستم Logging امن و کنترل‌شده ثبت شوند، نه اینکه مستقیماً در اختیار Client قرار بگیرند.

Rate Limiting و کنترل تعداد Requestها

HTTP به Client اجازه می‌دهد تعداد زیادی Request ارسال کند. اگر Application هیچ محدودیتی نداشته باشد، بعضی Endpointها می‌توانند هدف سوءاستفاده، Brute Force یا مصرف بیش از حد منابع قرار بگیرند.

Rate Limiting می‌تواند تعداد درخواست‌های مجاز را بر اساس IP، User، API Key، Session یا ترکیبی از این عوامل محدود کند.

POST /api/login

Request #1  → Allowed
Request #2  → Allowed
Request #3  → Allowed
...
Request #20 → Rate Limited

در صورت عبور از محدودیت، Server می‌تواند از Status Code مناسب مانند 429 Too Many Requests استفاده کند.

برای Endpointهای حساس مانند Login، Reset Password، OTP و APIهای هزینه‌بر، Rate Limiting باید بخشی از طراحی امنیتی باشد، نه یک قابلیت اضافه در پایان پروژه.

Logging؛ HTTP را ببینید، اما Secretها را ثبت نکنید

تحلیل HTTP بدون Logging مناسب دشوار است. توسعه‌دهنده و تیم امنیتی باید بتوانند بفهمند چه Requestهایی وارد سیستم شده‌اند، چه Responseهایی ایجاد شده‌اند و خطاها در چه شرایطی رخ داده‌اند.

اما Logging بیش از حد نیز می‌تواند به یک مشکل امنیتی تبدیل شود.

مواردی مانند Password، Session Cookie، Access Token و Secretهای API نباید بدون نیاز و بدون Masking در Log ذخیره شوند.

Authorization: Bearer eyJhbGciOi...

ثبت کامل چنین Headerی در Log می‌تواند باعث شود Token حساس در سیستم‌های Logging، داشبوردها، فایل‌های Backup یا سرویس‌های مانیتورینگ باقی بماند.

یک رویکرد بهتر، Mask کردن داده‌های حساس است:

Authorization: Bearer eyJ...REDACTED

چک‌لیست امنیت HTTP برای توسعه‌دهندگان

قبل از انتشار یک Web Application، بررسی موارد زیر می‌تواند نقاط ضعف رایج HTTP را تا حد زیادی کاهش دهد:

  • استفاده اجباری از HTTPS برای ارتباطات حساس
  • استفاده صحیح از Secure برای Cookieهای حساس
  • استفاده از HttpOnly برای Session Cookieهای مناسب
  • تنظیم صحیح SameSite بر اساس نیاز Application
  • اعتبارسنجی تمام Query Parameterها
  • اعتبارسنجی Path Parameterها
  • اعتبارسنجی Request Body
  • عدم اعتماد به Headerهای ارسال‌شده توسط Client
  • پیاده‌سازی Authorization در سمت Server
  • جلوگیری از IDOR
  • استفاده از CSRF Protection در سناریوهای لازم
  • محافظت در برابر XSS با Output Encoding و دفاع‌های تکمیلی مانند CSP
  • تنظیم صحیح CORS
  • استفاده از Security Headerهای متناسب با معماری
  • عدم نمایش Stack Trace در Production
  • استفاده از Rate Limiting برای Endpointهای حساس
  • محافظت از File Upload
  • جلوگیری از SSRF در قابلیت‌هایی که Server را مجبور به Fetch کردن URL می‌کنند
  • مدیریت صحیح Session Lifecycle
  • Regenerate کردن Session پس از تغییر سطح دسترسی در سناریوهای لازم
  • عدم ثبت Token و Cookie حساس در Log
  • بررسی تنظیمات Reverse Proxy و Load Balancer

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

توسعه‌دهنده‌ای که HTTP را فقط از دید «درخواست بفرست و پاسخ بگیر» می‌بیند، بخش بزرگی از واقعیت Application را از دست می‌دهد.

یک نگاه امنیتی بهتر این است که برای هر Request چند سؤال مشخص پرسیده شود:

  1. چه کسی این Request را ساخته است؟
  2. آیا داده‌های آن قابل اعتماد هستند؟
  3. اگر یک پارامتر تغییر کند چه اتفاقی می‌افتد؟
  4. آیا کاربر واقعاً اجازه انجام این عملیات را دارد؟
  5. آیا Response اطلاعات بیشتری از حد لازم افشا می‌کند؟
  6. اگر Request هزار بار تکرار شود چه اتفاقی رخ می‌دهد؟
  7. اگر Headerها تغییر کنند Application چه رفتاری دارد؟
  8. اگر Cookie دستکاری شود چه اتفاقی رخ می‌دهد؟
  9. اگر Client اصلاً مرورگر نباشد چه می‌شود؟
  10. اگر Request از یک Proxy یا Gateway عبور کرده باشد، کدام Headerها معتبر هستند؟

همین پرسش‌های ساده می‌توانند مسیر یک توسعه‌دهنده را از «کدنویسی که کار می‌کند» به سمت کدنویسی امن و مقاوم در برابر سوءاستفاده تغییر دهند.

جمع‌بندی؛ HTTP فقط یک پروتکل ساده نیست

HTTP پایه بسیاری از ارتباطات Web Applicationها و APIهای مدرن است. درک دقیق Request و Response، Methodها، Status Codeها، Headerها و Cookieها به توسعه‌دهنده کمک می‌کند رفتار واقعی Application را بهتر درک کند.

از طرف دیگر، متخصص امنیت می‌داند که همین اجزا می‌توانند Attack Surface ایجاد کنند. Query String، Header، Cookie، Session، Redirect، File Upload و حتی معماری Proxy می‌توانند در شرایط خاص به بخشی از یک زنجیره حمله تبدیل شوند.

بنابراین امنیت HTTP با یک Header یا یک تنظیم خاص تمام نمی‌شود. امنیت واقعی حاصل ترکیب HTTPS، مدیریت صحیح Session، کنترل دسترسی، اعتبارسنجی ورودی، Output Encoding، Cookie Security، Security Headers، Rate Limiting، Logging امن و طراحی صحیح معماری است.

اگر یک توسعه‌دهنده بتواند HTTP را هم‌زمان از دید Browser، Server، Proxy و مهاجم تحلیل کند، بسیاری از مشکلات امنیتی قبل از رسیدن به محیط Production قابل شناسایی خواهند بود.

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

    ```
  • HTTP چیست و چه کاربردی دارد؟

    HTTP پروتکل ارتباطی وب است که ساختار Request و Response بین Client و Server را مشخص می‌کند. مرورگرها و بسیاری از APIها از HTTP برای دریافت و ارسال منابع و داده استفاده می‌کنند.

  • تفاوت HTTP و HTTPS چیست؟

    HTTPS استفاده از HTTP روی یک ارتباط محافظت‌شده با TLS است. این لایه به حفاظت از محرمانگی و تمامیت داده‌های در حال انتقال کمک می‌کند و برای اطلاعات حساس باید به‌درستی پیکربندی شود.

  • Cookie چیست؟

    Cookie داده‌ای است که Server می‌تواند در مرورگر ذخیره کند تا در درخواست‌های بعدی، در شرایط مناسب، همراه Request ارسال شود. Cookieها معمولاً برای Session، تنظیمات و برخی کاربردهای دیگر استفاده می‌شوند.

  • HttpOnly چه کاری انجام می‌دهد؟

    HttpOnly باعث می‌شود Cookie از طریق APIهای JavaScript سمت Client مانند document.cookie قابل خواندن نباشد و برای Session Cookieها یک لایه دفاعی مهم ایجاد می‌کند.

  • Secure Cookie چیست؟

    Cookie دارای ویژگی Secure در درخواست‌های HTTPS ارسال می‌شود و برای Cookieهای حساس مانند Session Cookie توصیه می‌شود.

  • آیا POST از GET امن‌تر است؟

    صرفاً استفاده از POST باعث امن شدن یک عملیات نمی‌شود. امنیت به Authentication، Authorization، Validation، CSRF Protection و سایر کنترل‌های امنیتی وابسته است.

  • Headerهای HTTP چه نقشی در امنیت دارند؟

    Headerها می‌توانند اطلاعات و سیاست‌های مهمی درباره ارتباط و رفتار مرورگر مشخص کنند. Headerهایی مانند CSP، HSTS، Referrer-Policy و X-Content-Type-Options در معماری مناسب می‌توانند به کاهش برخی ریسک‌های امنیتی کمک کنند.

  • IDOR چیست؟

    IDOR زمانی رخ می‌دهد که برنامه صرفاً بر اساس یک شناسه موجود در Request به Resource دسترسی دهد و بررسی نکند آیا کاربر فعلی واقعاً مجوز دسترسی به آن Resource را دارد یا خیر.

  • CSRF چیست؟

    CSRF نوعی حمله است که در آن مهاجم تلاش می‌کند مرورگر کاربر را به ارسال یک Request ناخواسته به برنامه‌ای که کاربر در آن احراز هویت شده وادار کند.

  • آیا استفاده از Security Headerها به‌تنهایی سایت را امن می‌کند؟

    خیر. Security Headerها یک لایه دفاعی هستند و باید در کنار کنترل دسترسی، Validation، مدیریت Session، HTTPS، Encoding، Logging و سایر اصول Secure Development استفاده شوند.

  • ```

آنچه یک توسعه‌دهنده حرفه‌ای باید از HTTP بداند

اگر بخواهیم کل این بحث را در چند اصل خلاصه کنیم، باید بگوییم:

  • HTTP زبان ارتباطی Client و Server در وب است.
  • هر Request ورودی بالقوه غیرقابل اعتماد است.
  • هر Response باید حداقل اطلاعات لازم را افشا کند.
  • Authentication مشخص می‌کند «چه کسی هستی» و Authorization مشخص می‌کند «چه کاری اجازه داری انجام دهی».
  • Cookie و Session باید مانند دارایی‌های امنیتی حساس مدیریت شوند.
  • Headerها فقط Metadata نیستند و بعضی از آن‌ها مستقیماً روی امنیت Browser تأثیر دارند.
  • CORS جایگزین Authorization نیست.
  • HttpOnly و Secure مکمل یکدیگرند و هیچ‌کدام به‌تنهایی امنیت کامل Cookie را تضمین نمی‌کنند.
  • امنیت HTTP باید از Client تا Proxy و Backend بررسی شود.
  • امنیت واقعی نتیجه طراحی صحیح کل سیستم است، نه یک Header یا یک قطعه کد.