کاتی بڵاوکراوەتەوە :

SQL Injection - چی یە و چۆن خۆمانی لێ بپارێزین؟

زانیاری سکیوریتی
نوسین و ئامادەکردنی

SQL Injection هێرشێکی باوە لە تەکنۆلۆجیای وێب کە تێیدا هاکەران دەتوانن فەرمانی SQL تایبەت داخڵ بکەن لە ڕێگەی فۆرمەکانی وێبسایتەوە بۆ دەستکاریکردنی داتابەیس. ئەمەش دەبێتە هۆی لەدەستدانی زانیاری هەستیار لە داتابەیسەکان. بۆ نموونە، تەنها لە ماوەی دواییدا، گروپێکی هاکەر بە ناوی ResumeLooters توانیویانە زیاتر لە دوو ملیۆن ناونیشانی ئیمەیڵ و زانیاری کەسیی خەڵک لە ٦٥ وێبسایت بدزن، کە بە زۆری وێبسایتی فرۆشتن و دامەزراندن بوون.

 

کێشەی سەرەکی چییە؟

کێشەکە لێرەدایە کە کاتێک ئێمە لە کۆدەکانی SQL، فەرمانەکان بە شێوەیەکی دینامیکی دروست دەکەین و داتای بەکارهێنەرانی تێدا بەکاردەهێنین بەبێ پاککردنەوەی داتاکە، ئەوا ئەم داتایە دەبێتە بەشێک لە بەرنامەکە. بەپێی جۆری داتاکە، لەوانەیە دەرئەنجامی ئاسایی بێت یان دەرئەنجامی نەخوازراو وەک سڕینەوەی خشتەیەکی داتابەیس.

 

نموونەیەکی سادە بۆ SQL Injection

بۆ نموونە، با بڵێین کۆدێکمان هەیە بەم شێوەیە:

 

<?php

$offset = $_GET['offset']; // سەرنج بدە! هیچ پشکنینێک نییە!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);

?>

لێرەدا کێشەکە ئەوەیە کە کردارێکی SQL دینامیکی دروست دەکرێت بەبێ پشکنینی داتای بەکارهێنەر. کاتێک بەکارهێنەر شتێکی وەک

 

0; insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd) select 'crack', usesysid, 't','t','crack' from pg_shadow where usename='postgres'; --

داخڵ دەکات، ئەوا دەتوانێت دەستی بە داتابەیسەکە بگات بە مافی ئەدمینی سەرەکی!

 

چۆن خۆمان لە SQL Injection بپارێزین؟

١. بەکارهێنانی Prepared Statements

باشترین ڕێگا بۆ خۆپاراستن لە SQL Injection، بەکارهێنانی Prepared Statements یان Parameterized Queries یە. لە PHP دا، ئەم تەکنیکە بە باشی پشتگیری دەکرێت لە ڕێگەی PHP Data Objects (PDO). بەم شێوەیە:

 

<?php

// زانیاریەکانی پەیوەندی
$servername = "localhost";
$username = "ناوی_بەکارهێنەر";
$password = "وشەی_نهێنی";
$dbname = "ناوی_داتابەیس";



try {

    // دروستکردنی پەیوەندی
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);

   
    // دانانی مۆدی هەڵە
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

   

    // prepared statement
    $stmt = $conn->prepare("SELECT * FROM users WHERE username = :username");
    $stmt->execute(['username' => $_POST['username']]);

    

    // دەرهێنانی داتا
    $result = $stmt->fetchAll();

    
    // پیشاندان
    foreach($result as $row) {
        echo "ID: " . $row["id"] . " - ناو: " . $row["username"] . "<br>";
    }
}
catch(PDOException $e) {
    echo "هەڵە: " . $e->getMessage();
}

$conn = null; // داخستنی پەیوەندی

?>

گرنگە ئاگاداری ئەوە بیت کە کاتێک پەیوەندی PDO دروست دەکەیت، خاسیەتی ATTR_EMULATE_PREPARES بکەیت بە false. ئەمە وا دەکات کە PHP خۆی بەهاکان parse نەکات پێش ناردنی بۆ خزمەتگوزاری MySQL.

 

٢. بەکارهێنانی MySQLi

MySQLi ڕێگایەکی تری باوە بۆ پاراستنی کۆدەکان:

 

<?php

// زانیاریەکانی پەیوەندی

$servername = "localhost";
$username = "ناوی_بەکارهێنەر";
$password = "وشەی_نهێنی";
$dbname = "ناوی_داتابەیس";



