GraphQL قرار بود توسعه APIها را سادهتر و انعطافپذیرتر کند؛ اما اگر دسترسیها، ورودیها و محدودیت درخواستها بهدرستی پیادهسازی نشوند، همین انعطافپذیری میتواند اطلاعات حساس را در معرض خطر قرار دهد.
نکته مهم: در تست نفوذ GraphQL، هدف فقط پیدا کردن یک مسیر API نیست؛ باید بررسی کنیم کاربر دقیقاً به چه دادههایی دسترسی دارد، چه عملیاتی میتواند انجام دهد و آیا سرور محدودیتهای امنیتی را بهدرستی اعمال میکند یا نه.
۱. GraphQL چیست و چرا به تست امنیتی نیاز دارد؟
GraphQL یک زبان پرسوجو و محیط اجرایی برای دریافت و تغییر دادههاست. برخلاف REST که معمولاً چندین مسیر مشخص دارد، یک API مبتنی بر GraphQL ممکن است بیشتر درخواستها را از طریق یک نقطه ورودی مانند /graphql دریافت کند.
اجزای مهمی که در بررسی امنیتی با آنها سروکار داریم:
-
Schema: ساختار انواع دادهها و عملیات مجاز.
-
Query: دریافت اطلاعات.
-
Mutation: ایجاد، ویرایش یا حذف اطلاعات.
-
Resolver: کدی که درخواست را اجرا و داده را بازیابی میکند.
-
Authorization: بررسی اینکه کاربر اجازه دسترسی به داده یا انجام عملیات را دارد یا خیر.
وجود احراز هویت بهتنهایی کافی نیست. ممکن است کاربر وارد حساب خود شده باشد، اما بتواند اطلاعات حساب کاربر دیگری را نیز مشاهده کند؛ این همان نوع ضعفی است که در بررسی کنترل دسترسی به دنبال آن هستیم.
۲. شناسایی نقطه ورودی GraphQL
در اولین مرحله، باید مشخص کنیم API از کجا درخواست دریافت میکند. مسیرهای رایج عبارتاند از:
/graphql
/api/graphql
/graphql/
این مسیرها فقط نمونهاند و ممکن است API از مسیر دیگری استفاده کند. در تست واقعی، از مستندات پروژه، تنظیمات برنامه یا درخواستهای ثبتشده در مرورگر استفاده کنید؛ مسیرها را بدون مجوز روی سامانههای دیگر جستوجو نکنید.
بررسی یک API آزمایشگاهی با curl
فرض کنیم یک سرویس آزمایشی روی رایانه خودتان اجرا شده و آدرس آن http://127.0.0.1:4000/graphql است.
curl -i http://127.0.0.1:4000/graphql
این دستور پاسخ HTTP را نمایش میدهد. دریافت خطای 400 یا 405 بهتنهایی به معنی آسیبپذیری نیست؛ ممکن است سرور فقط درخواستهای POST یا قالب خاصی از درخواست را قبول کند.
حالا یک Query ساده ارسال کنید:
curl -i -X POST \
http://127.0.0.1:4000/graphql \
-H 'Content-Type: application/json' \
--data '{"query":"{ __typename }"}'
در صورت پشتیبانی سرور، پاسخ معمولاً ساختاری شبیه این دارد:
{
"data": {
"__typename": "Query"
}
}
مقدار Query در این مثال نام نوع ریشهای است و به پیادهسازی سرویس بستگی دارد. این آزمایش صرفاً بررسی میکند که آیا سرور یک Query معتبر را پردازش میکند؛ موفقیت آن بهتنهایی وجود ضعف امنیتی را ثابت نمیکند.
۳. بررسی Introspection؛ آیا ساختار API افشا میشود؟
یکی از قابلیتهای GraphQL، امکان پرسوجو درباره Schema است. این قابلیت برای توسعهدهندگان مفید است، اما در محیط عملیاتی باید تصمیم گرفت که آیا دسترسی عمومی به جزئیات Schema لازم است یا خیر.
در محیط آزمایشگاهی مجاز، درخواست زیر را بررسی کنید:
curl -s -X POST \
http://127.0.0.1:4000/graphql \
-H 'Content-Type: application/json' \
--data '{"query":"{ __schema { queryType { name } } }"}'
نتایج احتمالی:
-
پاسخ حاوی اطلاعات Schema: قابلیت Introspection فعال است.
-
خطای رد شدن درخواست: ممکن است Introspection غیرفعال باشد یا سیاست دیگری درخواست را رد کند.
-
خطای نحوی یا سروری: بهتنهایی نتیجه قطعی درباره وضعیت Introspection نیست.
نکته حرفهای: فعال بودن Introspection الزاماً به معنی آسیبپذیری نیست. باید بررسی کنید آیا اطلاعات افشاشده به کشف عملیات حساس یا ساختارهای غیرضروری کمک میکنند و آیا کنترل دسترسی مستقل و صحیح است.
۴. تست کنترل دسترسی؛ مهمترین بخش بررسی امنیتی
فرض کنید API یک فروشگاه فرضی، اطلاعات سفارشها را بر اساس شناسه برمیگرداند:
query GetOrder {
order(id: "101") {
id
status
total
}
}
برای تست، دو حساب آزمایشی بسازید:
-
حساب A مالک سفارش
101باشد. -
حساب B مالک سفارش
202باشد.
سپس با نشست معتبر هر حساب، دسترسی به سفارش متعلق به حساب دیگر را بررسی کنید. فقط از دادههای ساختگی خودتان استفاده کنید.
| آزمایش | نتیجه امن مورد انتظار |
|---|---|
| حساب A سفارش خودش را میخواند | پاسخ مجاز |
| حساب A سفارش حساب B را درخواست میکند | رد دسترسی یا پاسخ کنترلشده |
| کاربر بدون ورود سفارش خصوصی را میخواند | رد دسترسی |
| کاربر فیلد حساس و غیرمجاز را درخواست میکند | فیلد افشا نشود |
اگر حساب A بتواند داده خصوصی سفارش حساب B را دریافت کند، احتمال وجود ضعف کنترل دسترسی در سطح شیء (BOLA/IDOR) مطرح است. اگر بتواند عملیات مخصوص مدیر را اجرا کند، باید احتمال ضعف کنترل دسترسی در سطح عملیات (BFLA) بررسی شود. OWASP تأکید میکند که مجوزها باید هم برای دادهها و هم برای عملیات اعمال شوند؛ دانستن شناسه یک شیء نباید مجوز دسترسی تلقی شود.
۵. بررسی Mutation؛ آیا کاربر میتواند دادهها را تغییر دهد؟
در GraphQL، عملیات Mutation برای ایجاد، ویرایش و حذف دادهها استفاده میشود. اشتباه رایج این است که برنامه برای خواندن دادهها کنترل دسترسی دارد، اما هنگام ویرایش همان دادهها، مجوز مالکیت را بررسی نمیکند.
مثال فرضی:
mutation UpdateProfile {
updateProfile(input: {
displayName: "Test User"
}) {
id
displayName
}
}
این Query صرفاً یک نمونه ساختاری است و نام عملیات و فیلدها باید با Schema آزمایشگاه شما مطابقت داشته باشند.
در تست مجاز بررسی کنید:
-
آیا کاربر ناشناس قادر به اجرای Mutation است؟
-
آیا کاربر میتواند پروفایل کاربر دیگری را تغییر دهد؟
-
آیا نقش عادی میتواند عملیات مدیریتی را اجرا کند؟
-
آیا تغییر فیلدهای حساس مانند
role،isAdminیاaccountStatusمحدود شده است؟ -
آیا بعد از رد شدن درخواست، داده واقعاً بدون تغییر باقی میماند؟
نکته: تغییر نام یک فیلد در درخواست کافی نیست تا ضعف اثبات شود. باید اثر واقعی عملیات را در دادههای آزمایشی بررسی کنید.
۶. بررسی Queryهای سنگین و محدودیت منابع
انعطاف GraphQL اجازه میدهد چندین فیلد و رابطه تودرتو در یک درخواست دریافت شوند. اگر عمق، تعداد نتایج و هزینه اجرای Query محدود نشده باشد، درخواستهای پرهزینه ممکن است باعث مصرف بیش از حد منابع شوند.
برای نمونه، این Query فرضی را در نظر بگیرید:
query CheckPagination {
products(first: 10) {
id
name
}
}
در محیط آزمایشگاهی، مقدار first را در محدودههای کوچک و مجاز تغییر دهید و موارد زیر را ثبت کنید:
-
آیا تعداد نتایج از سقف تعیینشده عبور میکند؟
-
آیا درخواست خارج از محدوده با خطای مناسب رد میشود؟
-
آیا زمان پاسخ با افزایش تعداد نتایج بهشکل غیرعادی بالا میرود؟
-
آیا محدودیتها برای کاربران ناشناس و واردشده یکسان یا متناسب با سطح دسترسی هستند؟
از ارسال Queryهای بسیار عمیق، تعداد بالای درخواست یا تست بار مخرب روی سرویس واقعی خودداری کنید. برای ارزیابی ظرفیت، از محیط آزمایشی و برنامه تست بار کنترلشده استفاده کنید.
۷. بررسی خطاها و افشای اطلاعات
خطاهای GraphQL گاهی اطلاعاتی درباره ساختار داخلی برنامه، نام فیلدها، مسیر فایلها یا جزئیات پایگاه داده آشکار میکنند.
یک Query نامعتبر و بیخطر را روی محیط مجاز امتحان کنید:
query {
fieldThatDoesNotExist
}
سپس پاسخ را بررسی کنید:
-
آیا نام فیلدهای داخلی یا جزئیات غیرضروری نمایش داده میشوند؟
-
آیا Stack Trace یا مسیرهای فایل در پاسخ وجود دارند؟
-
آیا خطاها اطلاعات احراز هویت یا دادههای حساس را افشا میکنند؟
-
آیا پیام خطا برای کاربر مناسب است و جزئیات فنی فقط در لاگهای محافظتشده ثبت میشوند؟
نمایش پیام خطای اعتبارسنجی همیشه یک آسیبپذیری نیست؛ شدت مسئله به اطلاعات افشاشده و امکان سوءاستفاده از آنها بستگی دارد.
۸. اجرای بررسی با Burp Suite
برای مشاهده و تحلیل درخواستهای GraphQL میتوانید از Burp Suite استفاده کنید.
-
مرورگر آزمایشگاهی را از طریق Proxy ابزار تنظیم کنید.
-
وارد برنامه آزمایشی شوید و یک عملیات عادی انجام دهید.
-
درخواست GraphQL را در HTTP history پیدا کنید.
-
درخواست را به Repeater بفرستید.
-
در هر بار آزمایش فقط یک متغیر را تغییر دهید؛ برای مثال شناسه یک شیء آزمایشی.
-
درخواست را با نشست حساب A و سپس حساب B مقایسه کنید.
-
کد وضعیت HTTP، محتوای پاسخ، زمان پاسخ و تغییرات واقعی داده را ثبت کنید.
درخواست نمونه برای بررسی دستی:
POST /graphql HTTP/1.1
Host: 127.0.0.1:4000
Content-Type: application/json
{"query":"{ __typename }"}
آدرس و پورت فوق صرفاً برای آزمایش محلی هستند. در تست واقعی، از دامنه و نشستهایی استفاده کنید که مجوز بررسی آنها را دارید.
۹. چطور GraphQL را امن کنیم؟
| ریسک | راهکار دفاعی |
|---|---|
| افشای غیرضروری Schema | محدودسازی Introspection و ابزارهای توسعه در محیط عملیاتی |
| BOLA / IDOR | بررسی مجوز دسترسی در هر Resolver و برای هر شیء |
| عملیات مدیریتی غیرمجاز | کنترل دسترسی مستقل برای هر Query و Mutation |
| Queryهای پرهزینه | محدودیت عمق، تعداد نتایج و پیچیدگی Query |
| سوءاستفاده از درخواستهای دستهای | محدودیت Batch و Rate Limit در سطح عملیات |
| افشای اطلاعات از خطاها | حذف جزئیات داخلی و Stack Trace از پاسخ عمومی |
| تزریق به پایگاه داده یا سرویسهای دیگر | اعتبارسنجی ورودی و استفاده از روشهای امن دسترسی به منابع |
| تغییر فیلدهای حساس | Allowlist فیلدهای قابلویرایش و کنترل مجوز سمت سرور |
این اقدامات باید متناسب با معماری برنامه انتخاب شوند. غیرفعالکردن Introspection بهتنهایی جایگزین احراز هویت، کنترل دسترسی و محدودسازی منابع نیست.
۱۰. تمرین عملی برای مخاطبان صفر و یک سایبر
چالش آزمایشگاهی: پیدا کردن ضعف کنترل دسترسی
سطح: متوسط | ابزار: مرورگر، Burp Suite یا curl
پیشرفت تمرین
0 از 6
کپی چکلیست تمرین
معیار موفقیت تمرین این است که حساب A نتواند اطلاعات خصوصی حساب B را بخواند یا تغییر دهد و این محدودیت در سمت سرور اعمال شود.
۱۱. چکلیست نهایی تست نفوذ GraphQL
۱۲. منابع معتبر برای مطالعه بیشتر
-
OWASP — GraphQL Security Cheat Sheet؛ راهکارهای کنترل دسترسی، محدودسازی Query و جلوگیری از سوءاستفاده.
-
مستندات رسمی GraphQL — GraphQL Security؛ محدودیت منابع، Rate Limiting و تحلیل پیچیدگی.
-
راهنمای تست امنیت برنامههای وب OWASP — Web Security Testing Guide؛ روششناسی تست API و GraphQL.
سؤالات متداول
آیا فعال بودن Introspection یعنی سایت آسیبپذیر است؟
خیر. این قابلیت میتواند برای توسعه و مستندسازی ضروری باشد. باید مشخص شود اطلاعات قابل مشاهده غیرضروری یا حساس هستند یا خیر و کنترل دسترسی بهدرستی اجرا میشود.
آیا GraphQL از SQL Injection جلوگیری میکند؟
خیر. GraphQL لایه دریافت و ساختار پرسوجو را تعریف میکند؛ امنیت پایگاه داده به نحوه پیادهسازی Resolverها، اعتبارسنجی ورودیها و روش اجرای Queryها بستگی دارد.
مهمترین آسیبپذیری GraphQL چیست؟
یک پاسخ ثابت برای همه برنامهها وجود ندارد؛ اما کنترل دسترسی ناقص، بهخصوص BOLA/IDOR، و نبود محدودیت برای Queryهای پرهزینه از مهمترین مواردی هستند که باید بررسی شوند.
جمعبندی: در تست نفوذ GraphQL، صرفاً کشف Endpoint یا مشاهده Schema کافی نیست. ارزش اصلی زمانی ایجاد میشود که بتوانید با شواهد روشن نشان دهید آیا یک کاربر میتواند به داده یا عملیاتی خارج از مجوز خود دسترسی پیدا کند و سپس اصلاح آن را تأیید کنید. این همان رویکرد عملی و دفاعمحوری است که برای آموزش امنیت سایبری در صفر و یک سایبر مناسب است.

دیدگاه شما