حملات تزریق یا injection Attacks چیست؟
حملات تزریق یکی از رایجترین و خطرناکترین نوع حملات در حوزه امنیت وب هستند که از طریق ورودیهای ناامن به برنامهها یا سیستمهای وب انجام میشوند. این حملات به صورت کلی در دو دسته قرار میگیرند.
SQL Injection (حملات تزریق SQL):
در این نوع حمله، حملهگران با وارد کردن دستورات SQL مخرب به جای مقادیر ورودی ، توانایی دسترسی به پایگاه داده و اجرای دستورات ناخواسته را پیدا میکنند.
مثال: فرض کنید یک فرم ورود به سایت دارید که نام کاربری و رمزعبور را به پایگاه داده ارسال میکند. اگر یک هکر به جای رمزعبور معمولی، یک دستور SQL مخرب مانند '; DROP TABLE users; --
را وارد کند، میتواند به سادگی جداول دیتابیس را پاک کند.
Command Injection (حملات تزریق دستور):
در این حمله، حملهگر با استفاده از ورودیهایی که باید داده باشند (مانند فرمها یا پارامترهای URL)، دستورات سیستم عامل را به صورت ناخواسته اجرا میکند.
مثال: اگر یک برنامه وب به صورت داینامیک دستورات سیستم را برای اجرا از طریق ورودیهای کاربر قبول کند، میتواند این ورودیها را به نحوی تغییر داده و دستورات خطرناکی مانند rm -rf /
(برای حذف تمام فایلهای سیستم) را اجرا کند.
برای مقابله با حملات تزریق، از روشهایی مانند استفاده از پارامترایز شده کردن (parameterized queries) برای جلوگیری از SQL Injection و اعتبارسنجی دقیق ورودیهای کاربر برای جلوگیری از Command Injection استفاده میشود. همچنین استفاده از فایروالها و ورودیهای امن برای محافظت از برنامههای وب نیز اهمیت دارد.
نمونه هایی از حملات Sql injection
SQL Injection یک تکنیک حمله مخرب است که به وسیله آن حملهگران میتوانند دستورات SQL مخرب را به یک برنامه کاربردی وارد کنند. این حملات به دلیل نادرست بودن اعتبارسنجی و ضدعفونی ورودیها ممکن است رخ دهند. در ادامه به چند روش مختلف SQL Injection اشاره میکنیم:
Classic SQL Injection (حملات SQL Injection کلاسیک):
در این روش، حملهگر با وارد کردن کدهای SQL به ورودیهای برنامه، دستورات SQL مخرب را اجرا میکند.
مثال: فرض کنید یک برنامه کاربردی از این کوئری برای بررسی نام کاربری و رمز عبور استفاده میکند:
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
اگر حملهگر ورودی زیر را به عنوان نام کاربری وارد کند:
' OR '1'='1
کوئری نهایی به این صورت تغییر میکند:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'password';
که در نتیجه همیشه true میشود و هکر میتواند به سیستم دسترسی پیدا کند.
Blind SQL Injection (حملات SQL Injection کور):
در این روش، حملهگر نمیتواند مستقیماً نتایج را ببیند، اما با بررسی پاسخهای سرور و تغییر پارامترهای ورودی، اطلاعات لازم را استخراج میکند.
مثال: حملهگر میتواند با ارسال درخواستهای مختلف و بررسی پاسخهای true یا false، ستونهای جدول را کشف کند:
SELECT * FROM users WHERE id = 1 AND (SELECT COUNT(*) FROM information_schema.tables) > 0;
Union-Based SQL Injection (حملات SQL Injection بر پایه UNION):
در این روش، حملهگر از دستور 'UNION'
برای ترکیب نتایج چند کوئری استفاده میکند تا بتواند اطلاعات دیگری را از پایگاه داده استخراج کند.
//' UNION ' SELECT username, password FROM users --
Error-Based SQL Injection (حملات SQL Injection بر پایه خطا):
در این روش، حملهگر از پیامهای خطا برای استخراج اطلاعات استفاده میکند.
مثال: با ارسال ورودیهای نادرست و بررسی پیامهای خطا میتوان به ساختار جدولها و پایگاه داده پی برد:
' OR 1=1; --
Time-Based Blind SQL Injection (حملات SQL Injection کور بر پایه زمان):
در این روش، حملهگر از تأخیر زمانی برای استخراج اطلاعات استفاده میکند. اگر یک شرط درست باشد، پایگاه داده به مدت مشخصی متوقف میشود.
' OR IF(1=1, SLEEP(5), 0); --
Second-Order SQL Injection (حملات SQL Injection دومرحلهای):
در این روش، حملهگر کدهای مخرب را به گونهای وارد میکند که در مرحله بعدی یا توسط بخشی دیگر از برنامه اجرا شوند.
مثال: حملهگر میتواند دادههای مخرب را در یک فرم ثبت نام وارد کند و بعداً وقتی برنامه دادهها را در کوئری دیگری استفاده میکند، حمله اتفاق بیفتد.
روش های پیشگیری از حملات SQL اینجکشن
- استفاده از پرس و جوهای پارامتری: استفاده از Prepared Statements به جای ترکیب مستقیم ورودیهای کاربر با دستورات SQL.
- ضدعفونی ورودیها: اطمینان حاصل کنید که همه ورودیها به درستی ضدعفونی شدهاند.
- استفاده از ORM: استفاده از ابزارهای Object-Relational Mapping که به خودی خود در برابر SQL Injection مقاوم هستند.
- محدود کردن مجوزهای پایگاه داده: اعطای حداقل مجوزهای لازم به کاربران پایگاه داده.
- مانیتورینگ و ثبت لاگها: مانیتورینگ منظم و بررسی لاگها برای شناسایی و پاسخ به حملات احتمالی.
با پیروی از این روشها، میتوان به طور مؤثری از حملات SQL Injection جلوگیری کرد و امنیت برنامههای کاربردی وب را بهبود بخشید.
راهکارهای عملی برای جلوگیری از حملات Sql injection در زبان Php
برای جلوگیری از حملات SQL Injection در PHP، میتوانید از تکنیکها و راهکارهای زیر استفاده کنید. این روشها به شما کمک میکنند تا برنامههای وب خود را در برابر این نوع حملات محافظت کنید.
۱٫ استفاده از کوئریهای پارامتری (Prepared Statements)
استفاده از کوئریهای پارامتری در PDO (PHP Data Objects) و MySQLi (MySQL Improved) یکی از موثرترین روشها برای جلوگیری از SQL Injection است. این روش به شما اجازه میدهد تا ورودیهای کاربر را به عنوان پارامتر به کوئری اضافه کنید و از تزریق کدهای مخرب جلوگیری کنید.
مثالی با استفاده از PDO در این قسمت شرح می دهم :
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $dbh->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$username = $_POST['username'];
$password = $_POST['password'];
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
echo "Login successful!";
} else {
echo "Login failed!";
}
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
?>
مثال با استفاده از MySQLi :
connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$username = $_POST['username'];
$password = $_POST['password'];
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
if ($user) {
echo "Login successful!";
} else {
echo "Login failed!";
}
$stmt->close();
$mysqli->close();
?>
۲٫ ضدعفونی کردن ورودیهای کاربر (Input Sanitization)
هرچند استفاده از کوئریهای پارامتری اصلیترین روش جلوگیری از SQL Injection است، اما ضدعفونی کردن ورودیهای کاربر نیز به عنوان یک لایه امنیتی اضافی مفید است.
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$password = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);
۳٫ استفاده از ORMها (Object-Relational Mappers)
ORMها به توسعهدهندگان این امکان را میدهند که با استفاده از اشیاء به جای دستورات SQL، با پایگاه داده تعامل کنند. این ابزارها به خودی خود در برابر SQL Injection مقاوم هستند.
مثال با استفاده از Doctrine ORM:
'pdo_mysql',
'user' => 'root',
'password' => '',
'dbname' => 'testdb',
);
$entityManager = EntityManager::create($conn, $config);
// جستجوی کاربر
$username = $_POST['username'];
$password = $_POST['password'];
$userRepository = $entityManager->getRepository('User');
$user = $userRepository->findOneBy(array('username' => $username, 'password' => $password));
if ($user) {
echo "Login successful!";
} else {
echo "Login failed!";
}
?>
۴٫ استفاده از Stored Procedures
Stored Procedures یا روالهای ذخیرهشده، کدهای SQL را در پایگاه داده نگه میدارند و میتوانند به عنوان یک لایه امنیتی اضافی برای جلوگیری از SQL Injection استفاده شوند.
مثال در MySQL:
DELIMITER //
CREATE PROCEDURE sp_Login(IN username VARCHAR(50), IN password VARCHAR(50))
BEGIN
SELECT * FROM users WHERE users.username = username AND users.password = password;
END //
DELIMITER ;
استفاده در PHP:
connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
$stmt = $mysqli->prepare("CALL sp_Login(?, ?)");
$stmt->bind_param("ss", $username, $password);
$username = $_POST['username'];
$password = $_POST['password'];
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
if ($user) {
echo "Login successful!";
} else {
echo "Login failed!";
}
$stmt->close();
$mysqli->close();
?>
نتیجه گیری
با توجه به موضوعاتی که بررسی کردیم با برخی راهکار های جلوگیری از اینجکشن و محافظت از سیستم در برابر حملات Sql injection آشنا شدید. در نظر داشته باشید که محتوای این مقاله جنبه آموزشی داشت و صرفا هدف بررسی امکانات برای جلوگیری از حملات اینجکشن بود. در بخش های بعدی به انواع دیگری از حملات خواهیم پرداخت.