// دروستکردنی پەیوەندی
$conn = mysqli_connect($servername, $username, $password, $dbname);



// پشکنینی پەیوەندی
if (!$conn) {
    die("پەیوەندی سەرکەوتوو نەبوو: " . mysqli_connect_error());
}



// prepared statement

$stmt = mysqli_prepare($conn, "SELECT * FROM users WHERE username = ?");
mysqli_stmt_bind_param($stmt, "s", $_POST['username']); // "s" بۆ string
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);



// دەرهێنانی داتا
while($row = mysqli_fetch_assoc($result)) {
    echo "ID: " . $row["id"] . " - ناو: " . $row["username"] . "<br>";
}

mysqli_stmt_close($stmt);
mysqli_close($conn);

?>


٣. بەکارهێنانی Stored Procedures

Stored Procedures دەتوانن لایەنێکی تری پاراستن زیاد بکەن. ئەمانە فەرمانی SQL پێشوەختە کۆمپایڵکراون کە لە داتابەیس خەزن دەکرێن. کاتێک Stored Procedures بەکاردێنیت، دەتوانیت پارامیتەر دیاری بکەیت کە داتای بەکارهێنەر وەردەگرن، هاوشێوەی prepared statements. ئەمەش ڕێگە نادات بە هێرشی SQL Injection چونکە داتاکە وەک داتا مامەڵەی لەگەڵ دەکرێت نەک وەک بەشێک لە فەرمانەکە.

 

نموونەیەک لە MySQL:

DELIMITER //
CREATE PROCEDURE GetUserByUsername(IN usernameParam VARCHAR(255))

BEGIN
    SELECT * FROM users WHERE username = usernameParam;
END //

DELIMITER ;

و لە PHP:

<?php

$username = $_POST['username'];
$stmt = $conn->prepare("CALL GetUserByUsername(?)");
$stmt->execute([$username]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);

?>


٤. سنوردارکردنی مافەکان (Principle of Least Privilege)

بۆ کەمکردنەوەی زیانی هێرشێکی سەرکەوتووی SQL injection، دەبێت مافەکانی هەر هەژمارێکی داتابەیس لە ژینگەکەتدا کەم بکەیتەوە.

 

جێبەجێکردنی بنەمای کەمترین ماف واتە بەکارهێنەران و ئەپڵیکەیشنەکان تەنها ئەو مافانەیان هەبێت کە پێویستن بۆ ئەنجامدانی کارەکانیان. جێبەجێکردنی ئەم بنەمایە بۆ ڕۆڵەکانی بەکارهێنەر و مافەکانی داتابەیس هەنگاوێکی گرنگە لە ڕێگریکردن لە SQL injection.

 

جۆرەکانی SQL Injection

Blind SQL Injection کاتێک ڕوودەدات کە ئەپڵیکەیشنەکە ڕاستەوخۆ ئەنجامی query داخڵکراوەکە بۆ هێرشکەر ناگەڕێنێتەوە. لەبری ئەوە، هێرشکەران query داڕێژراو دەنێرن و چاودێری وەڵامی ئەپڵیکەیشنەکە دەکەن بۆ ئەوەی پێکهاتە و ناوەڕۆکی داتابەیسەکە دەربهێنن.

 

ئەنجام

خۆپاراستن لە SQL Injection زۆر گرنگە بۆ پاراستنی داتا و زانیاری کەسی. هەمیشە دڵنیابە لە پاککردنەوەی داتای بەکارهێنەران بە وریاییەوە، بەکارهێنانی prepared statements یان stored procedures. هەروەها دەتوانیت ئامڕازەکانی پشکنینی لاوازی بەکاربهێنیت بۆ دڵنیابوون لەوەی کە ئەپڵیکەیشنەکانت لاواز نین.

 

لەبیرت نەچێت کە ئەمانە بکەیت:

  • هەردەم prepared statements بەکاربهێنە
  • داتای بەکارهێنەران پاک بکەوە
  • مافەکانی بەکارهێنەری داتابەیس سنوردار بکە
  • بەردەوام ئەپڵیکەیشنەکەت تاقیبکەوە بۆ لاوازییەکان

 

بە جێبەجێکردنی ئەم ڕێنماییانە، دەتوانیت ئەپڵیکەیشنەکانت بپارێزیت لە هێرشی SQL Injection و داتای بەکارهێنەرانت بە پارێزراوی بهێڵیتەوە.