بازبینی امنیتی کد چیست؟
بازبینی امنیتی کد منبع (Secure Code Review) بررسی کد با هدف یافتن ضعفهای امنیتی است، پیش از آنکه به آسیبپذیری قابل بهرهبرداری در تولید تبدیل شوند. این کار آزمون جعبهسفید (White-box) است: آزمونگر به کد، پیکربندی و معماری دسترسی دارد، برخلاف جعبهسیاه که فقط از بیرون با برنامه تعامل میکند.
دو رویکرد متفاوت زیر همین نام قرار میگیرند:
- SAST (Static Application Security Testing) — تحلیل خودکار و ایستای کد، بدون اجرای برنامه. سریع، تکرارپذیر و قابل ادغام در خط لولهی CI/CD.
- بازبینی دستی — خواندن کد توسط یک آزمونگر با درک از دامنهی کسبوکار. کند، گران، و تنها روشی که مدل مجوزدهی و منطق کسبوکار را میفهمد.
این دو مکمل هماند. OWASP در A05:2025 تزریق ادغام SAST، DAST و IAST در خط لوله را توصیه میکند، و در A06:2025 طراحی ناامن یادآوری میکند که بخشی از مسئله اصلاً در کد نیست.
SAST چه چیزی پیدا میکند و چه چیزی را نمیبیند
| دستهی ضعف | SAST | بازبینی دستی |
|---|---|---|
| سینکهای تزریق (SQL، دستور، SSTI) | خوب | خوب |
| رمز و کلید جاسازیشده در کد | خوب | خوب |
| کاربرد نادرست رمزنگاری (الگوریتم منسوخ، IV ثابت) | خوب | خوب |
| پیکربندی ناامن پارسر و deserialization | متوسط | خوب |
| کنترل دسترسی و IDOR | تقریباً هیچ | خوب |
| منطق کسبوکار و گردشکار | هیچ | خوب |
| شرایط مسابقه و مرزهای تراکنش | ضعیف | متوسط |
الگوی این جدول را باید صریح گفت: SAST در ضعفهای دستهی تزریق و رمزنگاری خوب عمل میکند و در نقص کنترل دسترسی و منطق کسبوکار عملاً هیچ کارایی ندارد — و همین دو دسته، جای پرتأثیرترین یافتههای یک برنامهی وب است. دلیلش ساختاری است: ابزار نمیداند «کاربر ۵ باید به رکورد ۷ دسترسی داشته باشد یا نه». این تصمیم در سند نیازمندیهاست، نه در کد.
هزینهی دیگر SAST، مثبت کاذب است. تیمی که هشدارها را تریاژ نکند، در چند هفته به خستگی هشدار میرسد و ابزار را خاموش میکند.
تحلیل جریان داده و مفهوم taint
هستهی مفهومی SAST جدی، تحلیل آلودگی (Taint Analysis) است. سه مفهوم کلیدی دارد:
- Source — ورود دادهی غیرقابلاعتماد: پارامتر، هدر، کوکی، بدنهی JSON، فایل آپلودی.
- Sink — رسیدن داده به مفسر یا عملیات حساس: کوئری پایگاهداده، فراخوانی شل، رندر قالب، خروجی HTML.
- Sanitizer — تابعی که در مسیر آلودگی را برمیدارد: پارامتریسازی، کدگذاری متناسب با زمینه، فهرست سفید.
ابزار مسیر source به sink را دنبال میکند و اگر sanitizer معتبری نبود هشدار میدهد. تفاوت کیفیت ابزارها در عمق همین ردیابی است:
- تحلیل درونفایلی — مسیر فقط داخل یک فایل دنبال میشود؛ سریع است اما جریانهایی که از چند لایهی سرویس میگذرند را از دست میدهد. موتور رایگان Semgrep در همین سطح کار میکند و تحلیل میانفایلی و میانتابعی آن (Pro engine) قابلیت تجاری است.
- تحلیل کلبرنامه — کد به یک پایگاهدادهی رابطهای تبدیل میشود و پرسوجوی تحلیلی روی آن اجرا میشود؛ معماری CodeQL. توان تحلیلی بالاتری از تطبیق الگو دارد، اما برای زبانهای کامپایلی به بیلد نیاز دارد، ساخت پایگاهداده کند و منبعبر است و نوشتن پرسوجوی سفارشی شیب یادگیری تندی دارد.
واقعیت لایسنس: چیزی که محتوای فارسی اشتباه میگوید
«Semgrep کاملاً متنباز است و CodeQL رایگان است.» هر دو نادرستاند. تنها Semgrep Community Edition متنباز است (LGPL 2.1)؛ Semgrep Code، Secrets، Supply Chain و پلتفرم AppSec اختصاصی هستند. مهمتر اینکه قواعد ثبتشدهی خود Semgrep زیر مجوز محدودکنندهی «Semgrep Rules License v.1.0» قرار دارند: فقط برای مصارف داخلی کسبوکار، و فروشندگان نمیتوانند آنها را در محصول رقیب به کار ببرند. همین سختتر شدن لایسنس به انشعاب Opengrep انجامید — فورکی با پشتیبانی Endor Labs و گروهی از فروشندگان امنیتی برای احیای یک موتور SAST تماممتنباز.
و CodeQL: رایگان بودنش مشروط است به پروژههای متنباز و پژوهش دانشگاهی. تحلیل خودکار کدبیس خصوصی یا تجاری نیازمند توافق تجاری با GitHub است.
این جزئیات اهمیت عملی دارد: اگر SAST را بهعنوان سرویس به مشتری میفروشید، لایسنس قواعدی که استفاده میکنید مسئلهی حقوقی شماست. گزینههای عملگرایانهی امروز: Semgrep CE و فورک آن Opengrep برای کار عمومی، و ابزارهای مخصوص هر زبان که سیگنال بهتری میدهند — Bandit برای پایتون، gosec برای Go، Brakeman برای Rails، PHPStan و Psalm برای PHP، SpotBugs با find-sec-bugs برای جاوا، و njsscan یا افزونههای امنیتی ESLint برای جاوااسکریپت.
نمونهی فنی: یک قاعدهی ساده
قواعد SAST مدرن بهجای عبارت باقاعده، روی درخت نحو (AST) تطبیق میشوند. نمونهی یک قاعدهی خوانا برای الگویی که در پایتون به تزریق دستور منجر میشود:
rules:
- id: py-subprocess-shell-true
pattern: subprocess.run(..., shell=True, ...)
message: shell=True + untrusted input -> command injection
languages: [python]
severity: WARNINGاین قاعده الگو را پیدا میکند اما نمیداند ورودی از کاربر میآید یا یک رشتهی ثابت است؛ تأیید نهایی کار انسان است. همین شکاف نشان میدهد چرا خروجی SAST یک فهرست کاندید است، نه فهرست آسیبپذیری.
جای بازبینی کد در یک engagement وب
دسترسی به کد، آزمون را از جعبهسیاه به جعبهخاکستری یا جعبهسفید ارتقا میدهد و سه چیز را ممکن میکند که از بیرون تقریباً غیرممکناند: دیدن همهی اندپوینتها (از جمله موارد بیلینک)، فهم مدل مجوزدهی بهجای حدس زدن آن، و ریشهیابی هر یافتهی دینامیک تا خط کد مسئول.
ترتیبی که در عمل بهترین بازده را دارد:
- SAST را روی کل کدبیس اجرا کنید تا نقشهی sinkها به دست آید.
- یافتهها را با آزمون دینامیک در پروکسی رهگیر تأیید یا رد کنید؛ هر یافته باید PoC داشته باشد.
- بازبینی دستی را روی مناطق پرریسک متمرکز کنید: احراز هویت و مجوزدهی، مسیرهای آپلود، کوئریسازهای پویا و هر جا که سرور درخواست بیرونی میسازد (SSRF).
- یافتههای تکرارشونده را به قاعده تبدیل کنید تا در CI/CD بازنگردند.
گام چهارم همان جایی است که بازبینی کد از یک رخداد یکباره به قابلیت سازمانی تبدیل میشود. اگر هدف بالا بردن سطح تیم توسعه است، دورهی سازمانی توسعهی امن و مدلسازی تهدید در مرحلهی طراحی بازده بیشتری از افزودن ابزار دارند؛ ترکیب این فعالیتها در متدولوژی تست نفوذ و تست نفوذ وب آمده است.
پرسشهای متداول
تفاوت SAST و DAST چیست؟
SAST کد را بدون اجرا تحلیل میکند و میتواند خط دقیق کد مسئول را نشان دهد، اما زمینهی اجرا و پیکربندی واقعی را نمیبیند. DAST برنامهی در حال اجرا را از بیرون میسنجد، اما نمیداند مشکل کجای کد است. ترکیب این دو با آزمون دستی، پوشش قابل دفاع میسازد.
آیا Semgrep متنباز و رایگان است؟
فقط Semgrep Community Edition با مجوز LGPL 2.1 متنباز است. Semgrep Code، Secrets، Supply Chain و پلتفرم AppSec اختصاصیاند و قواعد ثبتشدهی خودِ Semgrep زیر «Semgrep Rules License v.1.0» فقط برای مصارف داخلی مجاز است — تغییری که به فورک Opengrep انجامید.
آیا میتوانم CodeQL را روی کد تجاری شرکتم استفاده کنم؟
بهصورت رایگان نه. CodeQL برای پروژههای متنباز و پژوهش دانشگاهی رایگان است؛ تحلیل خودکار کدبیس خصوصی یا تجاری به توافق تجاری با GitHub نیاز دارد. برای کد بسته، Semgrep CE یا Opengrep و ابزارهای مخصوص زبان گزینههای بدون قید لایسنساند.
آیا بازبینی کد جای تست نفوذ را میگیرد؟
نه، و برعکسش هم درست نیست. بازبینی کد اندپوینتهای پنهان و ریشهی باگ را نشان میدهد اما نمیگوید در پیکربندی واقعی تولید چه رخ میدهد. بهترین نتیجه از ترکیب این دو در حالت جعبهخاکستری به دست میآید.