SQL injection چیست و چگونه از آن جلوگیری کنیم ؟

SQL injection چیست جلوگیری از آن – تزریق SQL یکی از محبوب ترین باگ های نفوذ گران دنیا وب است به طوری که بیشترین سهم را در هک وبسایت دارد .
چرا که تمامی اطلاعات یک وبسایت در دیتابیس آن ذخیره می شود و دسترسی به این منبع ارزشمند یعنی دسترسی به کل وبسایت . ( SQL injection چیست جلوگیری از آن )
در صورتی که برنامه نویس با این باگ خطرناک آشنا نباشد با کدنویسی غیر ایمن باعث به خطر افتادن وبسایت می شود .
بررسی SQL injection
1- ابتدا کاربر با اضافه کردن ‘ در متغیری که بدون بررسی ورودی انجام شود درخواست را می فرستد تا بررسی کند که آیا دارای باگ SQLi می باشد یا خیر . در صورتی که باگ وجود داشت دستور های MYSQL را تزریق می کند .
2- اطلاعات را به سرور می فرستد تا بررسی شود . کد های برنامه نویس که بدون هیچ بررسی ورودی کاربر دریافت کرده و پردازش می کند .
3- اطلاعات ورودی کاربر ( همان اطلاعاتی که هکر تزریق کرده ) را به دیتابیس می فرستد .
4- دیتابیس با توجه به query پاسخ می دهد و مجدد به سرور می فرستد .
5- سرور اطلاعات ( رکورد های ) دریافت شده از دیتابیس را دریافت کرده و بر اساس پردازش هایی که انجام می شود نتیجه را به کاربر برمی گرداند که
نتیجه حاکی از این است که کاربر نام کاربری و رمز عبور خود را به درستی وارد کرده این در حالی است که فقط نام کاربری وارد شده و هیچ رمز عبوری وجود نداشته .

کد آسیب پذیر SQLi
معمولا نام کاربری و رمز عبور با متود GET صورت نمی گیرد و POST است اما برای سرعت بخشیدن و عدم نیاز به ابزار های جداگانه برای ارسال POST به صورت GET در نظر گرفته شده .
$mysqli = new mysqli("localhost", "root", "", "api");
if ($mysqli->connect_error) {
die("MYSQL ISSUE : " . $mysqli->connect_error);
}
$mysqli->set_charset("utf8");
$username = $_GET['username'];
$password = $_GET['password'];
$query = "SELECT * FROM `my_tbl` WHERE username='$username' AND password='$password' LIMIT 1";
$row = [];
if ($res = $mysqli->query($query)) {
if ($res->num_rows) {
while ($row_loop = $res->fetch_row()) {
$row = $row_loop;
}
}
$res->close();
}
echo $row ? "Access Granted" : "Access Denied";
$mysqli->close();
کد ایمن در برابر SQLi با استفاده از stmt
انجمن تحقیقاتی و امنیتی owasp با توجه به موضوع sql inejction توصیه می کند که از mysqli یا PDO کمک گرفته و حتما از stmt استفاده کنید .
با استفاده از stmt دیگر باگ SQLi رخ نخواهد داد کد نمونه زیر :
$mysqli = new mysqli("localhost", "root", "", "api");
if ($mysqli->connect_error) {
die("MYSQL ISSUE : " . $mysqli->connect_error);
}
$mysqli->set_charset("utf8");
$stmt = $mysqli->stmt_init();
$username = $_GET['username'];
$password = $_GET['password'];
$query = "SELECT * FROM `my_tbl` WHERE username=? AND password=? LIMIT 1";
$stmt->prepare($query);
$stmt->bind_param('ss' , $username , $password);
$row = [];
if ($stmt->execute() && $res = $stmt->get_result()) {
if ($stmt->affected_rows || $res->num_rows) {
while ($row_loop = $res->fetch_assoc()) {
$row = $row_loop;
}
}
}
echo $row ? "Access Granted" : "Access Denied";
$mysqli->close();
ارسال نظر