آموزش کامل SQL Injection (SQLi) — تهدید قدیمی اما هنوز خطرناک
SQL Injection چیست؟
SQL Injection یا به اختصار SQLi نوعی حمله تزریقی است که در آن مهاجم با وارد کردن دادهٔ مخرب در ورودیها، ساختار کوئری SQL برنامه را تغییر میدهد. اگر ورودیها بهدرستی اعتبارسنجی نشوند یا از کوئریهای پارامتری استفاده نشده باشد، اجرای دستورات غیرمجاز (از خواندن داده تا حذف جدول) ممکن میشود.
چرا در سال ۲۰۲۵ هنوز خطرناک است؟
- وجود سامانهها و کدهای قدیمی (Legacy) در تولید.
- عدم رعایت اصول Secure Coding و نبود Code Review امنیتی.
- تکیهٔ بیشازحد به WAF بدون اصلاح ریشهای کد.
- نبود تست امنیت در CI/CD و اسکن دورهای.
حتی با فریمورکهای مدرن، خطاهای سادهٔ اتصال رشتهها به SQL همچنان رایج است.
SQLi چطور کار میکند؟
در سادهترین حالت، اتصال مستقیم ورودی کاربر به کوئری باعث تغییر منطق فیلترها میشود.
// PHP (ناامن)
$username = $_POST['username'];
$password = $_POST['password'];
$q = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
ورودی مخرب:
admin' --
کوئری نهایی:
SELECT * FROM users WHERE username = 'admin' --' AND password = '';
نتیجه: احراز هویت دور زده میشود. این همان دلیل اصلی لزوم Prepared Statement است.
مثالهای عملی
۱) دور زدن لاگین
' OR 1=1 --
۲) استخراج داده با UNION
SELECT title FROM posts WHERE id=1 UNION SELECT username, password FROM users --
۳) حمله مخرب (حذف جدول) — غیرمجاز
1; DROP TABLE users --
انواع حملات SQLi
نوع | توضیح کوتاه | نمونهٔ الگو |
---|---|---|
Classic/Inline | تغییر مستقیم شرطها با کوتیشن و عملگرها | ' OR 1=1 -- |
Union-Based | ترکیب نتایج با UNION | ... UNION SELECT ... |
Error-Based | افشای اطلاعات از پیامهای خطا | extractvalue() ، updatexml() |
Blind (Boolean) | استنتاج با درست/نادرست بودن پاسخ | AND 1=1 vs AND 1=2 |
Time-Based | استنتاج از تاخیر عمدی | SLEEP(5) ، pg_sleep(5) |
تست آسیبپذیری
۱) تست دستی سریع
- تزریق
'
یا"
در پارامترها و مشاهدهٔ خطا. - تغییر منطق با
OR 1=1
یاAND 1=2
. - بررسی تفاوت پاسخها در صفحات لیستی با پارامترهای عددی.
۲) تست خودکار (مثال قانونی)
sqlmap -u "https://target.test/product.php?id=1" --risk=2 --level=2 --batch --dbs
اجرای ابزارها تنها با مجوز کتبی مالک سامانه مجاز است.
ابزارهای کاربردی
- SQLmap — شناسایی و اکسپلویت خودکار.
- Burp Suite — رهگیری/بازنویسی درخواستها، افزونههای Active Scan.
- jSQL Injection — رابط گرافیکی سبک برای تست.
- Intercepting Proxies — مانند ZAP برای کراول و فازینگ.
روشهای دفاع و پیشگیری
۱) کوئریهای پارامتری (Prepared Statements)
// PHP (PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :u AND password = :p");
$stmt->execute([':u'=>$username, ':p'=>$password]);
// Node.js (pg)
const res = await client.query('SELECT * FROM users WHERE email=$1 AND pass=$2',[email, pass]);
۲) اعتبارسنجی و پاکسازی ورودی
- تطبیق نوع/محدوده، وایتلیست برای فیلدهای کلیدی.
- عدم اتکا به escaping بهتنهایی.
۳) کمینهسازی دسترسی دیتابیس (Least Privilege)
- یوزر اپلیکیشن بدون مجوز
DROP
/ALTER
/GRANT
.
۴) خطاها و لاگها
- عدم نمایش خطاهای دیتابیس به کاربر؛ ثبت امن در لاگ.
۵) لایهٔ محافظتی تکمیلی
- WAF/WAAP، الگوهای رفتاری، و Security Headers (اگرچه جایگزین اصلاح کد نیستند).
جمعبندی
SQL Injection همچنان یکی از تهدیدات جدی وب است. با درک سازوکار حمله و پیادهسازی اصولیِ دفاع (پارامتریسازی، اعتبارسنجی، کمینهسازی دسترسی، و مانیتورینگ)، میتوان ریسک را بهشدت کاهش داد. تمرین عملی را صرفاً روی محیطهای آموزشی مثل DVWA، bWAPP و WebGoat انجام دهید.
پرسشهای متداول
آیا SQLi در سال ۲۰۲۵ هنوز کاربردی است؟
بله، بهویژه در سامانههای قدیمی و پروژههایی که اصول امن را رعایت نکردهاند.
بهترین راه دفاع چیست؟
استفادهٔ سراسری از Prepared Statement، همراه با اعتبارسنجی ورودی و کمینهسازی دسترسی.
از کجا شروع به تمرین کنم؟
محیطهای آموزشیِ آفلاین/آنلاین مانند DVWA، bWAPP، WebGoat و PortSwigger Labs.