SQL инъекции и какие есть заблуждения в устранении её

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

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

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

Условный пример: • SELECT * FROM users WHERE username = '$username' AND password = '$password';

Если в username передать: • ' OR 1=1; --

то итоговая логика запроса может измениться: • SELECT * FROM users WHERE username = '' OR 1=1; --' AND password = '...'

Здесь OR 1=1 делает условие истинным, а -- комментирует остаток запроса, чтобы не получить синтаксическую ошибку.

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

━━━━━━━━━━ Какие бывают SQLi ━━━━━━━━━━

Если коротко, SQL-инъекции можно разделить на видимые и слепые.

➤ UNION-based SQLi Когда результат запроса возвращается в ответе, мы можем использовать UNION, чтобы добавить к легитимной выборке данные из других таблиц.

➤ Error-based SQLi Когда приложение или БД возвращают ошибки, через них можно вытягивать структуру или данные.

➤ Boolean-based blind SQLi Когда данные не отображаются напрямую, но можно задавать вопросы в стиле “истина / ложь” и по разнице в ответе постепенно восстанавливать данные.

➤ Time-based blind SQLi Похожая история с булевым значением, но вместо разницы в содержимом используется задержка, например через sleep.

➤ Out-of-band SQLi Когда результат уходит не в HTTP-ответ, а через внешний канал, например DNS/HTTP-запрос от БД на контролируемый сервер.

━━━━━━━━━━ Где изучать глубже ━━━━━━━━━━

Во все времена и все советуют ресурс — PortSwigger Web Security Academy.

Там можно не просто прочитать про SQLi, но и порешать лабы: ➥ https://portswigger.net/web-security/sql-injection

━━━━━━━━━━ Главное заблуждение при фиксе ━━━━━━━━━━

Много где пишут: “используйте параметризованные запросы”. И это от части правильный совет.

Но важно понимать нюанс: ➤ параметры защищают значения, но не защищают структуру SQL-запроса.

То есть вот так — хорошо: • WHERE username = ?

А вот так — уже плохо: • ORDER BY + userInput • SELECT * FROM + tableName • WHERE + rawCondition

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

━━━━━━━━━━ Где параметризация ломается ━━━━━━━━━━

➤ Динамический ORDER BY Плохая идея: • ORDER BY + sort Если пользователь может передать sort, он влияет на структуру запроса.

➤ Динамическое имя таблицы или колонки Плохо: • SELECT * FROM + tableName Параметры обычно не предназначены для подстановки имён таблиц и колонок.

➤ Часть WHERE собирается строкой Плохо: • WHERE status = ? AND + filter Даже если часть запроса параметризована, небезопасный кусок строки может вернуть SQLi обратно.

➤ Stored Procedures не всегда безопасны Stored procedure сама по себе не гарантирует защиту. Если внутри процедуры есть dynamic SQL и склейка строк, проблема остаётся: • EXEC('SELECT * FROM users WHERE name = ''' + @name + '''')

➤ ORM тоже не панацея ORM безопасен, пока используется его нормальные методы. Но как только начинается: • raw() • createQuery() • query("SELECT ... " + userInput) то мы вновь собираем SQL запрос и можем получить ту же самую SQL-инъекцию.

━━━━━━━━━━ Как защищаться нормально ━━━━━━━━━━

Минимальный набор: • параметризованные запросы для значений • никакой склейки пользовательского ввода с SQL • белые списки ввода пользователя • осторожность с raw SQL и stored procedures • минимум прав у пользователя БД • тесты на инъекции в критичных ручках

#AppSec #SQLi #SQLInjection #Pentest #CyberSecurity #OWASP #Portswigger #IT

SQL инъекции и какие есть заблуждения в устранении её | Сетка — социальная сеть от hh.ru