PENTEST

نمونه تست نفوذ: مطالعه موردی یک پلتفرم فروشگاهی ایرانی

علیرضا کیا
علیرضا کیا
کارشناس وب و موبایلبازبینی: ۲۵ مرداد ۱۴۰۵
۲۹ فروردین ۱۴۰۵ ۱۸ دقیقه مطالعه

بیشتر «نمونه تست نفوذ»هایی که در فارسی پیدا می‌کنید یا فهرستی از نام آسیب‌پذیری‌هاست یا یک گزارش سانسورشده‌ی بی‌روایت. آنچه یک مدیر فناوری پیش از سفارش پروژه واقعاً می‌خواهد بداند این است: کار عملاً چطور پیش می‌رود، تستر از کجا شروع می‌کند، هر یافته چطور پیدا می‌شود و چه چیزی آن را از یک هشدار ابزار متمایز می‌کند. این مقاله یک روایت کامل از یک پروژه‌ی فرضی روی پلتفرم فروشگاهی است — از اسکوپینگ تا آزمون مجدد — و برای هر یافته می‌گوید چگونه کشف شد، تأثیر کسب‌وکاری‌اش چه بود، شدتش بر چه مبنایی تعیین شد و رفع درست آن چیست.

در یک نگاه

  • این روایت یک سناریوی ترکیبی و آموزشی است، نه گزارش یک مشتری مشخص. هیچ نام، دامنه، داده یا هویت واقعی در آن وجود ندارد.
  • نقطه‌ی اتکای اول یک IDOR در اندپوینت جزئیات سفارش بود — یافته‌ای که هیچ اسکنری تولید نمی‌کند و با مقایسه‌ی دو نشست کشف شد.
  • ارتقای سطح دسترسی از راه Mass Assignment در به‌روزرسانی پروفایل: فیلدی که رابط کاربری هرگز نمی‌فرستد، اما بک‌اند آن را می‌پذیرفت.
  • دو یافته‌ی منطقی پرهزینه: انباشت تخفیف و شرایط مسابقه در برداشت از کیف پول (با تکنیک single-packet attack).
  • چهار یافته از پنج یافته‌ی اصلی، یک علت ریشه‌ای مشترک داشتند: اعمال مجوزدهی و اعتبارسنجی در لایه‌ی مسیریابی به‌جای لایه‌ی دسترسی به داده.

این نمونه تست نفوذ چیست و چه چیزی نیست — سلب مسئولیت

این یک سناریوی ترکیبی و آموزشی است

روایت زیر مطالعه‌ی موردی یک مشتری واقعی مشخص نیست. یک سناریوی ترکیبی (Composite) و تشریحی است که از الگوهای رایج و شناخته‌شده در پلتفرم‌های فروشگاهی ساخته شده تا روش کار را نشان دهد. هیچ نام شرکت، دامنه‌ی واقعی، داده‌ی مشتری، شناسه یا هویتی در آن افشا نشده و هیچ‌یک از یافته‌ها به سامانه‌ی مشخصی قابل انتساب نیست. نمونه‌های فنی، صرفاً شکل آسیب‌پذیری را نشان می‌دهند و کد بهره‌جویی قابل اجرا نیستند. تعهد محرمانگی ما بخشی از قرارداد است؛ گزارش‌های واقعی هرگز — حتی به‌صورت سانسورشده — بدون رضایت کتبی مشتری منتشر نمی‌شوند.

چرا با این محدودیت چنین مطلبی می‌نویسیم؟ چون تصور رایج این است که تست نفوذ یعنی «یک ابزار را اجرا کن و ببین چه چیزی قرمز شد». روایت زیر نشان می‌دهد پنج یافته‌ی مهم پروژه — همان‌هایی که ارزش مالی داشتند — هیچ‌کدام از خروجی اسکنر بیرون نیامدند. الگوهای زیر تقریباً در هر پلتفرمی با کیف پول و کمپین تخفیف تکرار می‌شوند؛ ادامه‌ی بحث در امنیت فروشگاه اینترنتی.

