آموزش رایگان PHP

آموزش Prepared Statement در PHP: امن‌سازی دیتابیس در برابر SQL Injection

1405/05/13 21:17 محراب حسن زاده
آموزش Prepared Statement در PHP: امن‌سازی دیتابیس در برابر SQL Injection

حمله SQL Injection چیست و چرا دیتابیس ما را تهدید می‌کند؟

یکی از رایج‌ترین و خطرناک‌ترین آسیب‌پذیری‌های امنیتی در وب، حمله تزریق دیتابیس یا SQL Injection (SQLi) است. این حمله زمانی رخ می‌دهد که ورودی کاربر مستقیماً و بدون فیلترسازی در ساختار کوئری‌های SQL قرار گیرد. در این حالت، نفوذگر با وارد کردن دستورات مخرب SQL می‌تواند منطق کوئری شما را تغییر داده، به اطلاعات حساس (مانند رمزهای عبور) دسترسی پیدا کرده و یا حتی کل دیتابیس را حذف کند.

گوگل و نهادهای امنیتی معتبری مانند OWASP، استفاده از عبارات آماده یا Prepared Statements را به عنوان مطمئن‌ترین و استانداردترین راهکار برای مقابله با این آسیب‌پذیری معرفی کرده‌اند.

Prepared Statement چیست و چگونه کار می‌کند؟

در روش‌های سنتی، ساختار کوئری و داده‌های ورودی با هم ترکیب شده و یکجا به دیتابیس ارسال می‌شوند. اما در Prepared Statement، این فرآیند به دو مرحله مجزا تقسیم می‌شود:

  1. مرحله آماده‌سازی (Prepare): قالب کوئری SQL (بدون داده‌های واقعی کاربر) به دیتابیس فرستاده می‌شود. دیتابیس ساختار کوئری را آنالیز و بهینه‌سازی می‌کند.
  2. مرحله ارسال داده و اجرا (Execute): داده‌های کاربر به عنوان پارامترهای مجزا به سمت دیتابیس ارسال شده و به قالب متصل می‌شوند. در این حالت، دیتابیس به داده‌ها صرفاً به عنوان یک «مقدار متنی خام» نگاه می‌کند و هیچ دستور SQLی را درون ورودی کاربر اجرا نخواهد کرد.

آموزش استفاده از Prepared Statement با استفاده از PDO (توصیه شده)

کتابخانه PDO (PHP Data Objects) بهترین و استانداردترین روش برای اتصال به دیتابیس در PHP است چرا که از دیتابیس‌های مختلف پشتیبانی می‌کند و امنیت بالایی دارد.

در ادامه یک نمونه کد کامل برای اجرای کوئری امن با PDO آورده شده است:


try {
    // 1. اتصال امن به دیتابیس به وسیله PDO
    $dsn = "mysql:host=localhost;dbname=my_secure_db;charset=utf8mb4";
    $username = "root";
    $password = "";
    $options = [
        PDO::ATTR_ERRMODE            =--> PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false, // خاموش کردن شبیه سازی برای امنیت واقعی
    ];
    
    $pdo = new PDO($dsn, $username, $password, $options);

    // ۲. تعریف کوئری با استفاده از Placeholders (:username)
    $sql = "SELECT id, email, password FROM users WHERE username = :username_param LIMIT 1";
    
    // ۳. آماده سازی کوئری در دیتابیس
    $stmt = $pdo->prepare($sql);
    
    // ۴. بایند کردن داده کاربر به صورت کاملا امن
    $userInput = "admin' OR '1'='1"; // یک ورودی مخرب نمونه
    $stmt->bindParam(':username_param', $userInput, PDO::PARAM_STR);
    
    // ۵. اجرا
    $stmt->execute();
    
    $user = $stmt->fetch();
    
    if ($user) {
        echo "کاربر با موفقیت یافت شد!";
    } else {
        echo "کاربری یافت نشد.";
    }
    
} catch (PDOException $e) {
    // در محیط پروڈکشن هرگز جزییات خطا را به کاربر نمایش ندهید
    error_log($e->getMessage());
    die("خطایی در سیستم رخ داده است.");
}

آموزش استفاده از Prepared Statement در MySQLi

اگر پروژه شما از اکستنشن قدیمی‌تر MySQLi استفاده می‌کند، باز هم باید از عبارات آماده به شکل زیر بهره ببرید:



// ۱. ایجاد اتصال به دیتابیس
$mysqli = new mysqli("localhost", "root", "", "my_secure_db");

if ($mysqli--->connect_error) {
    die("اتصال ناموفق: " . $mysqli->connect_error);
}

