بیشتر Endpointهای ناامن با نبودن TLS یا یک ابزار عجیب شکست نمیخورند؛ شکست از جایی شروع میشود که تیم نمیتواند به چند پرسش ساده و دقیق جواب دهد: این درخواست دقیقاً چه عمل تجاریای انجام میدهد؟ چه کسی روی کدام رکورد و کدام فیلد مجاز است؟ هزینه پردازش آن چقدر است؟ اگر درخواست دو بار رسید چه میشود؟ و هنگام سوءاستفاده چه شواهدی داریم؟ نصب API Gateway، انتخاب JWT یا افزودن WAF جای این قرارداد را نمیگیرد.
این راهنما برای امنسازی و تست پذیرش یک Endpoint نوشته شده است؛ از تعریف قرارداد دسترسی تا کنترل BOLA و BOPLA، سوءاستفاده از جریان تجاری، SSRF، بودجه منابع، Idempotency، پاسخ، لاگ و Runbook. برای طراحی برنامه امنیت در سطح کل سبد REST، GraphQL و Webhook، ابتدا راهنمای جامع امنیت API و OWASP را بخوانید. اینجا واحد کار کوچکتر و عملیتر است: یک Method و Path که باید پیش از انتشار، شواهد قبولی تولید کند.
امنسازی Endpoint API دقیقاً یعنی چه؟
Endpoint فقط یک URL نیست. یک مرز اجرایی میان مصرفکننده، هویت، داده، منطق کسبوکار و سرویسهای پاییندست است. امنسازی یعنی این مرز برای ورودی معتبر و نامعتبر رفتار تعریفشده داشته باشد، حداقل اختیار را اعمال کند، هزینه را محدود نگه دارد، اثر جانبی را کنترل کند و برای تصمیمهای حساس شواهد قابلپیگیری بسازد.
OWASP API Security Top ۱۰ نسخه ۲۰۲۳ موضوعهایی مانند مجوزدهی شکسته در سطح شیء و ویژگی، مصرف نامحدود منابع، دسترسی نامحدود به جریانهای حساس، SSRF، موجودی ناقص و اعتماد ناامن به API ثالث را برجسته میکند. این فهرست برای آگاهی و Threat modeling مفید است، اما خودش Specification یا Test plan کامل یک Endpoint نیست.
| سؤال | پاسخ ضعیف | شاهد قابلقبول |
|---|---|---|
| چه کسی مجاز است؟ | کاربر لاگینشده | Subject، Tenant، Role/Scope، Assurance و Policy مشخص |
| به چه چیزی دسترسی دارد؟ | سفارش خودش | قانون Object و Property با تست Alice/Bob/Admin |
| چه ورودی میپذیرد؟ | JSON معتبر | Schema، Allowlist، سقف اندازه و خطای قراردادی |
| چقدر منابع مصرف میکند؟ | Rate limit داریم | بودجه درخواست، همزمانی، Query، فایل، Export و Downstream |
| اگر تکرار شد؟ | کلاینت نباید تکرار کند | Idempotency key، دامنه، TTL، پاسخ Replay و تست Race |
| چطور رخداد را میبینیم؟ | همه Payload را لاگ میکنیم | Audit event کمینه، Redaction، Correlation ID، Alert و Runbook |
Intent و مرز این راهنما
کلیدواژه اصلی این صفحه «امنسازی API» و «امنسازی Endpoint» است. عبارتهای مکمل شامل چکلیست امنیت API، تست امنیت Endpoint، BOLA و BOPLA، امنیت JWT، Rate limiting، Idempotency و API security testing هستند. هدف جستوجو عملی است: توسعهدهنده یا مالک فنی میخواهد قبل از Release بداند چه کنترلهایی را کجا پیاده و چگونه قبول یا رد کند.
این صفحه جای طراحی هویت سازمانی، معماری Zero Trust یا تست نفوذ مستقل را نمیگیرد. برای Policy و Enforcement سراسری به مدل Zero Trust برای وباپلیکیشن و برای ارزیابی مستقل به راهنمای تست نفوذ وباپلیکیشن مراجعه کنید. تمرکز اینجا Acceptance قابلتکرار در سطح Endpoint است.
قرارداد امنیتی Endpoint را قبل از کدنویسی بنویسید
یک قرارداد خوب بهاندازهای کوتاه است که در Pull Request دیده شود و بهاندازهای دقیق است که از آن تست بسازید. OpenAPI میتواند شکل Request و Response را مستند کند، اما قرارداد امنیتی باید معنا و اثر تجاری را هم اضافه کند. عبارت «Bearer token required» نمیگوید دارنده توکن روی کدام شیء، فیلد یا تغییر وضعیت مجاز است.
| فیلد قرارداد | پرسش الزامی | نمونه برای POST /v1/orders |
|---|---|---|
| Owner و Version | چه تیمی پاسخگوست و تا چه تاریخی پشتیبانی میشود؟ | Checkout / v1 / بازبینی فصلی |
| Consumer | Browser، Mobile، Partner یا Service؟ | اپ موبایل و وب First-party |
| Business action | اثر واقعی درخواست چیست؟ | رزرو موجودی و ایجاد سفارش پرداختنشده |
| Data class | PII، مالی، Credential یا عمومی؟ | شماره تماس و آدرس؛ حساس تجاری |
| Authentication | نوع Credential و Assurance چیست؟ | Session/OAuth access token معتبر |
| Authorization | Function، Object، Property و State چه قواعدی دارند؟ | فقط سبد Tenant جاری؛ قیمت سمت Server |
| Input | Schema، Allowlist و Normalization چیست؟ | شناسه آدرس، اقلام، کد تخفیف؛ بدون total |
| Resource budget | اندازه، تعداد، زمان و همزمانی چقدر است؟ | حداکثر ۱۰۰ قلم، Body محدود، Timeout پاییندست |
| Replay | تکرار و Race چگونه کنترل میشوند؟ | Idempotency-Key به ازای Subject و Operation |
| Response | کدام فیلدها و خطاها قابلنمایشاند؟ | DTO صریح؛ بدون Cost داخلی یا Rule محرمانه |
| Telemetry | چه Event و Metric بدون افشای داده ثبت میشود؟ | Outcome، Latency، Authz decision، order_id هششده |
| Failure policy | در خرابی Identity، DB یا PSP چه میشود؟ | Fail closed برای مجوز؛ وضعیت قابلبازیابی برای سفارش |
نمونه قرارداد فشرده
Endpoint: POST /v1/orders
Actor: authenticated customer in current tenant
Input: address_id, items[{sku, quantity}], coupon_code?
Server-owned: unit_price, discount, inventory, payable_amount, status
Authorization: actor owns cart and address; SKU is sellable in tenant
Preconditions: cart_version matches; address active; coupon eligible
Budget: body/items/query/time/concurrency/downstream calls are bounded
Replay: Idempotency-Key scoped to actor + operation + normalized payload
Response: explicit OrderCreated DTO; private fields denied by default
Audit: actor, tenant, action, outcome, policy/version, correlation_id
Failure: no duplicate order; ambiguous payment moves to verification stateاین متن برای پیادهسازی کافی نیست، اما اختلافهای پنهان میان Product، Backend، Security و QA را زود آشکار میکند. آن را کنار قرارداد Data و Integration نگه دارید؛ مقاله یکپارچهسازی سایت با API، Webhook و Data Contract مرزهای وابستگی و Runbook را در سطح معماری توضیح میدهد.
زنجیره تصمیم هر Request
کنترلها را بهصورت زنجیره ببینید، نه مجموعهای از Pluginها. ترتیب دقیق با معماری فرق دارد، اما هر مرحله باید Owner، Failure mode و Test داشته باشد:
- ارتباط امن و هویت سرویس یا Origin بررسی شود.
- Method، Path، Version، Content-Type، Encoding و اندازه مجاز باشند.
- Credential استخراج و از نظر امضا، صادرکننده، مخاطب، زمان و Context اعتبارسنجی شود.
- Subject، Tenant و Assurance به Context قابلاعتماد تبدیل شوند.
- مجوز Function، Object، Property و Business state در Server اعمال شود.
- ورودی با Schema و Allowlist Parse و Normalize شود؛ داده اضافی رد یا نادیدهسازیِ قراردادی شود.
- بودجه منابع، Abuse و وابستگیهای خروجی پیش از کار پرهزینه کنترل شوند.
- Transaction، Idempotency، Concurrency و Side effect مدیریت شوند.
- Response از DTO صریح و مجوز فیلدی ساخته، Cache و Error کنترل شوند.
- رویداد کمینه و نتیجه تصمیم برای مشاهدهپذیری ثبت شود.
Gateway میتواند مراحل مشترک مانند TLS termination، Route، اعتبار اولیه Token، سقف اندازه و Rate limit را متمرکز کند. اما Gateway معمولاً نمیداند کاربر «الف» مالک سفارش ۴۲ است یا مدیر فروش اجازه دیدن فیلد هزینه تأمین را دارد. مجوز شیء و ویژگی باید نزدیک منطق و داده اعمال شود.
احراز هویت: JWT یک ویژگی امنیتی خودکار نیست
API Key، Cookie session، OAuth access token، mTLS و Workload identity ابزارهایی با Threat model متفاوتاند. انتخاب باید از Consumer، چرخه عمر Credential، امکان Revocation، سطح Assurance و اثر سرقت آغاز شود. API Key بهتنهایی برای دسترسی حساسِ کاربر نهایی معمولاً هویت و مجوز کافی نمیسازد؛ Session مرورگر نیز بدون کنترل CSRF و Cookie درست، صرفاً «لاگین» نیست.
اگر JWT استفاده میکنید، Decode شدن Token هیچ چیز را اثبات نمیکند. RFC ۸۷۲۵، Best Current Practices برای JWT بر Allowlist الگوریتم، اعتبارسنجی عملیات رمزنگاری، کلید مناسب، Issuer و Audience و جلوگیری از Token substitution تأکید دارد. حداقل قرارداد اعتبارسنجی باید این موارد را روشن کند:
- الگوریتمهای مجاز در تنظیم Server ثابتاند؛ Header ارسالی کاربر آنها را انتخاب نمیکند.
- Signature و زنجیره Key/JWK معتبرند و Rotation یا Key compromise مسیر عملیاتی دارد.
iss،aud،exp،nbfو Claimهای الزامی با Clock skew محدود بررسی میشوند.- ID Token بهجای Access token و Token مربوط به API دیگر پذیرفته نمیشود.
kid،jkuیا Claimهای URL برای Lookup کورکورانه استفاده نمیشوند.- Logout، Suspension، تغییر Role و رخداد سرقت با عمر کوتاه، Session state یا Revocation متناسب پوشش مییابند.
برای OAuth، RFC ۹۷۰۰؛ OAuth ۲.۰ Security Best Current Practice مرجع جاریِ انتخاب Flow و دفاع در برابر تهدیدهای شناختهشده است. نام استاندارد بهتنهایی تضمین نمیکند Client، Redirect URI، PKCE، Token storage و Resource server درست پیکربندی شدهاند.
MFA و Step-up را در نقطه ریسک بهکار ببرید
ممکن است Session کاربر برای مشاهده پروفایل کافی باشد اما تغییر شماره، افزودن حساب تسویه، صدور کلید API یا Refund بزرگ به Step-up نیاز داشته باشد. Policy باید نوع عمل، تازگی احراز هویت، ریسک دستگاه و Recovery را مشخص کند. برای حسابهای کنترلکننده سامانه، راهنمای MFA پنل مدیریت الگوی استقرار و بازیابی را پوشش میدهد.
مجوزدهی را به چهار لایه بشکنید
بسیاری از نقصهای جدی وقتی رخ میدهند که تیم فقط Route-level role check دارد. مجوز مؤثر دستکم چهار تصمیم جداست:
| لایه | سؤال | شکست نمونه | تست منفی |
|---|---|---|---|
| Function | آیا Actor اصولاً این عمل را دارد؟ | کاربر عادی به Endpoint ادمین میرسد | User نقش عادی، Method و Route ادمین را صدا بزند |
| Object | آیا روی این رکورد مشخص مجاز است؟ | تعویض order_id، سفارش دیگری را نشان میدهد | Alice شناسه Bob را درخواست کند |
| Property | کدام فیلد را میتواند بخواند یا تغییر دهد؟ | Client مقدار role یا unit_price میفرستد | فیلد Server-owned به Payload تزریق شود |
| Business state | این Transition اکنون مجاز است؟ | سفارش ارسالشده Cancel یا Refund دوباره میشود | عمل در State، زمان یا سقف نامعتبر تکرار شود |
BOLA: شناسه قابلحدس مسئله اصلی نیست
Broken Object Level Authorization یعنی Server پس از دریافت شناسه، رابطه Actor با Object را درست بررسی نمیکند. UUID میتواند حدسزدن را سختتر کند، اما مجوز نیست. Query باید در Scope قابلاعتماد ساخته شود؛ مثلاً سفارش با tenant_id و owner_id جاری بازیابی شود، نه اینکه ابتدا هر سفارش پیدا و سپس به شرطی شکننده تکیه شود.
BOPLA و Mass Assignment: ورودی و خروجی را صریح کنید
Bind کردن مستقیم JSON به Model راهی کوتاه برای تغییر فیلدهای role، status، balance یا approved_at است. DTO ورودی باید Allowlist داشته باشد و Mapping به Model صریح باشد. در خروجی نیز Serialization کل Entity ممکن است شماره داخلی، حاشیه سود، Flag تقلب یا داده Tenant دیگر را افشا کند. Response model مستقل و مجوز Property لازم است.
// الگوی مفهومی؛ نامها وابسته به Framework هستند
const input = OrderInput.parse(request.body) // allowlist + limits
const actor = requireIdentity(request)
const cart = await carts.findOwned(input.cartId, actor.tenantId, actor.id)
authorize(actor, 'order:create', cart)
const result = await createOrder(mapServerOwnedValues(input, cart))
return OrderCreatedResponse.from(result, actor) // explicit fieldsجریان تجاری حساس را جدا از Rate limit محافظت کنید
یک درخواست ممکن است از نظر Syntax و Authentication معتبر باشد اما در مقیاس، ترتیب یا نیت مخرب باشد. ارسال OTP، آزمون کد تخفیف، رزرو بلیت، ساخت حساب، استعلام قیمت، افزودن کارت هدیه، درخواست Refund و Export نمونههای Sensitive business flow هستند. مهاجم الزاماً Rate بسیار بالا ندارد؛ ممکن است آهسته، توزیعشده و با هزار حساب قانونی عمل کند.
| جریان | ارزش مهاجم | کنترلهای ترکیبی | Guardrail محصول |
|---|---|---|---|
| ارسال OTP پیامکی | تحمیل هزینه، مزاحمت یا Enumeration | Device/Account/Number/IP/ASN velocity، Cooldown، Risk score | Recovery و دسترسپذیری برای کاربر واقعی |
| Coupon check | کشف کد یا مصرف انبوه | Attempt budget، Binding، Monitoring، Rule server-side | خطای غیرقابل Enumeration |
| رزرو موجودی | احتکار یا ایجاد کمبود مصنوعی | Hold TTL، Account/device quota، payment binding | Release قطعی و وضعیت شفاف |
| Refund | برداشت یا تکرار بازپرداخت | State machine، Step-up، سقف، four-eyes، idempotency | زمان پاسخ و مسیر بررسی |
| Export | استخراج تدریجی داده | Scope، row/time budget، async job، approval، audit | Notification و امکان لغو |
Rate limit باید چندبعدی و متناسب با عمل باشد: Subject، Tenant، Credential، Device، مقصد، شماره تلفن، IP/Network، Action و پنجره زمانی. IP بهتنهایی پشت NAT، اپراتور موبایل یا VPN میتواند هم کاربر واقعی را مسدود کند و هم حمله توزیعشده را از دست بدهد. CAPTCHA نیز یک تصمیم محصول و دسترسپذیری است، نه دیوار جادویی.
برای هر Endpoint بودجه منابع تعریف کنید
OWASP در API4:۲۰۲۳ از Unrestricted Resource Consumption میگوید؛ مسئله فقط تعداد درخواست نیست. یک درخواست کوچک میتواند Query سنگین، Fan-out زیاد، فایل فشرده انفجاری، Export میلیونی یا فراخوانی پرهزینه پیامک و سرویس ثالث بسازد.
| منبع | بودجه قابلاندازهگیری | تست مرزی |
|---|---|---|
| HTTP body | Byte پس از Decompression و پیش از Parse | کمی زیر/روی سقف، Chunked و فشرده |
| JSON | عمق، تعداد Node، طول String/Array | Nested object و Array بزرگ |
| Pagination | page size، cursor validity، max scan | limit منفی/بزرگ و cursor قدیمی |
| Database | Query count، rows scanned، timeout | Filter بدترین حالت و tenant بزرگ |
| GraphQL | Depth، complexity، aliases، batch | Fragment چرخهای و alias fan-out |
| فایل | نوع واقعی، اندازه، Pixel/page، زمان پردازش | Polyglot، archive، تصویر عظیم |
| همزمانی | Per actor/tenant/global in-flight | Burst و Slow request |
| Downstream | Call count، timeout، retry budget، cost | کندی یا ۴۲۹ سرویس پیامک/PSP |
سقفها باید از ظرفیت و ریسک کسبوکار بیایند، نه عدد ثابت اینترنتی. رفتار عبور از سقف نیز بخشی از Contract است: رد سریع، Queue، پاسخ ۴۲۹ با راهنمای Retry، Job ناهمگام یا کاهش قابلیت. Retry بیحد میتواند خرابی پاییندست را به Retry storm تبدیل کند.
ورودی: Parse محدود، Schema صریح و معنا سمت Server
پیش از Parse، Content-Type و Encodingهای پشتیبانیشده را Allowlist کنید. Methodهای تعریفنشده باید رد شوند. Schema فقط نوع را نسنجد؛ طول، Range، Format، تعداد، رابطه فیلدها و Unknown property را هم قرارداد کند. Normalize باید یک بار و پیش از Validation/Authorization انجام شود تا دو لایه برداشت متفاوت نداشته باشند.
- Query و Command پایگاه داده Parameterized باشد؛ Escape عمومی جای Context-specific encoding و Parameterization را نمیگیرد.
- نام فایل، MIME اعلامی و Extension را قابلاعتماد فرض نکنید؛ نوع واقعی و مسیر ذخیره مستقل بررسی شوند.
- قیمت، تخفیف، وضعیت، Tenant، Role و Owner از Client پذیرفته نشوند؛ Server آنها را از Context و داده معتبر بسازد.
- اعداد فارسی/عربی،
۰۹...و+98...، فاصله و نیمفاصله را طبق قرارداد Locale تبدیل کنید؛ چند Normalization متفاوت میتواند دورزدن یا Duplicate بسازد. - خطای Validation باید قابلعمل باشد، اما Stack trace، SQL، Secret یا تفاوتی که Enumeration بسازد افشا نکند.
Endpointهای URLمحور را برای SSRF طراحی کنید
Webhook tester، Import from URL، دریافت تصویر، PDF generator، Link preview و Callback validator میتوانند Server را وادار کنند به مقصد انتخابی مهاجم درخواست بفرستد. Regex روی رشته URL یا Block کردن localhost کافی نیست؛ Redirect، DNS rebinding، IP notation، IPv6، Credential در URL و شبکه Metadata باید در Threat model باشند.
- اگر ممکن است مقصد را از شناسه Server-side انتخاب کنید، نه URL آزاد کاربر.
- Scheme، Host و Port را Parse و Canonicalize کنید؛ Allowlist مقصد بر Blocklist مقدم است.
- DNS را Resolve و هر IP خصوصی، Loopback، Link-local و شبکه داخلی ممنوع کنید؛ پس از Redirect دوباره بررسی کنید.
- Redirect خودکار، Cookie، Authorization header و Proxy محیط را پیشفرض خاموش کنید.
- Egress شبکه را محدود و سرویس Fetch را از Metadata و Control plane جدا کنید.
- اندازه پاسخ، زمان، تعداد Redirect و Content-Type را بودجهبندی کنید و Event ثبت کنید.
Idempotency و Concurrency: دوبار کلیک یک رخداد امنیتی هم هست
شبکه موبایل، Timeout، Retry کتابخانه، دوبار کلیک و Queue delivery میتوانند یک درخواست را تکرار کنند. مهاجم نیز همین ابهام را برای سفارش، انتقال، شارژ، Coupon یا Refund آزمایش میکند. RFC 9110 Methodهای Safe و Idempotent را تعریف میکند؛ POST ذاتاً Idempotent نیست، اما کاربرد میتواند با قرارداد مشخص آن را برای تکرار امن کند.
قرارداد Idempotency-Key
- کلید به Actor/Tenant، Operation و نسخه Payload Normalized Scope شود.
- ثبت کلید و اثر تجاری Atomic باشد؛ Check-then-act ساده Race دارد.
- Payload متفاوت با همان کلید Conflict صریح بدهد، نه نتیجه قبلیِ نامرتبط.
- TTL از پنجره Retry و ریسک کسبوکار مشتق و رفتار پس از انقضا مستند شود.
- پاسخ Replay از نظر Status و Body قراردادی باشد و Secret را دوباره افشا نکند.
- Idempotency جای Lock، Optimistic concurrency یا State machine را نمیگیرد.
برای Updateهای رقابتی، Version/ETag و Precondition مانع Last-write-wins ناخواسته میشود. برای موجودی یا Balance، invariant باید داخل Transaction یا Primitive سازگارِ Data store اعمال شود. تست با دو Request همزمان مهمتر از دو Request پشتسرهم است.
پاسخ، خطا و Cache را بخشی از مرز امنیت بدانید
GraphQL به Client امکان انتخاب Field میدهد، اما «ذاتاً» جلوی Excessive data exposure را نمیگیرد؛ Schema، Resolver authorization، Field-level policy و Complexity budget همچنان لازماند. در REST نیز ORM Entity را مستقیماً Serialize نکنید. خروجی باید از DTO صریح ساخته شود و Default برای فیلد جدید «عدم نمایش» باشد.
برای خطا میتوان از ساختار Problem Details در RFC ۹۴۵۷ الهام گرفت: نوع پایدار، عنوان قابلفهم، Status، شناسه رخداد و جزئیات امن. پیام عمومی برای Client و جزئیات تشخیصی Redacted در Telemetry جدا باشند. تفاوت خطا یا زمان پاسخ نباید وجود حساب، شماره، Coupon یا Object را ناخواسته آشکار کند.
| موضوع | قاعده | تست |
|---|---|---|
| Cache | داده خصوصی Cache عمومی نشود؛ Key/Vary شامل Context لازم باشد | پاسخ Alice پس از درخواست Bob دیده نشود |
| GET حساس | Secret و PII در URL/Query قرار نگیرد | Access log، History و Referrer بررسی شود |
| خطا | Stack/SQL/Path/Token افشا نشود | Malformed، timeout و dependency failure |
| Download | Authorization در لحظه دریافت و URL کوتاهعمر | Replay، user swap و expiry |
| Content | Media type، nosniff و filename امن | HTML/SVG یا CRLF تزریقی |
CORS و CSRF را با هم اشتباه نگیرید
CORS کنترل میکند کدام Origin در Browser اجازه خواندن پاسخ را دارد؛ سازوکار احراز هویت یا مجوز Server نیست و Client غیرمرورگری را متوقف نمیکند. Allow-origin باز همراه Credentials یا Reflection بیاعتبار Origin خطرناک است. Originهای لازم، Methodها و Headerها را محدود و پاسخ Cacheشونده را با Vary: Origin درست مدیریت کنید.
CSRF وقتی مهم است که Browser Credential را خودکار—مانند Cookie—همراه Request میفرستد. SameSite مناسب، CSRF token، Origin/Referer verification و منع State change روی GET را متناسب ترکیب کنید. ذخیره Token در JavaScript نیز مسئله XSS و سرقت Token را ایجاد میکند؛ هیچ انتخابی بدون Trade-off نیست.
TLS و Encryption لازماند، اما کافی نیستند
HTTPS داده را در مسیر تعریفشده محافظت میکند، به شرط اعتبار Certificate، تنظیم درست Client/Proxy و نبود Downgrade یا Termination ناامن. این کنترل مانع کاربر معتبرِ بدون مجوز، SSRF، Mass assignment یا افشای داده در Response نمیشود. در ارتباط سرویسبهسرویس، هویت Workload و Trust boundary را هم مشخص کنید؛ «شبکه داخلی» دلیل اعتماد نیست.
Encryption at rest اثر سرقت Disk یا Snapshot را کاهش میدهد، اما وقتی Application با همان Key داده را میخواند، مهاجم دارای دسترسی Application هم میتواند آن را بخواند. Key management، جداسازی دسترسی، Rotation، Backup و Audit تعیین میکنند Encryption چقدر مؤثر است. Secretها نباید در Repository، Image، URL، Log یا Client bundle باشند.
مرز API Gateway و WAF
Gateway برای Policyهای سراسری مانند Route inventory، TLS، اعتبار اولیه Token، Client quota، Request size و Telemetry نقطه خوبی است. بااینحال میتواند Dependency بحرانی، محل پیکربندی اشتباه یا هدف دورزدن باشد. Origin باید فقط از مسیرهای مجاز قابلدسترسی باشد و Policy میان Gateway و Application ناسازگار نشود.
WAF میتواند الگوهای شناختهشده، Bot و بخشی از Payloadهای مخرب را در لبه کاهش دهد؛ مالک مجوز شیء، invariant تراکنش یا Business abuse نیست. برای انتخاب و Test policy، راهنمای فایروال و WAF سایت را ببینید. معیار خوب فقط Block count نیست؛ False positive، Bypass، Latency و زمان واکنش هم مهماند.
پاسخ API ثالث را ورودی غیرقابلاعتماد بدانید
API پرداخت، پیامک، نقشه، CRM یا هوش مصنوعی خارج از Trust boundary شماست. HTTPS و قرارداد تجاری، Schema یا محتوا را قابلاعتماد نمیکند. Timeout، Retry، Signature callback، Source authenticity، Schema validation، Response size، Redirect، HTML/Markdown خروجی و Dependency compromise باید کنترل شوند.
- Callback درگاه را فقط از روی Redirect مرورگر موفق ندانید؛ نتیجه را Server-to-server تأیید و مبلغ، سفارش، وضعیت و یکتایی را تطبیق دهید.
- Signature Webhook را روی Raw body و الگوریتم قراردادی بررسی کنید؛ Timestamp/Replay window و Secret rotation داشته باشید.
- پاسخ Third-party را پیش از SQL، Template، Command، URL fetch یا Log کردن Validate و Contextually encode کنید.
- Circuit breaker و Timeout را با Idempotency و Reconciliation بسازید تا «نامشخص» به Duplicate تبدیل نشود.
همه Request و Response را لاگ نکنید
لاگ کامل میتواند Access token، Cookie، رمز، OTP، شماره کارت، آدرس، فایل و داده سلامت را به مخزن ثانویهای با دسترسی گسترده تبدیل کند. ابتدا Event schema را تعریف کنید و Data minimization را پیشفرض بگیرید. Debug logging زماندار و محدود با Audit trail دائمی یکی نیست.
| ثبت شود | ثبت نشود یا Redact شود | دلیل |
|---|---|---|
| timestamp، endpoint_id/version، outcome، latency | Body کامل پیشفرض | عملیات بدون Data lake حساس |
| subject/tenant pseudonymous، authn assurance | Token، Cookie، API key | Trace تصمیم بدون Credential leakage |
| policy_id/version و authz result | PII خام مگر ضرورت مستند | توضیحپذیری و کمینهسازی |
| correlation/request/idempotency reference | Secret، OTP، CVV، password | Reconciliation امن |
| resource-budget class و throttle reason | Query string حساس | تشخیص Abuse بدون افشا |
Retention، دسترسی، Integrity، Clock، منطقه زمانی و حذف باید مالک داشته باشند. در ایران، ثبت شماره موبایل کامل یا متن پیامک برای Debug میتواند بیش از نیاز داده تولید کند؛ شناسه پایدار کمریسک، Masking و دسترسی محدود معمولاً مفیدتر است.
Observability امنیتی را به Outcome وصل کنید
افزایش ۴۰۱ لزوماً حمله نیست و کاهش آن نیز سلامت را ثابت نمیکند. Signalها را با Endpoint، Actor class، Tenant، Outcome و Baseline تفکیک کنید. داشبورد حداقلی میتواند نرخ ۲xx/۴xx/۵xx، P50/P95/P99، Rejectهای Authn/Authz، Resource limit، Idempotency replay/conflict، Dependency failure و Business outcome را نشان دهد.
Alert باید Owner، Threshold/Anomaly، پنجره، Severity و لینک Runbook داشته باشد. برای طراحی SLI، Trace و هشدار قابلعمل به راهنمای Observability و مانیتورینگ مراجعه کنید. Sampling نباید رخداد مالی یا تغییر مجوز را گم کند؛ در مقابل، Telemetry بیشازحد هم هزینه و ریسک حریم خصوصی میسازد.
ماتریس تست پذیرش امنیت Endpoint
Happy path فقط ثابت میکند یک درخواست مجاز گاهی کار میکند. تست امنیت باید تغییر کوچک در Actor، Object، Property، State، زمان، اندازه، ترتیب و وابستگی را پوشش دهد. هر Test case ورودی، Precondition، Expected status/body/side effect، Audit event و Cleanup دارد.
| خانواده تست | نمونهها | قبولی |
|---|---|---|
| Authentication | بدون Token، منقضی، aud/iss غلط، alg نامجاز، key قدیمی | رد یکنواخت؛ بدون Side effect یا Leak |
| Authorization | Alice/Bob، Tenant swap، Role downgrade، Field injection | Function/Object/Property/State دقیق اعمال شود |
| Schema | Unknown field، Type confusion، Unicode، عمق/طول مرزی | Parse محدود و Error قراردادی |
| Resource | Body/Array/Page/Query/File/Burst/Concurrency | بودجه در هر لایه و بدون Collapse پاییندست |
| Business abuse | OTP/Coupon/Reserve/Refund/Export با Velocity متفاوت | Abuse کم و Recovery کاربر واقعی حفظ شود |
| Replay/Race | کلید یکسان/متفاوت، Payload متفاوت، ۲۰ Request همزمان | یک اثر قطعی، Conflict درست، Reconciliation ممکن |
| SSRF/Upload | Private IP، redirect، DNS change، polyglot، archive | Egress/Type/size/time محدود |
| Browser/Cache | Origin مخرب، CSRF، cache cross-user | هیچ خواندن/نوشتن یا نشت میان کاربر رخ ندهد |
| Dependency | timeout، ۴۲۹، پاسخ malformed، callback تکراری | Retry محدود، State معلوم/قابلتطبیق، بدون Duplicate |
| Telemetry | هر Failure بالا | Event کافی بدون Secret/PII ناموجه |
ماتریس Alice/Bob/Admin
Case Actor Object owner Property State Expected
A1 Alice Alice public fields paid 200
A2 Alice Bob public fields paid deny
A3 Admin Bob support fields paid policy-dependent
A4 Admin Bob secret fields paid deny by default
A5 Alice Alice unit_price draft ignore/reject; server-owned
A6 Alice Alice cancel shipped conflict/deny
A7 Alice Alice refund refunded idempotent result/no duplicateتستها باید علیه Policy واقعی و Data fixture چند Tenant اجرا شوند. Status code یک انتخاب قراردادی است؛ مهمتر این است که هیچ Side effect، تفاوت قابلسوءاستفاده یا Audit gap ایجاد نشود.
چه چیزی را در CI/CD خودکار کنیم؟
Contract test برای Method/Schema/Error، تست مجوز با Fixture، Dependency scanning، SAST، Secret scanning و تستهای Race منتخب را در Pipeline قرار دهید. DAST و Fuzzing برای کلاسهایی از ورودی مفیدند، اما Context مالکیت و منطق Refund را از روی URL کشف نمیکنند. اسکن سبز باید یک شاهد در کنار Review و تست باشد، نه Gate یگانه.
NIST SSDF 1.1 توصیههای توسعه امن را در SDLC ادغام میکند؛ برای پیوند کنترلها با Build، Artifact، Provenance و Rollback نیز راهنمای CI/CD امن را ببینید.
| Gate | شاهد | قاعده شکست |
|---|---|---|
| Contract | OpenAPI/Schema diff و compatibility | Field/permission جدید بدون Review |
| Authorization | ماتریس Actor/Object/Property/State | هر دسترسی نامجاز یا Fixture ناقص |
| Resource | Boundary/load test کنترلشده | نبود سقف یا SLO breach شدید |
| Supply chain | SCA/SBOM/Provenance و Policy | Risk خارج از SLA یا Artifact ناشناخته |
| Runtime | Canary metric، alert و rollback probe | Telemetry/Runbook/rollback نامعتبر |
Inventory، نسخه و حذف Endpoint
Endpoint فراموششده همانقدر خطر دارد که Endpoint جدید. Routeهای Production را با Spec، Gateway، Code و Traffic تطبیق دهید. برای هر نسخه Owner، Consumer، Data class، Auth policy، تاریخ آخرین استفاده، Deprecation و Sunset ثبت کنید. نسخه قدیمی بدون Monitor و مهلت حذف، Shadow API میشود.
- Spec با Runtime route مقایسه و اختلاف Alert شود.
- Environmentهای Test، Admin، Debug و Management از اینترنت عمومی جدا یا همسطح Production محافظت شوند.
- نسخه منسوخ ابتدا Usage measurement و Consumer notification، سپس محدود و در نهایت حذف شود.
- Secret و Credential مربوط به Consumer بازنشسته Rotate یا Revoke شود.
- پس از حذف، Route و DNS/Proxy rule واقعاً ۴۰۴/۴۱۰ دهند و Backend دورزدنی باقی نماند.
ملاحظات عملی برای API در ایران
کنترل جهانی است، اما سناریوی قبولی باید شرایط واقعی مصرفکننده ایرانی را پوشش دهد. شبکه ناپایدار و تغییر IP میتواند Retry و Request تکراری را بیشتر کند؛ راهحل، حذف سقف یا اعتماد به IP نیست، بلکه Idempotency، Timeout روشن و UX وضعیت نامشخص است. تاریخ و پول نیز باید Contract صریح داشته باشند.
| موضوع | ریسک رایج | قرارداد پیشنهادی |
|---|---|---|
| موبایل | ۰۹، +۹۸، +۹۸ و رقم فارسی هویت تکراری میسازند | Canonical form، نمایش Masked، Rate چندبعدی |
| OTP پیامکی | هزینه، تأخیر، Enumeration و Retry | Cooldown/expiry/attempt budget، تحویل غیرقطعی، Recovery |
| ریال/تومان | خطای دهبرابری و دستکاری amount | Minor unit/واحد صریح، amount سمت Server، نمایش شفاف |
| درگاه | Redirect موفق کاذب، callback تکراری یا مبهم | Verify سمت Server، تطبیق amount/order، state machine، reconciliation |
| تاریخ | تفاوت شمسی/میلادی و Asia/Tehran/UTC | Timestamp استاندارد در API، Locale در نمایش، timezone صریح |
| شبکه/VPN | IP مشترک یا متغیر و False positive | Risk چندسیگنالی، Step-up و مسیر بازیابی |
| سرویس خارجی | Eligibility، تحریم، Billing یا قطع ناگهانی | بررسی شرایط رسمی، جایگزین قانونی، Export و Failover تمرینشده |
هیچ کنترل امنیتی نباید تیم را به هویت جعلی، دورزدن شرایط سرویس یا وابستگی پنهان سوق دهد. Eligibility، محل داده، شرایط پرداخت و امکان خروج را پیش از انتخاب Provider بررسی و Snapshot تصمیم را تاریخدار نگه دارید.
چهار Runbook حداقلی
۱. نشت Token یا API Key
Signal و Scope را تأیید کنید، Credential را Revoke/Rotate و مسیر انتشار را ببندید، Tokenهای مرتبط و Sessionها را متناسب منقضی کنید، دسترسیهای انجامشده را با Audit کمینه بررسی و Consumer را از مسیر امن مطلع کنید. Rotate بدون رفع Source leak فقط حادثه را تکرار میکند.
۲. مشاهده BOLA یا BOPLA
Endpoint/Version و Data class را مشخص، دسترسی آسیبپذیر را با Feature flag یا Policy محدود، شواهد را بدون گسترش Exposure حفظ و Query/Authorization root cause را اصلاح کنید. سپس همه Endpointهای الگوی مشابه و Serializerهای مشترک را جستوجو، داده در معرض را Scope و Retest مستقل انجام دهید.
۳. Abuse جریان تجاری
بهجای Block سراسری IP، Actor/Device/Target/Velocity و هزینه را بخشبندی کنید. Threshold یا Queue را موقت تنظیم، مسیر کاربر واقعی و Support را حفظ، Accountهای درگیر و وابستگی پیامک/پرداخت را کنترل و پس از رخداد Policy را با داده False positive بازتنظیم کنید.
۴. اختلال یا Compromise سرویس ثالث
فراخوانی را محدود یا Circuit را باز، Credential ثالث را Rotate، داده ورودی/خروجی و Side effectهای نامشخص را Reconcile، Alternate path قانونی را فعال و Consumer را با وضعیت دقیق آگاه کنید. پس از بازیابی، Backlog را با Idempotency پردازش و Retry storm نسازید.
برنامه ۳۰، ۶۰ و ۹۰روزه
| بازه | کار | Definition of Done |
|---|---|---|
| روز ۱ تا ۳۰ | Inventory، انتخاب ۱۰ Endpoint پرریسک، قرارداد و ماتریس مجوز | Owner/Data class/Policy/Budget/Test برای ۱۰ مورد ثبت شده |
| روز ۳۱ تا ۶۰ | اصلاح Authz/DTO/Idempotency، تست منفی و Telemetry | Gateهای اصلی سبز و Dashboard/Alert با Runbook متصل |
| روز ۶۱ تا ۹۰ | تست نفوذ هدفمند، Game day، حذف نسخه قدیمی و تعمیم Template | Retest بسته، رخداد تمرینی پاسخ داده و Coverage گزارش شده |
ریسک را با تعداد کنترلها نسنجید. معیارهای بهتر شامل درصد Endpointهای پرریسک با قرارداد و Owner، پوشش ماتریس مجوز، زمان بستن یافته تا Retest، نرخ Duplicate مالی، درصد Eventهای بدون Secret، زمان تشخیص و مهار و تعداد نسخههای بدون مصرف اما فعالاند.
چکلیست انتشار Endpoint
- Method، Path، Version، Consumer، Owner، Data class و اثر تجاری ثبت شدهاند.
- Authentication نوع Credential، Issuer/Audience/Lifetime/Rotation/Revocation روشن دارد.
- Function، Object، Property و Business-state authorization جداگانه تست شدهاند.
- Input DTO صریح است و فیلدهای Server-owned از Client پذیرفته نمیشوند.
- Body، Parse، Query، File، Page، Concurrency و Downstream بودجه دارند.
- Business abuse با Rate چندبعدی و Guardrail تجربه کاربر پوشش یافته است.
- SSRF، Upload، Injection، CORS/CSRF، Cache و Error متناسب بررسی شدهاند.
- Idempotency، Race، Retry، Timeout و وضعیت نامشخص تست شدهاند.
- Response model فقط فیلدهای مجاز را میسازد و Default فیلد جدید Deny است.
- Log و Trace بدون Token/Secret/PII ناموجهاند و Retention/Access دارند.
- وابستگی ثالث Validate، Timeout و Reconciliation دارد.
- تست منفی در CI و تست مستقل متناسب با ریسک برنامهریزی شده است.
- Dashboard، Alert، Runbook، Rollback و Owner کشیک قابلآزمایشاند.
- Runtime route با Inventory/Spec منطبق و Deprecation تاریخدار است.
پرسشهای متداول
آیا API Gateway بهتنهایی Endpoint را امن میکند؟
خیر. Gateway برای TLS، Route، بررسی اولیه Credential، Quota و Telemetry مشترک مفید است، اما معمولاً مالک رابطه کاربر با رکورد، مجوز فیلد و وضعیت کسبوکار نیست. این تصمیمها باید در سرویس و نزدیک داده هم اعمال و تست شوند.
برای امنیت API، JWT بهتر است یا Session؟
پاسخ مطلق وجود ندارد. Consumer، Threat model، Revocation، Storage، CSRF/XSS، مقیاس و معماری تعیینکنندهاند. JWT اگر Signature، الگوریتم، Issuer، Audience، زمان، Key rotation و نوع Token درست اعتبارسنجی نشوند، صرفاً یک رشته قابلحمل است.
تفاوت BOLA و BOPLA چیست؟
BOLA درباره مجوز روی یک Object مشخص است؛ مثلاً کاربر سفارش فرد دیگری را با تغییر شناسه میبیند. BOPLA درباره Fieldهاست؛ مثلاً کاربر فیلد نقش یا قیمت را تغییر میدهد یا پاسخ، فیلد محرمانه را افشا میکند. یک Endpoint میتواند همزمان هر دو نقص را داشته باشد.
Rate limiting را بر اساس IP تنظیم کنیم؟
IP فقط یکی از سیگنالهاست. در شبکه موبایل، NAT و VPN ممکن است چند کاربر یک IP یا یک کاربر IPهای متعدد داشته باشند. Subject، Tenant، Credential، Device، Target، Action، Cost و Velocity را ترکیب کنید و مسیر بازیابی کاربر واقعی را بسنجید.
حداقل تست امنیتی پیش از انتشار Endpoint چیست؟
علاوه بر Happy path، Token نامعتبر، Alice/Bob/Tenant swap، فیلد اضافی، State نامجاز، ورودی مرزی، Request همزمان و تکراری، Timeout وابستگی، Cache cross-user و Redaction لاگ را تست کنید. برای Endpoint مالی یا داده حساس، تست نفوذ مستقل و Game day رخداد هم متناسب است.
جمعبندی
امنیت Endpoint محصول نصب یک Gateway، WAF یا فرمت Token نیست. نقطه شروع یک قرارداد قابلتست است: چه Subjectی، روی کدام Object و Property، در چه State و با چه بودجهای میتواند چه اثر تجاریای ایجاد کند. سپس Authentication، Authorization، Schema، Abuse control، SSRF، Idempotency، Response، Telemetry و Runbook باید همان قرارداد را در Runtime حفظ کنند.
از ده Endpoint پرریسک شروع کنید. برای هرکدام ماتریس Alice/Bob/Admin و بودجه منابع بسازید، Race و Failure را واقعاً اجرا کنید و شواهد را به CI و Observability وصل کنید. هدف «صفر خطا» یا «اسکن سبز» نیست؛ هدف این است که تصمیم دسترسی درست، اثر جانبی محدود، شکست قابلبازیابی و رخداد قابلمهار باشد.