مرحله‌ی صفر: اسکوپینگ و قواعد درگیری

سازمان فرضی ما یک پلتفرم فروشگاهی چندفروشندگی است: وب‌اپلیکیشن مشتری، پنل فروشنده، پنل مدیریت داخلی، و یک API که هم اپ موبایل و هم فرانت‌اند وب از آن استفاده می‌کنند. کیف پول داخلی دارد، کد تخفیف و کمپین دارد، و درگاه پرداخت بیرونی.

پرسش‌نامه‌ی اسکوپینگ سه چیز را روشن کرد که مسیر کل پروژه را تعیین کرد:

  • پنج نقش کاربری: مهمان، مشتری، فروشنده، پشتیبانی، مدیر. برای هر نقش دو حساب دریافت شد — چون آزمون دسترسی افقی به دو حساب هم‌سطح نیاز دارد.
  • مدل جعبه‌ی خاکستری: حساب‌ها و مستندات API در اختیار تیم قرار گرفت، کد منبع نه. اثر این تصمیم بر پوشش و هزینه را در هزینه تست نفوذ توضیح داده‌ایم.
  • محیط Staging با داده‌ی مصنوعی برای آزمون‌های مخرب، و محیط عملیاتی فقط برای آزمون‌های خواندنی و بی‌اثر.

قواعد درگیری هم مکتوب شد: بازه‌ی آزمون ده روز کاری با ممنوعیت آزمون در دو روز کمپین فروش، محدودیت نرخ درخواست، ممنوعیت آزمون منع سرویس، فهرست IPهای مبدأ تیم، و یک شماره‌ی تماس تشدید در هر دو طرف. مجوز کتبی با امضای مالک سامانه پیش از اولین درخواست HTTP امضا شد — قالب و بندهای این سند در قرارداد و مجوز تست نفوذ آمده است.

یک تصمیم اسکوپینگ که ارزشش را نشان داد: خواسته شد پنل فروشنده هم داخل دامنه باشد. مشتری اولش تمایل داشت آن را حذف کند («فروشنده‌ها که غریبه نیستند»). سه یافته از پنج یافته‌ی اصلی از همان پنل بیرون آمد.

شناسایی: نگاشت سطح حمله

دو روز اول صرف نگاشت شد و هیچ آزمون تهاجمی انجام نگرفت. این مرحله معادل دسته‌های WSTG-INFO و WSTG-CONF است و در چک لیست تست نفوذ ردیف‌به‌ردیف فهرست شده.

آنچه به دست آمد:

  • سه زیردامنه که مشتری در فهرست دارایی‌هایش نداشت: یک محیط Staging قدیمی، یک سرویس گزارش‌گیری داخلی، و یک نسخه‌ی قبلی API که هنوز پاسخ می‌داد. مورد سوم بعداً مهم شد.
  • Source Map باقی‌مانده در فرانت‌اند پنل مدیریت، که ساختار درخت کد و نام تمام اندپوینت‌ها را بازسازی می‌کرد — از جمله چند اندپوینت که در رابط کاربری هیچ دکمه‌ای نداشتند.
  • نگاشت کامل جریان‌های کسب‌وکار: ثبت سفارش، اعمال تخفیف، شارژ و برداشت کیف پول، تسویه‌ی فروشنده. این نگاشت پیش‌نیاز آزمون منطق است و بدون آن، بخش BUSL عملاً اجرا نمی‌شود.