// ۲. کوئری با استفاده از علامت سوال ?
$sql = "SELECT id, email FROM users WHERE email = ?";

// ۳. آماده سازی در دیتابیس
$stmt = $mysqli->prepare($sql);

if ($stmt) {
    $emailInput = "test@example.com";
    
    // ۴. بایند کردن پارامتر (s مخفف string است)
    $stmt->bind_param("s", $emailInput);
    
    // ۵. اجرا
    $stmt->execute();
    
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        echo "شناسه کاربر: " . $row['id'];
    }
    
    $stmt->close();
}
$mysqli->close();

تفاوت اجرای امن و غیر‌امن در دیتابیس

هنگامی که از Prepared Statement استفاده می‌کنید، موتور دیتابیس کوئری را کامپایل کرده و جایگاه داده‌ها را مشخص می‌کند. اگر کاربر متنی مانند admin' OR '1'='1 وارد کند، دیتابیس فیلد نام کاربری را دقیقا برابر با کل این متن جستجو می‌کند و هرگز بخش OR '1'='1 را به عنوان دستور شرطی منطقی اجرا نخواهد کرد.

این تفاوت بنیادین، راه نفوذ و دور زدن اهراز هویت در دیتابیس را برای همیشه مسدود خواهد کرد.


پیشنمایش

پرسش و پاسخ

نظری یافت نشد

مطالب مشابه

آموزش ساخت اولین فایل PHP و بررسی ساختار تگ‌ها بر اساس استاندارد وب
1405/03/15 00:08

آموزش ساخت اولین فایل PHP و بررسی ساختار تگ‌ها بر اساس استاندارد وب

مطالعه بیشتر
آموزش کامل کار با fopen، سطوح دسترسی و حذف فایل در PHP
1405/05/04 23:28

آموزش کامل کار با fopen، سطوح دسترسی و حذف فایل در PHP

مطالعه بیشتر
آموزش کار با رویدادهای فرم و اعتبارسنجی فرم‌ها در جاوا اسکریپت: راهنمای جامع
1403/08/03 16:47

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

مطالعه بیشتر
آموزش مدیریت Box Model و ترکیب اجزای آن با CSS: کنترل دقیق فاصله‌ها و ابعاد عناصر
1402/06/05 23:30

آموزش مدیریت Box Model و ترکیب اجزای آن با CSS: کنترل دقیق فاصله‌ها و ابعاد عناصر

مطالعه بیشتر
آشنایی با Inheritance در CSS: اصول وراثت و مدیریت استایل‌ها
1403/08/12 19:59

آشنایی با Inheritance در CSS: اصول وراثت و مدیریت استایل‌ها

مطالعه بیشتر
آموزش Responsive Design با استفاده از Media Queries: طراحی واکنش‌گرا برای تمامی دستگاه‌ها
1402/06/10 18:07

آموزش Responsive Design با استفاده از Media Queries: طراحی واکنش‌گرا برای تمامی دستگاه‌ها

مطالعه بیشتر
آموزش جامع توابع در جاوا اسکریپت: نحوه تعریف، فراخوانی و بازگشت مقادیر
1402/11/02 23:23

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

مطالعه بیشتر
آموزش کامل عملگرهای منطقی در PHP (همراه با تفاوت‌های کلیدی)
1405/04/03 23:56

آموزش کامل عملگرهای منطقی در PHP (همراه با تفاوت‌های کلیدی)

مطالعه بیشتر
نصب Vue.js و ایجاد پروژه ساده: آموزش گام‌به‌گام راه‌اندازی Vue
1402/06/28 00:41

نصب Vue.js و ایجاد پروژه ساده: آموزش گام‌به‌گام راه‌اندازی Vue

مطالعه بیشتر
آموزش کامل دستور switch-case در PHP (به همراه مثال‌های کاربردی)
1405/04/04 00:08

آموزش کامل دستور switch-case در PHP (به همراه مثال‌های کاربردی)

مطالعه بیشتر
راهنمای جامع جلوگیری از SQL Injection در PHP (طبق استانداردهای گوگل)
1405/05/13 21:19

راهنمای جامع جلوگیری از SQL Injection در PHP (طبق استانداردهای گوگل)

مطالعه بیشتر
مقایسه کامل و جامع MySQLi و PDO در PHP: کدام یک برای پروژه شما مناسب‌تر است؟
1405/05/04 23:45

مقایسه کامل و جامع MySQLi و PDO در PHP: کدام یک برای پروژه شما مناسب‌تر است؟

مطالعه بیشتر

تمامی حقوق معتلق به ناشر سایت است و کپی از آن پیگرد قانونی دارد