امنیت وب ۲۰۲۶/۱۰/۲۵ · ۱۰ دقیقه مطالعه

SQL Injection چیست و چگونه جلوی آن را بگیریم؟

نویسنده: تیم آرنا

SQL Injection (تزریق اس‌کیو‌ال) سال‌هاست در صدر فهرست آسیب‌پذیری‌های وب قرار دارد و هنوز هم یکی از دلایل اصلی نشت داده‌هاست. خبر خوب این است که جلوگیری از آن ساده است — اگر بدانی چه کار کنی.

SQL Injection چیست؟

این حمله زمانی رخ می‌دهد که ورودی کاربر مستقیماً وارد یک کوئری دیتابیس شود. مهاجم با دستکاری ورودی، منطق کوئری را عوض می‌کند و می‌تواند داده‌ها را بخواند، تغییر دهد یا حذف کند.

یک مثال واقعی

فرض کن کد ورود این‌طور نوشته شده باشد:

$email = $_POST['email'];
$query = "SELECT * FROM users WHERE email = '$email'";

حالا اگر مهاجم به‌جای ایمیل این را وارد کند:

' OR '1'='1

کوئری نهایی می‌شود:

SELECT * FROM users WHERE email = '' OR '1'='1'

شرط '1'='1' همیشه درست است، پس همهٔ کاربران برگردانده می‌شوند و مهاجم ممکن است بدون رمز وارد شود. در حالت‌های پیشرفته‌تر، مهاجم می‌تواند کل دیتابیس را استخراج کند.

راه‌حل اصلی: Prepared Statements

کلید دفاع این است که داده را از دستور SQL جدا کنی. با Prepared Statements، ورودی هرگز به‌عنوان بخشی از دستور تفسیر نمی‌شود:

// ✅ امن — با PDO
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
$user = $stmt->fetch();

اینجا ? یک جای‌خالی است و مقدار $email فقط به‌عنوان داده استفاده می‌شود، نه دستور. حتی اگر مهاجم ' OR '1'='1 بفرستد، دقیقاً همان رشته در دیتابیس جست‌وجو می‌شود و حمله بی‌اثر است.

در Laravel چطور؟

اگر از Laravel و Eloquent استفاده کنی، به‌صورت پیش‌فرض از Prepared Statements استفاده می‌شود:

// امن به‌صورت خودکار
User::where('email', $email)->first();

تا وقتی از Query Builder یا Eloquent استفاده می‌کنی و کوئری خام با الحاق رشته نمی‌نویسی، در برابر SQL Injection محافظت‌شده‌ای.

چند لایهٔ دفاعی دیگر

  • اعتبارسنجی ورودی: انتظار داده را مشخص کن (مثلاً ایمیل باید فرمت ایمیل داشته باشد).
  • کمترین دسترسی (Least Privilege): کاربر دیتابیسِ برنامه نباید دسترسی DROP یا مدیریتی داشته باشد.
  • پیام خطای مبهم: جزئیات خطای دیتابیس را به کاربر نشان نده.
  • WAF: فایروال اپلیکیشن وب می‌تواند لایهٔ اضافه باشد (اما جایگزین کد امن نیست).

جمع‌بندی

SQL Injection خطرناک اما کاملاً قابل‌پیشگیری است. قانون طلایی: هیچ‌وقت ورودی کاربر را مستقیم در کوئری نگذار؛ همیشه Prepared Statements.

می‌خواهی این حمله را عملی تجربه کنی؟ در میدان نبرد آرنا چالش‌های امنیتی واقعی حل کن. و برای یادگیری امن‌نویسی سمت سرور، مسیر PHP را ببین.

مقاله‌های مرتبط