در همین مرحله یک اسکن با ابزارهای امضامحور هم اجرا شد. نتیجه‌اش صادقانه این بود: چند هدر امنیتی غایب، یک نسخه‌ی قدیمی در هدر سرور، و فهرست‌شدن دایرکتوری روی یک مسیر استاتیک — مفید، ارزان و بی‌ربط به آنچه در ادامه پیدا شد؛ تفکیک نقش ابزارها در ابزارهای تست نفوذ. نکته‌ی متدولوژیک: نسخه‌ی قدیمی API که هنوز پاسخ می‌داد مصداق «مدیریت نادرست موجودی» در OWASP API Security Top 10 است؛ مسیر /api/v1/ پس از انتشار v2 خاموش نشده بود و بررسی‌های مجوزی جدید فقط در v2 اضافه شده بودند.

یافته‌ی اول: IDOR در اندپوینت جزئیات سفارش

چگونه کشف شد

روش استاندارد و کاملاً دستی: با دو حساب مشتری هم‌سطح وارد شدیم، همان جریان «مشاهده‌ی جزئیات سفارش» را با هر دو انجام دادیم، و سپس درخواست حساب اول را با نشست حساب دوم بازپخش کردیم. تنها چیزی که تغییر کرد، شناسه‌ی سفارش در مسیر بود:

GET /api/v2/orders/104387/details HTTP/2
Authorization: Bearer <session-of-user-B>

پاسخ، جزئیات کامل سفارش کاربر A را برگرداند: نام، شماره تماس، نشانی پستی کامل، اقلام سفارش و چهار رقم آخر کارت. کد وضعیت ۲۰۰ بود و هیچ خطایی ثبت نشد.

چرا اسکنر این را پیدا نمی‌کند: از دید ابزار، این یک درخواست معتبر با پاسخ ۲۰۰ است. ابزار نمی‌داند سفارش ۱۰۴۳۸۷ به چه کسی تعلق دارد. تشخیص این نقص به دانستن «چه چیزی باید مجاز باشد» نیاز دارد و آن دانش بیرون از ابزار است. مفاهیم پایه در IDOR و کنترل دسترسی شکسته.

گسترش یافته

یک یافته‌ی IDOR هرگز تنها نمی‌ماند. بررسی سیستماتیک نشان داد الگوی مشابه روی سه اندپوینت دیگر هم وجود دارد و روی یکی از آن‌ها، متد GET بررسی مجوز داشت اما PATCH نداشت — یعنی امکان تغییر نشانی سفارش کاربر دیگر. این همان الگوی «رفع ناقص» است که در آزمون مجدد بیشترین تکرار را دارد.

تأثیر کسب‌وکار و استدلال شدت

با شمارش ترتیبی شناسه‌ها، کل تاریخ سفارش‌های پلتفرم قابل استخراج بود: نشانی و شماره تماس همه‌ی مشتریان. این نه فقط نشت داده‌ی شخصی، بلکه سرمایه‌ی رقابتی هم هست (حجم فروش، الگوی خرید).

بردار CVSS v4.0 که برای این یافته ثبت شد:

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

استدلال: از شبکه قابل انجام است (AV:N)، پیچیدگی پایین (AC:L)، هیچ پیش‌شرط استقراری لازم نیست (AT:N)، نیازمند یک حساب معمولی است (PR:L)، بدون تعامل کاربر (UI:N)، و محرمانگی سامانه‌ی آسیب‌پذیر بالا (VC:H). امتیاز پایه ۷٫۱ محاسبه شد، یعنی رتبه‌ی کیفی High. برای اندپوینت PATCH که یکپارچگی را هم می‌شکست، VI:H اضافه شد و امتیاز به ۸٫۶ رسید — بالاتر، اما همچنان در بازه‌ی High، چون بازه‌ی Critical از ۹٫۰ شروع می‌شود.

رفع

راهکار ثبت‌شده در دو سطح بود: (۱) فوری — افزودن شرط مالکیت به کوئری بازیابی، به‌شکل WHERE id = ? AND customer_id = ? در لایه‌ی دسترسی به داده، نه به‌عنوان بررسی پس از واکشی؛ (۲) ساختاری — انتقال بررسی مجوز به یک لایه‌ی مرکزی که همه‌ی متدها و همه‌ی نسخه‌های API از آن عبور کنند. راهکار «شناسه‌ها را UUID کنید» صریحاً رد شد: UUID هزینه‌ی حدس را بالا می‌برد اما هیچ بررسی مجوزی اضافه نمی‌کند و از پاسخ اندپوینت‌های دیگر نشت می‌کند.

