چگونه REST API امن بسازیم؟
چرا بسیاری از APIها در اولین تست نفوذ شکسته میشوند و چطور میتوانید از همان ابتدا، لایهای از امنیت را در طراحی REST API خود جای دهید؟ راهنمای عملی بر پایه تجربه واقعی
یک بار روی پروژهای کار میکردم که API آن در تست نفوذ اول، دو آسیبپذیری جدی نشان داد: یکی از مسیرها بدون احراز هویت به داده مشتریان دسترسی میداد و مسیر دیگری بهخاطر نبود محدودسازی نرخ، در یک دقیقه قابل حمله بود. تیم توسعه تصور میکرد چون API پشت HTTPS است و توکن JWT دارد، امن است. اما امنیت REST API از جنس لایههای روی هم است، نه یک لایه واحد. آن پروژه باعث شد در همه پروژههای بعدی، از همان مرحله طراحی، یک چکلیست امنیتی را روی APIها اعمال کنم.
REST API دقیقاً چیست و چرا امنیتش پیچیده است؟
اگر با مفهوم کلی آشنا نیستید، پیشنهاد میکنم ابتدا REST API چیست و اصول طراحی REST API را بخوانید. اما در یک جمله: REST API واسطی است که به برنامههای دیگر اجازه میدهد با دادههای شما کار کنند. همین واسطه بودن، امنیت را پیچیده میکند، چون API نه فقط کاربران انسانی، بلکه برنامهها و سرویسهای خودکار را هم میپذیرد. هر端点ی که برای یک برنامه باز است، میتواند هدف یک مهاجم هم باشد.
چهار ویژگی که REST APIها را از یک سایت معمولی متفاوت میکند:
- داده ماشینخوان: پاسخ APIها معمولاً JSON است و میتواند شامل دادههای حساس باشد که در یک سایت نمایش داده نمیشود.
- بدون حالت: برخلاف نشستهای مرورگر، APIها معمولاً بدون حالت کار میکنند و همین، احراز هویت را چالشبرانگیزتر میکند.
- مقیاسپذیری: APIها معمولاً در مقیاس بالاتر از یک سایت استفاده میشوند و همین، بردار حمله را گستردهتر میکند.
- دسترسی مستقیم به داده: هر آسیبپذیری در API میتواند به معنای دسترسی مستقیم به دیتابیس باشد.
امنیت REST API از جنس لایههای روی هم است، نه یک دیوار واحد. اگر هر لایه بهدرستی طراحی نشود، یک نقطه ضعف کوچک میتواند تمام لایههای دیگر را بیاثر کند.
تهدیدهای اصلی که REST APIها را هدف میگیرند
پیش از ورود به راهحلها، فهرست تهدیدهای رایج را مرور کنیم. آشنایی با اینها، در طراحی امنیت بسیار کمک میکند. مبانی کامل این تهدیدها را در امنیت وب چیست و چه اصولی دارد باز کردهام.
- Broken Authentication: ضعف در احراز هویت، مثل توکنهای بدون انقضا یا قابل حدس.
- Broken Object Level Authorization: دسترسی کاربر A به داده کاربر B، بهخاطر نبود بررسی مالکیت.
- Excessive Data Exposure: بازگرداندن داده بیش از نیاز، مثل نمایش تمام فیلدهای کاربر به همه.
- Lack of Rate Limiting: نبود محدودیت درخواست، که به حملات Brute Force، DDoS و سوءاستفاده منجر میشود.
- Injection Attacks: حملات تزریق مثل SQL Injection و XSS، که در API هم وجود دارند.
- Improper Assets Management: نبود نسخهبندی درست و باقیماندن endpointهای قدیمی.
- Mass Assignment: امکان تخصیص فیلدهای ناخواسته توسط کاربر (مثل کاربری که خودش را admin میکند).
- Server-Side Request Forgery (SSRF): سوءاستفاده از سرور برای ارسال درخواست به منابع داخلی.
فهرست بالا، منبع اصلی من در طراحی امنیتی است. اگر طراحی API شما در برابر هر یک از این تهدیدها پاسخ مشخصی دارد، در مسیر درستی هستید.
احراز هویت؛ بنیاد امنیت API
نخستین لایه امنیت، شناخت این است که چه کسی درخواست میدهد. تفاوت احراز هویت و مجوزدهی را در تفاوت احراز هویت و مجوزدهی چیست باز کردهام. سه روش رایج احراز هویت در API:
API Key
سادهترین روش، مناسب برای APIهای داخلی. هر کلید به یک برنامه اختصاص مییابد. اما این روش، هویت کاربر را مشخص نمیکند و برای APIهای عمومی کافی نیست.
OAuth 2.0
استاندارد صنعتی برای احراز هویت سومشخص. اگر API شما را میخواهید به برنامههای دیگر متصل کنید، OAuth انتخاب درستی است. توضیح کامل در OAuth چیست و چگونه کار میکند.
JWT (JSON Web Token)
روش محبوب احراز هویت بدون حالت. توکن در هر درخواست ارسال میشود. مهمترین نکته امنیتی: توکنهای JWT باید کوتاهمدت باشند و با refresh token تمدید شوند. تفصیل در JWT چیست و چه کاربردی در احراز هویت دارد.
توصیههای عملی که در همه پروژهها رعایت میکنم:
- توکنهای کوتاهمدت: طول عمر توکن دسترسی را حداکثر ۱۵ دقیقه در نظر بگیرید.
- Refresh Token جداگانه: برای تمدید، از توکن جداگانه با انقضای بلندتر استفاده کنید.
- ذخیره امن کلیدها: کلیدهای JWT و APIها را در متغیرهای محیطی نگه دارید، نه در کد.
- عدم ارسال توکن در URL: توکن باید در هدر
Authorizationباشد، نه در query parameter.
مجوزدهی؛ تفاوت حیاتی با احراز هویت
شایعترین خطای امنیتی در APIها، اشتباه گرفتن احراز هویت با مجوزدهی است. احراز هویت میگوید «شما چه کسی هستید»، مجوزدهی میگوید «شما اجازه چه کاری را دارید». در پروژههای واقعی، این اشتباه باعث شده که کاربر A به داده کاربر B دسترسی پیدا کند — یکی از جدیترین آسیبپذیریهای API.
سه اصل در طراحی مجوزدهی:
- کنترل در سطح شیء (Object Level): برای هر درخواست، بررسی کنید که آیا کاربر مجاز به دسترسی به این شیء خاص است. مثلاً
GET /orders/123باید بررسی کند که آیا سفارش ۱۲۳ به کاربر درخواستدهنده تعلق دارد یا نه. - کنترل در سطح عمل (Action Level): بررسی کنید که کاربر مجاز به انجام این عمل است. مثلاً کاربر عادی نباید بتواند محصول حذف کند.
- کنترل در سطح فیلد (Field Level): بعضی فیلدها مثل
roleیاis_adminنباید از طریق API تغییر داده شوند، حتی توسط کاربران معتبر. این مفهوم با عنوانMass Assignmentشناخته میشود.
اعتبارسنجی و پاکسازی ورودی
هر دادهای که از API میآید، باید بهعنوان داده غیرقابلاعتماد در نظر گرفته شود. این اصل در طراحی امن وب بنیادی است. سه لایه اعتبارسنجی:
- اعتبارسنجی نوع: درخواستهای غیرمنطبق با schema رد شوند. اگر فیلد
ageباید عدد باشد، درخواست با مقدار"hello"رد شود. - اعتبارسنجی محدوده: مقادیر باید در محدوده معقول باشند. مثلاً
ageنمیتواند منفی یا بیش از ۱۵۰ باشد. - اعتبارسنجی معنایی: مقدار باید با قوانین کسبوکار منطبق باشد. مثلاً ارسال ایمیل تکراری در ثبتنام، باید رد شود.
در لایه دیتابیس هم برای جلوگیری از SQL Injection حتماً از Prepared Statements استفاده کنید. اگر با این مفهوم آشنا نیستید، جلوگیری از SQLi با Prepared Statements راهنمای کامل است. برای جلوگیری از XSS هم در خروجیها پاکسازی مناسب انجام دهید. راهنمای امنیتی در جلوگیری از XSS در برنامههای وب.
محدودسازی نرخ و محافظت از منابع
یک API بدون محدودسازی نرخ، مانند دری است که هر کسی میتواند در آن بکوبد. سه لایه محدودسازی:
- Rate Limiting عمومی: حداکثر N درخواست در دقیقه برای هر کاربر. مثلاً ۶۰ درخواست در دقیقه.
- Rate Limiting اختصاصی: برای endpointهای حساس مثل ورود و فراموشی رمز، محدودیت سختگیرانهتر (مثلاً ۵ درخواست در ۱۰ دقیقه).
- پایش ناهنجاری: الگوهای مشکوک مثل درخواستهای پشتسرهم از IP یکسان، باید بهطور خودکار محدود شوند.
پاسخ مناسب هنگام عبور از حد مجاز، کد 429 Too Many Requests با هدر Retry-After است. سرویسهای بیرونی مثل Cloudflare و AWS WAF میتوانند این لایه را در سطح زیرساخت ارائه دهند. جزئیات مربوط به لایههای امنیتی سرور در فایروال ابری در مقابل فایروال سنتی و فایروال نرمافزاری در سرور آمده است.
HTTPS و هدرهای امنیتی
API امن، فقط با HTTPS میگذرد. این پیشنیاز است. اما در کنار HTTPS، هدرهای امنیتی نقش مهمی دارند:
- Strict-Transport-Security (HSTS): مرورگر را مجبور میکند در تمام تعاملات بعدی از HTTPS استفاده کند.
- Content-Security-Policy (CSP): در API، این هدر کماستفاده است اما در پاسخهای HTML مفید است.
- X-Content-Type-Options: nosniff: جلوگیری از تفسیر اشتباه محتوای پاسخ.
- Cache-Control: در پاسخهای حاوی داده حساس، مقدار
no-storeرا تنظیم کنید.
راهنمای کامل هدرهای امنیتی در هدرهای امنیتی HTTP چه کاربردی دارند. برای HTTPS، حتماً گواهی SSL معتبر داشته باشید. تفاوت انواع گواهی در گواهی SSL رایگان و پولی چه تفاوتی دارند.
محافظت از داده حساس در پیامها
یکی از بزرگترین اشتباهات، بازگرداندن داده بیش از نیاز است. سه اصل در طراحی پاسخ API:
- حداقل داده (Data Minimization): فقط دادهای که کاربر نیاز دارد بازگردانده شود. مثلاً API کاربر، نباید فیلد
password_hashرا بازگرداند. - عدم افشای ساختار داخلی: خطاها نباید شامل جزئیات داخلی مثل نام جدول یا مسیر فایل باشند.
- رمزنگاری در سطح فیلد: دادههای حساس مثل شماره کارت بانکی، حتی در دیتابیس هم باید رمزنگاری شوند.
یک عادت که در همه پروژهها به آن پایبندم: پیش از انتشار API، فهرست تمام فیلدهای هر پاسخ را بازبینی میکنم و سوال میپرسم «آیا این فیلد برای مصرفکننده ضروری است؟». اگر نه، حذف میشود. همین قاعده ساده، جلوی بسیاری از افشاهای ناخواسته را میگیرد.
لاگگیری، پایش و پاسخ به حادثه
امنیت API بدون پایش، نابیناست. سه لایه لاگگیری که در همه پروژهها فعال میکنم:
- لاگ دسترسی: هر درخواست با اطلاعات کلیدی (IP، توکن، endpoint، پاسخ) ثبت شود. این لایه اولین مکان بررسی در حادثه است.
- لاگ خطاهای امنیتی: تلاشهای ناموفق احراز هویت، خطاهای مجوزدهی و درخواستهای مشکوک، جداگانه ثبت شوند.
- لاگ عملکرد: زمان پاسخ، نرخ خطا و رفتار غیرمعمول، برای شناسایی حملات DoS و ناهنجاریها.
دادههای حساس مثل توکنها و رمزها نباید در لاگها نوشته شوند. در پروژهای دیدم که توکنهای JWT در لاگهای سرور ذخیره میشدند و در صورت افشای لاگ، تمام احراز هویت API قابل نفوذ بود. راهنمای کامل در چگونه لاگ حملات سایت را بررسی کنیم.
تست نفوذ و ابزارهای ارزیابی امنیت API
پس از طراحی امن، لایه مهمتر تست نفوذ است. ابزارهایی که در پروژهها استفاده کردهام:
- Postman و Insomnia: برای تست دستی endpointها با سناریوهای مختلف. مقایسه در Postman یا Insomnia.
- OWASP ZAP: ابزار متنباز تست امنیت وب که APIها را هم پوشش میدهد.
- Burp Suite: ابزار حرفهای تست نفوذ با پشتیبانی از APIها.
- k6 و JMeter: برای تست بار و کشف ناهنجاریهای عملکردی.
- Snyk و ابزارهای مشابه: برای بررسی امنیتی وابستگیها و پکیجهای استفادهشده.
تست نفوذ را در محیط استیجینگ انجام دهید، نه در تولید. اصول کلی تست امنیت وب در تست امنیت وبسایت چگونه انجام میشود آمده است.
جدول خلاصه؛ لایههای امنیت REST API
| لایه | اقدام کلیدی | ابزار یا روش |
|---|---|---|
| احراز هویت | توکن کوتاهمدت + Refresh | JWT، OAuth 2.0 |
| مجوزدهی | کنترل در سطح شیء و فیلد | RBAC، ABAC |
| اعتبارسنجی | Schema و محدوده | JSON Schema، Validators |
| محدودسازی نرخ | درخواست در دقیقه | Middleware یا WAF |
| انتقال امن | HTTPS + هدرها | SSL، HSTS |
| داده حساس | حداقل داده، رمزنگاری | Data Minimization |
| پایش | لاگ ساختاریافته + هشدار | Sentry، ELK |
| تست | نفوذ در استیجینگ | OWASP ZAP، Burp |
اشتباهاتی که امنیت REST API را نابود میکند
- اعتماد به HTTPS بهعنوان کافی: HTTPS فقط انتقال امن را تضمین میکند، نه احراز هویت و مجوزدهی.
- نبود بررسی مالکیت: یکی از شایعترین آسیبپذیریهای API. همیشه بررسی کنید که کاربر مجاز به دسترسی به این منبع خاص است.
- خطاهای پرمحتوا: خطاهایی که جزئیات داخلی سیستم را فاش میکنند، راهنمای خوبی برای مهاجمان هستند.
- توکنهای طولانیمدت: توکنی که سال دیگر هم کار کند، خطر بزرگی است.
- کلیدهای API در مخزن کد: کلیدها باید در متغیرهای محیطی باشند.
- نبود محدودسازی نرخ: اجازه حمله Brute Force روی endpoint ورود.
- Mass Assignment: اجازه دادن به کاربر برای ارسال فیلدهای غیرمجاز.
- نبود نسخهبندی: endpointهای قدیمی باقی میمانند و به فراموشی سپرده میشوند.
- عدم پایش: حملات فقط در زمان بحران کشف میشوند.
نگاه فراتر از احراز هویت: API بهعنوان مرز اعتماد
برای معماران پلتفرم و تیمهای فنی، REST API نباید بهعنوان یک سری endpoint دیده شود؛ بلکه یک مرز اعتماد (Trust Boundary) است که دو حوزه امنیتی را جدا میکند. در این نگاه، سه الگوی معماری ارزشمند است:
- جداسازی API عمومی از API داخلی: در پروژههای بزرگ، دو لایه API وجود دارد: یکی برای مصرفکنندگان خارجی (پارتنرها، موبایل) و یکی برای سرویسهای داخلی. این جداسازی، سطح حمله را کاهش میدهد و هر لایه میتواند سیاست امنیتی متفاوتی داشته باشد.
- الگوی Zero Trust: در معماری مدرن، اعتماد کامل به هیچ لایهای نمیشود. حتی سرویسهای داخلی باید با توکن به هم درخواست بدهند. این رویکرد، در برابر نفوذ داخلی مقاومتر است و در پروژههای سازمانی توصیه میشود.
- پایش و پاسخ خودکار: در معماری پرمعامله، کشف و پاسخ به حمله باید خودکار باشد. ابزارهایی مثل WAF و ابزارهای SIEM میتوانند در لحظه واکنش نشان دهند.
- نسخهبندی بهعنوان بخشی از امنیت: APIهای بدون نسخهبندی، بهسرعت به کدهای قدیمی آلوده میشوند. راهنمای نسخهبندی در نسخهبندی REST API.
در این نگاه، امنیت API یک لایه نقطهای نیست؛ یک ویژگی معماری است که در تمام طول عمر پروژه با آن زندگی میکند. برای دیدن تصویر کامل این نگاه در پروژههای وب، معماری مونولیتیک یا میکروسرویس و امنیت بکاند چه نکاتی دارد مکملهای خوبی هستند.
پرسشهای پرتکرار
آیا HTTPS کافی است برای امنیت REST API؟ نه. HTTPS فقط انتقال را امن میکند. احراز هویت، مجوزدهی، اعتبارسنجی و محدودسازی نرخ لایههای دیگر هستند.
JWT یا Session، کدام بهتر است؟ برای APIهای بدون حالت، JWT. برای سایتهای سنتی با کوکی، Session. تفصیل مقایسه در JWT چیست.
چطور از Mass Assignment جلوگیری کنم؟ با تعریف صریح فیلدهای مجاز (Whitelist) و رد کردن هر فیلد غیرمجاز. در فریمورکها معمولاً این قابلیت بهصورت بومی وجود دارد.
چند درخواست در دقیقه برای Rate Limiting مناسب است؟ بسته به API شما متفاوت است. برای endpointهای عمومی ۶۰ در دقیقه نقطه شروع خوبی است. برای endpointهای حساس مثل ورود، ۵ در ۱۰ دقیقه.
آیا باید همه APIها احراز هویت داشته باشند؟ نه، بعضی APIها عمومی هستند. اما هر API که داده کاربر را میخواند یا تغییر میدهد، باید احراز هویت داشته باشد.
چطور بفهمم API من امن است؟ با تست نفوذ منظم و استفاده از چکلیستهای معتبر مثل OWASP API Security Top 10.
آیا استفاده از ابزارهای ابری برای محدودسازی نرخ کافی است؟ بهعنوان لایه اضافی بله، اما نباید جایگزین لایه درونبرنامهای شود. اگر مهاجم از داخل شبکه شما حمله کند، ابزار بیرونی نمیتواند کمک کند.
گفتار آخر
امنیت REST API، در نگاه اول مجموعهای از تکنیکهای فنی است؛ در باطن، یک نگرش معماری است که در تمام طول عمر پروژه با آن زندگی میکند. تجربهام نشان داده هر پروژهای که از روز اول امنیت را لایهای در طراحی دیده، در طول سالها هزینه نگهداری کمتری داشته. از احراز هویت و مجوزدهی تا محدودسازی نرخ و پایش مداوم، هر لایه در تجمیع، یک مرز اعتماد پویا میسازد که میتواند در برابر حملات متنوع مقاومت کند. سه اقدام که همین امروز پیشنهاد میکنم: اول، چکلیست لایههای امنیتی این مقاله را روی APIهای خود اعمال کنید؛ دوم، حتماً یک تست نفوذ در محیط استیجینگ اجرا کنید؛ سوم، پایش مداوم لاگها و هشدار خودکار را بهعنوان بخشی از سیستم در نظر بگیرید.
اگر تجربهای از امنیت REST API در پروژههای خودتان دارید — چه یک آسیبپذیری که در تست نفوذ پیدا کردید، چه یک راهکار خلاقانه برای مقابله با حمله — برای من و خوانندگان این سایت ارزشمند است که در دیدگاهها بخوانیم. بگویید در پروژه شما کدام لایه از امنیت REST API بیشترین تفاوت را ساخت و چرا؛ همان یک تجربه میتواند به خواننده بعدی که همین امروز در حال طراحی API است، چند هفته آزمونوخطا را صرفهجویی کند. 🔐