در این تمرین، یک برنامه وب آسیبپذیر را در محیط محلی راهاندازی میکنیم، رفتار SQL Injection را بررسی میکنیم، تفاوت کد ناامن و امن را میآموزیم و در پایان یک گزارش تست نفوذ حرفهای مینویسیم.
هدف آموزشی: درک علت آسیبپذیری و اثبات کنترلشده آن در آزمایشگاه؛ نه آزمایش روی سایتهای واقعی بدون مجوز.
نقشه اجرای تمرین
۱. آمادهسازی کالی لینوکس
نصب Docker یا انتخاب آزمایشگاه آماده
۲. مشاهده SQL Injection
مقایسه ورودی عادی با ورودی آزمایشگاهی کنترلشده
۳. تحلیل علت فنی
شناخت نحوه تغییر ساختار پرسوجوی SQL
۴. اصلاح و اعتبارسنجی
استفاده از پرسوجوی پارامتری و آزمون مجدد
مرحله اول: آمادهسازی آزمایشگاه
پیشنهاد من استفاده از OWASP Juice Shop یا OWASP WebGoat است؛ هر دو برای آموزش امنیت برنامههای وب طراحی شدهاند.
-
OWASP Juice Shop — صفحه رسمی پروژه
-
OWASP WebGoat — صفحه رسمی پروژه
در ادامه از Docker استفاده میکنیم تا برنامه آزمایشی از سیستم اصلی جدا بماند. اگر Docker از قبل نصب نیست، ابتدا نصب و اجرای آن را بررسی کن.
۱.۱ اجرای Juice Shop
در ترمینال کالی این دستورات را اجرا کن:
docker --version
docker info
اگر Docker فعال است، آزمایشگاه را دریافت کن:
docker pull bkimminich/juice-shop
سپس آن را فقط روی رابط محلی اجرا کن:
docker run --rm --name juice-lab \
-p 127.0.0.1:3000:3000 \
bkimminich/juice-shop
این روش اجرا با مستندات پروژه سازگار است و اتصال سرویس را به 127.0.0.1 محدود میکند.
مرورگر را باز کن و به این آدرس برو:
http://127.0.0.1:3000
ترمینال را باز نگه دار؛ برای توقف آزمایشگاه از Ctrl+C استفاده کن.
اگر Docker نصب نیست یا docker info خطا میدهد، ابتدا باید همان مشکل را برطرف کنیم.
مرحله دوم: SQL Injection چیست؟
فرض کن برنامه برای جستوجوی یک کاربر، این پرسوجو را میسازد:
SELECT id, username
FROM users
WHERE username = 'INPUT';
در طراحی ناامن، ورودی کاربر مستقیماً به متن SQL متصل میشود. اگر ورودی بهگونهای تفسیر شود که ساختار پرسوجو را تغییر دهد، ممکن است شرطهای برنامه تغییر کنند.
در مقابل، Prepared Statement ورودی را بهعنوان داده جدا از دستور SQL ارسال میکند.
مرحله سوم: آزمایش مفهومی و کنترلشده
این نمونه مستقل از هر سایت واقعی است و برای نشان دادن علت آسیبپذیری طراحی شده است.
فرض کن جدول آزمایشی users این دادهها را دارد:
| id | username |
|---|---|
| 1 | sara |
| 2 | ali |
| 3 | reza |
برنامه باید فقط رکوردی را برگرداند که نام کاربری آن با ورودی برابر است.
-
ورودی
sara: باید فقط رکورد سارا را برگرداند. -
ورودیای که ساختار شرط را تغییر میدهد: در پیادهسازی ناامن ممکن است نتیجه متفاوتی ایجاد کند.
-
در پیادهسازی پارامتری: ورودی بهعنوان مقدار مقایسه میشود، نه بخشی از دستور SQL.
در این مرحله، در محیط Juice Shop یک تمرین مرتبط با SQL Injection انتخاب کن و رفتار برنامه را از طریق مرورگر بررسی کن. برای فهم ساختار درخواستها نیز میتوانی Burp Suite Community را باز کنی و درخواست آزمایشگاه را در بخش HTTP history مشاهده کنی.
مرحله چهارم: اصلاح آسیبپذیری در کد
نمونه ناامن در Python با SQLite:
query = ( "SELECT id, username FROM users " "WHERE username = '" + username + "'")cursor.execute(query)
نسخه اصلاحشده:
query = """ SELECT id, username FROM users WHERE username = ?"""cursor.execute(query, (username,))
در نسخه امن، مقدار username جداگانه به پایگاه داده ارسال میشود. استفاده از پارامترهای مناسب، دفاع اصلی در برابر SQL Injection است؛ اعتبارسنجی ورودی و محدود کردن مجوزهای حساب پایگاه داده نیز لایههای تکمیلی دفاع هستند.
مستندات تکمیلی: راهنمای پیشگیری از SQL Injection در OWASP
مرحله پنجم: گزارش تست نفوذ
برای انتشار این آموزش در «صفر و یک سایبر»، گزارش یافته باید دستکم شامل موارد زیر باشد:
-
عنوان: SQL Injection در ورودی جستوجوی کاربر
-
محیط: آزمایشگاه محلی OWASP
-
شرایط بازتولید: مراحل دقیق مشاهده رفتار ناامن
-
شواهد: درخواست و پاسخ آزمایشگاهی، بدون اطلاعات حساس
-
اثر امنیتی: احتمال دسترسی یا تغییر غیرمجاز دادهها، متناسب با شواهد
-
راهکار اصلاح: پرسوجوی پارامتری، حداقل دسترسی پایگاه داده و آزمون مجدد
-
نتیجه آزمون مجدد: تأیید اینکه ورودی دیگر ساختار SQL را تغییر نمیدهد

دیدگاه شما