یافته‌ی دوم: ارتقای سطح دسترسی با Mass Assignment

چگونه کشف شد

از Source Map پنل مدیریت، ساختار مدل کاربر بازسازی شد و مشخص شد شیء کاربر فیلدهایی مثل نقش، وضعیت تأیید فروشنده و سقف اعتبار دارد. اندپوینت به‌روزرسانی پروفایل در حالت عادی فقط نام و شماره تماس را می‌فرستد. پرسش ساده بود: اگر فیلد بیشتری بفرستیم چه می‌شود؟

PATCH /api/v2/me HTTP/2
Content-Type: application/json

{"displayName":"test","role":"seller"}

پاسخ ۲۰۰ بود و در واکشی بعدی پروفایل، نقش تغییر کرده بود. بک‌اند بدنه‌ی JSON را مستقیماً روی مدل نگاشت می‌کرد و فهرست فیلدهای مجاز نداشت. با همین الگو، ارتقا تا نقش پشتیبانی هم ممکن شد؛ نقش مدیر در جدول جداگانه‌ای نگه‌داری می‌شد و از این مسیر قابل دسترسی نبود.

این دسته در OWASP API Security Top 10 با نام BOPLA (مجوزدهی شکسته در سطح ویژگی) شناخته می‌شود و CWE متناظرش CWE-915 است. در OWASP Top 10:2025 زیر A08 (نقص یکپارچگی نرم‌افزار یا داده) و A01 قرار می‌گیرد. مفاهیم پایه در ارتقای سطح دسترسی.

تأثیر کسب‌وکار و استدلال شدت

یک کاربر تازه‌ثبت‌نام‌شده می‌توانست خودش را فروشنده‌ی تأییدشده کند: افزودن کالا به پلتفرم، دیدن داده‌ی فروش، و ورود به چرخه‌ی تسویه‌ی مالی. ترکیب این یافته با یافته‌ی اول، یک زنجیره‌ی کامل می‌ساخت — و اهمیت زنجیره‌سازی همان چیزی است که تست نفوذ را از فهرست هشدار جدا می‌کند.

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N

امتیاز پایه: ۸٫۶ — رتبه‌ی کیفی High. استدلال بالا بودن امتیاز، ترکیب دسترسی پایین لازم با تأثیر هم‌زمان روی محرمانگی و یکپارچگی است. رسیدن به بازه‌ی Critical (۹٫۰ به بالا) نیازمند PR:N (بدون هیچ حسابی) یا اثر روی سامانه‌ی پیرو (SC/SI) بود؛ هیچ‌کدام اینجا برقرار نیست. نوشتن «بحرانی» روی این بردار، امتیاز را با احساسِ شدت اشتباه گرفتن است.

رفع

راهکار درست، فهرست سفید صریح فیلدهای قابل نوشتن در لایه‌ی سریال‌سازی است (الگوی DTO یا Schema ورودی)، به‌جای نگاشت خودکار بدنه روی مدل. فهرست سیاه («فیلد role را نپذیر») راهکار نیست، چون با افزودن هر فیلد جدید به مدل، شکاف تازه‌ای باز می‌شود. علاوه بر آن، تغییر نقش باید رخدادی قابل ثبت و هشدارپذیر باشد — که مستقیماً به دسته‌ی A09:2025 مربوط است. در این پروژه، هیچ لاگی برای تغییر نقش وجود نداشت.

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

