2. Конкатенация и логика БД
Конкатенация и логика БД: Магия OR 1=1
Конструкция OR 1=1 стала своего рода мемом в ИБ, но её эффективность от этого не уменьшилась. Это фундаментальный пример манипуляции логикой запроса: хакер добавляет условие, которое всегда истинно, заставляя базу игнорировать проверку пароля.
Эта техника настолько фундаментальная, что попала в массовую культуру: в комиксе xkcd #327 «Exploits of a Mom» героиня называет сына Robert'); DROP TABLE Students;--, и весь интернет-юмор про "Little Bobby Tables" родом отсюда. За шуткой стоит реальная статистика: по данным Verizon Data Breach Investigations Report 2023, SQL-инъекции остаются одним из топ-5 векторов атаки на веб-приложения, и подавляющее большинство успешных инъекций — это базовый OR 1=1 или его вариации против форм аутентификации.
Аналогия: представь автоматический шлагбаум на въезде в закрытый посёлок. Охранник принимает QR-код от посетителя, сканер проверяет «есть ли такой код в базе разрешённых». Если разработчик системы написал проверку как «впусти, если код есть в списке ИЛИ если на улице день», то любой посетитель днём может проехать без QR — потому что условие «на улице день» всегда истинно с 9 до 17. SQL-инъекция через OR 1=1 работает ровно так же: атакующий дописывает условие, которое математически не может быть ложным, и WHERE-фильтр перестаёт фильтровать.
Изучим механику этого приема и поймем, как он работает на уровне математической логики SQL.
1. Механика: "ИЛИ ВСЕГДА ВЕРНО"
Сейчас увидим, как одна-единственная незащищённая кавычка превращает обычный SQL-запрос в чёрный ход. Разработчик пишет код проверки логина так, как ему диктует учебник «getting started»: возьми из формы username и password, подставь в строку запроса, выполни. Никаких атак не предполагается — кто будет ломать тестовый CRUD? Реальность в том, что любой production-сайт получает сканирование на инъекции в первые 24 часа после публикации DNS-записи.
Представьте запрос в Go-коде:
SELECT id FROM users WHERE username = '%s' AND password = '%s' (через fmt.Sprintf).
Хакер вводит в поле username: ' OR '1'='1. Пароль может быть любым.
Как это видит SQL-парсер:
WHERE username = '' OR '1'='1' AND password = 'любое_слово'
Условие '1'='1' всегда истинно.
Согласно приоритетам SQL (сначала AND, потом OR), логика запроса превращается в:
(username = '') OR ('1'='1' AND password = '...')
...что почти всегда равно Истине для каждой строки в базе!
Особо важный момент: WHERE-выражение работает как фильтр для КАЖДОЙ строки таблицы. Если для строки выражение вернуло TRUE — строка попадает в результат. Когда мы превращаем условие в тавтологию OR '1'='1', выражение становится TRUE для каждой строки без исключения. Поэтому SELECT возвращает всех пользователей сразу. Большинство Go-приложений в логике аутентификации используют что-то вроде if rows.Next() { ... успешный логин ... } — то есть берут первую попавшуюся строку. По принципу B-tree индекса, первой обычно идёт строка с самым низким ID, а это, как правило, администратор системы (тот, кого первым создали при инициализации БД). Поздравляем, атакующий вошёл как admin без знания пароля.
2. Логическая таблица: Как хакер обходит проверку
| Условие 1 (Username) | Условие 2 (Password) | Итог (AND) | Итог (OR 1=1) |
|---|---|---|---|
| ✅ Верный | ✅ Верный | ✅ TRUE | ✅ TRUE |
| ❌ Неверный | ❌ Неверный | ❌ FALSE | ✅ TRUE (благодаря OR) |
| ❌ Неверный | ✅ Верный | ❌ FALSE | ✅ TRUE (благодаря OR) |
| ✅ Верный | ❌ Неверный | ❌ FALSE | ✅ TRUE (благодаря OR) |
3. Почему это фатальная ошибка?
Если ваш SQL-запрос выполняется через конкатенацию, хакер больше не борется с вашей базой — он просто дописывает за вас команду. Вместо поиска конкретного пользователя, база ищет ЛЮБОГО пользователя, для которого условие истинно. А раз '1'='1' — это всегда правда, база вернет первого попавшегося (администратора).
Производный класс атак: «authentication bypass through stacked OR». Если форма проверяет WHERE username = '%s' AND password_hash = '%s', атакующий подаёт username = admin' --, и SQL превращается в WHERE username = 'admin' --' AND password_hash = '...'. Двойной дефис -- начинает SQL-комментарий, и всё после него игнорируется. База ищет просто пользователя admin, без проверки пароля. Это даже не требует знания того, что в базе вообще есть пользователь — достаточно угадать роль (admin / root / superuser встречаются в 90% систем).
4. Как проверить из Go-кода (Индикаторы)
Вы можете заметить атаку по логам: если в логах вашего веб-сервера мелькают странные запросы с одиночными кавычками и словами OR, AND, UNION — кто-то прямо сейчас пытается "нащупать" уязвимость в ваших формах.
Но детекция через логи — это уже реактивный подход, когда атака случилась. Превентивная защита заключается в одной простой замене паттерна: вместо db.Query(fmt.Sprintf(...)) всегда писать db.Query("SELECT ... WHERE name = ?", username). В Go-стандартной библиотеке параметризация работает одинаково для всех СУБД через драйверы — database/sql сам преобразует плейсхолдер в нужный диалект (? для MySQL/SQLite, $1 для PostgreSQL). Эта замена не требует ни новых библиотек, ни специальных знаний — только дисциплины.
Linter gosec ловит большинство случаев fmt.Sprintf с SQL-подобными строками через правило G201. CI/CD-пайплайн с gosec ./... на каждом PR закрывает 95% таких ошибок ещё на этапе ревью. Бонус: ревьюер видит alert в PR description, и привычка «параметризуй или объясни почему нет» закрепляется в команде.
Логическая инъекция — это манипуляция истинностью. Хакеру не нужен ваш пароль, если он может сделать так, чтобы базе он был не нужен.
Соответствие стандартам и регуляторам: OWASP Top 10 A03:2021 Injection, #3 в списке; CWE-89 SQL Injection (Top 25 Most Dangerous Software Weaknesses); CAPEC-66 «SQL Injection» как pattern атаки; PCI-DSS 6.5.1 обязывает защиту от инъекций для систем, обрабатывающих карточные данные. GDPR Article 32 «Security of Processing» — нарушение через OR 1=1 с эксфильтрацией персональных данных может привести к штрафу до 4% годового оборота. Известный кейс — TalkTalk 2015 года: подросток с базовыми знаниями SQLi скомпрометировал 4 миллиона записей через простую OR 1=1 инъекцию, компания получила штраф £400 тысяч и потеряла £77 миллионов рыночной капитализации.
Чтобы атака была успешной, хакеру часто нужно избавиться от «хвоста» оригинального запроса. Для этого используются комментарии.
Продолжить чтение
Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу
Когда закончишь — отметь раздел, чтобы продолжить.