چگونه کشف شد

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

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

  • کد تخفیف در مرحله‌ی سبد اعتبارسنجی می‌شد و شناسه‌ی تخفیف در بدنه‌ی درخواست نهایی سفارش دوباره ارسال می‌شد — و در آن مرحله دوباره اعتبارسنجی نمی‌شد. یعنی می‌شد کد را روی سبدی اعمال کرد و سپس محتوای سبد را تغییر داد.
  • ارسال دو شناسه‌ی تخفیف در یک آرایه پذیرفته می‌شد، چون منطق فقط عضو اول را برای بررسی ناسازگاری می‌خواند و همه‌ی اعضا را برای محاسبه.
  • ترتیب اعمال تخفیف و اعتبار کیف پول قابل جابه‌جایی بود، که در بعضی ترکیب‌ها مبلغ نهایی را از مبلغ درست کمتر می‌کرد.

هیچ‌کدام از این‌ها «آسیب‌پذیری» در معنای امضامحور نیستند؛ هر سه درخواست، درخواست‌های معتبری هستند. این دقیقاً دسته‌ی WSTG-BUSL و A06:2025 (طراحی ناامن) است — و همان جایی که OWASP تصریح می‌کند «طراحی ناامن را هیچ پیاده‌سازی بی‌نقصی اصلاح نمی‌کند».

تأثیر کسب‌وکار و استدلال شدت

تأثیر مستقیم مالی و قابل تکرار در مقیاس: هر کاربر می‌توانست تخفیف را چند برابر قواعد کمپین دریافت کند و این با اسکریپت ساده قابل انبوه‌سازی بود.

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

رتبه‌ی کیفی: High. اما اینجا یک صداقت فنی لازم است: CVSS برای سنجش خسارت مالی مستقیم ساخته نشده است. بردار بالا فقط می‌گوید یکپارچگی داده نقض می‌شود؛ نمی‌گوید این نقض برای کسب‌وکار چه معنایی دارد. به همین دلیل در گزارش، در کنار امتیاز، تأثیر کسب‌وکار جداگانه و به زبان مالی نوشته شد. گزارشی که فقط عدد CVSS می‌دهد، برای این دسته یافته‌ها کم‌کار است — نکته‌ای که در گزارش تست نفوذ باز کرده‌ایم.

رفع

محاسبه‌ی قیمت نهایی باید یک‌بار و به‌صورت اتمی در سرور انجام شود، در همان تراکنشی که سفارش ثبت می‌شود، و هیچ مقدار محاسبه‌شده‌ای از سمت کلاینت پذیرفته نشود — نه مبلغ، نه شناسه‌ی تخفیف اعمال‌شده. به‌علاوه، آزمون‌های واحد باید سناریوهای سوءاستفاده را پوشش دهند نه فقط مسیر خوشبینانه: «دو کد تخفیف هم‌زمان»، «تغییر سبد پس از اعمال تخفیف»، «مبلغ منفی».

یافته‌ی چهارم: شرایط مسابقه در برداشت از کیف پول

چگونه کشف شد

هر جریانی که به وضعیت مشترک دست می‌زند، نامزد آزمون موازی است. جریان برداشت از کیف پول الگوی کلاسیک «بررسی سپس اقدام» را داشت: خواندن موجودی، مقایسه با مبلغ درخواستی، ثبت درخواست برداشت، کاهش موجودی. اگر این چهار گام در یک تراکنش اتمی نباشند، پنجره‌ای وجود دارد.

آزمون با گروه‌بندی چند درخواست یکسان و ارسال هم‌زمان آن‌ها انجام شد. اینجا تکنیکی مهم است که تصور قدیمی را باطل می‌کند: single-packet attack. این روش با استفاده از چندگانه‌سازی HTTP/2 چندین درخواست کامل را در یک بسته‌ی TCP بسته‌بندی می‌کند و اثر نویز شبکه را عملاً حذف می‌کند. پژوهش منتشرشده‌ی PortSwigger میانه‌ی پراکندگی حدود ۱ میلی‌ثانیه را گزارش می‌کند، در برابر حدود ۴ میلی‌ثانیه برای روش قدیمی‌تر همگام‌سازی بایت آخر.

نتیجه: از موجودی محدود کیف پول، چند درخواست برداشت هم‌زمان ثبت شد و جمع مبالغ تأییدشده بیش از موجودی بود. مفاهیم و روش دفاع در شرایط مسابقه.

باور غلط رایج

«حمله‌ی شرایط مسابقه روی اینترنت عملی نیست، چون تأخیر شبکه پنجره را از بین می‌برد.» این جمله تا حدود سال ۲۰۲۳ تقریباً درست بود و امروز نیست. single-packet attack روی HTTP/2 نویز شبکه را از معادله حذف می‌کند؛ پژوهش مرجع، فشرده‌سازی ده‌ها درخواست در پنجره‌ای زیر یک میلی‌ثانیه را حتی در فواصل قاره‌ای نشان داده است. هر جریان مالی باید تحت بار موازی آزموده شود.

استدلال شدت

CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

توجه کنید که AC:H و AT:P امتیاز عددی را پایین می‌آورند، چون بهره‌جویی به شرایط زمانی وابسته است و نتیجه قطعی نیست. اما تأثیر کسب‌وکاری آن، خروج پول از سازمان است. در گزارش، این یافته با وجود بازه‌ی عددی پایین‌تر، در اولویت رفع فوری قرار گرفت و دلیلش صریحاً نوشته شد. این همان جایی است که قضاوت انسانی باید بر عدد بچربد.

رفع

راهکار درست در سطح پایگاه‌داده است، نه در سطح برنامه: به‌روزرسانی اتمی و شرطی مثل کاهش موجودی با شرط کافی بودن آن در همان دستور، یا قفل سطری با SELECT ... FOR UPDATE در یک تراکنش، به‌همراه محدودیت یکتایی به‌عنوان تور ایمنی و کلید Idempotency برای درخواست‌های برداشت. راهکار پیشنهادی اولیه‌ی تیم توسعه — یک قفل در سطح برنامه — رد شد، چون در معماری چندنمونه‌ای که پشت متعادل‌کننده‌ی بار اجرا می‌شود، قفل درون‌پردازه‌ای کار نمی‌کند. این شایع‌ترین رفع اشتباه برای این دسته یافته است.

یافته‌ی پنجم: زنجیره‌ی تأمین و کامپوننت قدیمی

چگونه کشف شد

از اثرانگشت فریم‌ورک در مرحله‌ی شناسایی و از فایل‌های باندل‌شده‌ی فرانت‌اند، نسخه‌ی چند کتابخانه استخراج شد. یکی از آن‌ها — کتابخانه‌ای برای پردازش و تبدیل فایل در مسیر آپلود مدارک فروشنده — چند نسخه‌ی اصلی عقب بود و برای آن نسخه، آسیب‌پذیری عمومی منتشر شده بود.

در همین بررسی، دو مشاهده‌ی مهم‌تر از خودِ نسخه‌ی قدیمی هم ثبت شد:

  • هیچ فهرست دارایی نرم‌افزاری (SBOM) وجود نداشت. تیم توسعه نمی‌دانست کدام کتابخانه‌ها در کدام سرویس استفاده می‌شوند. یعنی هنگام انتشار آسیب‌پذیری بعدی، پاسخ به «آیا ما متأثر هستیم؟» چند روز طول می‌کشید.
  • خط لوله‌ی CI/CD امضای بسته‌ها را راستی‌آزمایی نمی‌کرد و از یک آینه‌ی عمومی بدون بررسی نصب می‌کرد.

این دسته در نسخه‌ی جاری فهرست OWASP اهمیت تازه‌ای گرفته: A03:2025 نقص‌های زنجیره‌ی تأمین نرم‌افزار جانشین «اجزای آسیب‌پذیر و قدیمی» شده و دامنه‌اش صریحاً «همه‌ی نقص‌های زنجیره‌ی تأمین، نه فقط مواردی که به آسیب‌پذیری شناخته‌شده مربوط‌اند» است. CWEهای مرتبط: CWE-1104 (استفاده از کامپوننت ثالث بی‌متولی) و CWE-1395 (وابستگی به کامپوننت ثالث آسیب‌پذیر). حوادثی که OWASP خودش نام می‌برد — از SolarWinds تا کرم npm با نام Shai-Hulud در ۲۰۲۵ که بیش از ۵۰۰ نسخه‌ی بسته را آلوده کرد — نشان می‌دهد چرا این دسته صعود کرده.

استدلال شدت و رفع

شدت این یافته به‌تنهایی Medium ثبت شد، چون مسیر رسیدن ورودی مهاجم به کامپوننت آسیب‌پذیر محدود بود (فقط فروشنده‌ی تأییدشده می‌توانست فایل آپلود کند). اما در گزارش به‌عنوان یافته‌ی ساختاری علامت‌گذاری شد: مسئله یک کتابخانه نیست، نبود فرایند است. راهکار سه‌گانه: تولید و نگهداری SBOM متمرکز، راستی‌آزمایی امضا در خط لوله و دریافت بسته فقط از منبع رسمی یا آینه‌ی داخلی بررسی‌شده، و اتصال این‌ها به یک چرخه‌ی مدیریت آسیب‌پذیری با مسئول مشخص.

جمع‌بندی یافته‌ها و علت ریشه‌ای مشترک

#یافتهدستهرتبهچگونه کشف شد
۱IDOR در جزئیات سفارش (و PATCH بدون بررسی)A01:2025 / WSTG-ATHZHigh (۷٫۱ → ۸٫۶)مقایسه‌ی دستی دو نشست هم‌سطح
۲Mass Assignment در به‌روزرسانی پروفایلA08:2025 / BOPLAHigh (۸٫۶)بازسازی مدل داده از Source Map
۳انباشت تخفیف و اعتبارسنجی دوباره‌نشدهA06:2025 / WSTG-BUSLHighنگاشت جریان کسب‌وکار
۴شرایط مسابقه در برداشت کیف پولWSTG-BUSLاولویت فوریارسال موازی با single-packet attack
۵کامپوننت قدیمی و نبود SBOMA03:2025Medium (ساختاری)اثرانگشت نسخه در فاز شناسایی
۶نسخه‌ی قدیمی API فعال بدون بررسی‌های جدیدA02:2025Mediumشناسایی زیردامنه و نسخه
۷نبود لاگ برای تغییر نقش و شکست مجوزدهیA09:2025Mediumبازبینی لاگ‌های بازه‌ی آزمون

مهم‌ترین جمله‌ی گزارش، هیچ‌کدام از این ردیف‌ها نبود. مهم‌ترین جمله این بود:

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

رفع تک‌تک هفت ردیف بالا، هفت وصله می‌ساخت و ریسک را حذف نمی‌کرد. رفع درست، انتقال مجوزدهی به یک لایه‌ی مرکزی و اجبار عبور همه‌ی مسیرها از آن بود. این تفکیک — بین رفع نقطه‌ای و اصلاح ساختاری — همان چیزی است که یک گزارش خوب را از فهرست هشدار جدا می‌کند و در ساختار گزارش تست نفوذ به‌عنوان بخش «نقشه‌ی راه رفع» توضیح داده شده.

آزمون مجدد و آنچه از این پروژه می‌آموزیم

سه هفته بعد، آزمون مجدد اجرا شد. نتیجه شبیه اکثر پروژه‌ها بود:

  • چهار یافته رفع تأییدشده.
  • دو یافته رفع ناقص: بررسی مجوز به لایه‌ی مرکزی منتقل شده بود اما نسخه‌ی v1 از آن لایه عبور نمی‌کرد؛ و در جریان برداشت، به‌روزرسانی اتمی اضافه شده بود ولی یک مسیر تسویه‌ی فروشنده همان الگوی قدیمی را داشت.
  • یک یافته پذیرش ریسک با امضای مدیر فنی: کامپوننت قدیمی تا انتشار بعدی جایگزین نمی‌شد و در فاصله، مسیر آپلود موقتاً محدود شد.

«رفع ناقص» شایع‌ترین نتیجه‌ی آزمون مجدد است و دقیقاً دلیل الزامی بودن این مرحله. توجه کنید PCI DSS در بند ۱۱٫۴٫۴ تکرار آزمون برای تأیید رفع را الزام می‌کند، نه توصیه.

چهار درس قابل تعمیم

  1. دارایی‌هایی که نمی‌شناسید آزموده نمی‌شوند. سه زیردامنه‌ی بیرون از فهرست مشتری، دو یافته تولید کردند.
  2. بخش‌های «خودی» را از دامنه حذف نکنید. پنل فروشنده که مشتری می‌خواست کنارش بگذارد، منبع سه یافته بود.
  3. هیچ ابزاری این پنج یافته را پیدا نمی‌کرد. پیشنهاد قیمتی که زمان انسانی برای این نوع کار در نظر نگرفته، این یافته‌ها را تولید نمی‌کند — استدلال کامل در هزینه تست نفوذ.
  4. رفع درست ساختاری است و ساختار را تیم توسعه می‌سازد، نه تیم آزمون؛ به همین دلیل تحویل گزارش با جلسه‌ی مشترک همراه شد و دوره‌ی سازمانی توسعه‌ی امن به‌عنوان اقدام میان‌مدت پیشنهاد شد.

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

پرسش‌های متداول

آیا این نمونه تست نفوذ مربوط به یک مشتری واقعی است؟

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

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

چون هر پنج یافته‌ی اصلی از جنس مجوزدهی و منطق کسب‌وکار هستند و درخواست‌های مربوط به آن‌ها همه معتبرند. ابزار نمی‌داند سفارش ۱۰۴۳۸۷ به چه کسی تعلق دارد، یا اینکه دو کد تخفیف نباید با هم جمع شوند. این‌ها نیازمند دانش «چه چیزی باید مجاز باشد» هستند و آن دانش بیرون از ابزار است.

چنین پروژه‌ای چقدر طول می‌کشد؟

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

آیا PoC واقعی و قابل اجرا در گزارش می‌آید؟

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

چرا شدت یافته‌ی شرایط مسابقه پایین‌تر بود اما اولویت رفعش فوری؟

چون CVSS پیچیدگی و عدم‌قطعیت بهره‌جویی را در امتیاز لحاظ می‌کند (AC:H و AT:P) اما خسارت مالی مستقیم را نمی‌سنجد. یافته‌ای که هر بار کار نمی‌کند ولی هر بار که کار کند پول از سازمان بیرون می‌رود، باید بر پایه‌ی تأثیر کسب‌وکار اولویت‌بندی شود. گزارش خوب هر دو را می‌دهد: امتیاز استاندارد و تحلیل تأثیر.

بعد از دریافت چنین گزارشی از کجا شروع کنیم؟

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

علیرضا کیا
WRITTEN BY

علیرضا کیا

کارشناس وب و موبایل

متخصص تست نفوذ وب و اندروید با سابقه‌ی مدیریت تیم نفوذ در داتین. مهندسی معکوس اپ‌ها و کشف ذخیره‌سازی ناامن، تخصص اوست.

PENTEST

فرایند تست نفوذ گام‌به‌گام برای سازمان‌ها

ادامه مطلب ←
PENTEST

تست نفوذ وب: از OWASP تا گزارش

ادامه مطلب ←
PENTEST

گزارش تست نفوذ: نمونه، ساختار و قالب نوشتن

ادامه مطلب ←