Ответ
SQL-инъекция (SQL Injection) — это тип атаки на базу данных, при которой злоумышленник внедряет вредоносный SQL-код в запрос через входные данные, передаваемые приложением.
Это происходит, когда приложение напрямую конкатенирует (склеивает) строки для формирования SQL-запроса, не проверяя и не экранируя пользовательский ввод.
Пример уязвимого кода на Go:
// НЕ ДЕЛАЙТЕ ТАК!
userInput := "' OR 1=1 --"
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userInput)
// Запрос превратится в:
// SELECT * FROM users WHERE name = '' OR 1=1 --'
// Условие `OR 1=1` всегда истинно, а `--` комментирует остаток запроса.
// В результате будут выбраны ВСЕ пользователи из таблицы.
rows, err := db.Query(query)
Как защититься: основной метод
Используйте параметризованные запросы (Prepared Statements).
Это самый надежный способ. Суть в том, что SQL-запрос и данные передаются в базу данных раздельно. Сначала отправляется шаблон запроса с плейсхолдерами (? или $1, $2 в зависимости от СУБД), а затем — значения для этих плейсхолдеров. Драйвер базы данных сам безопасно подставляет данные, не интерпретируя их как часть SQL-кода.
Пример безопасного кода:
// Используем плейсхолдер `?` для MySQL или `$1` для PostgreSQL
query := "SELECT * FROM users WHERE username = ? AND password = ?"
username := "admin"
password := "some_password"
// Данные передаются как отдельные аргументы в Query() или Exec()
// Драйвер сам позаботится о безопасной подстановке
rows, err := db.QueryContext(ctx, query, username, password)
Другие методы защиты
- Использование ORM: Библиотеки вроде GORM или sqlx по умолчанию используют параметризованные запросы под капотом, что делает код более безопасным.
- Валидация и очистка ввода (Sanitization): Всегда проверяйте, что пользовательский ввод соответствует ожидаемому формату (например, что ID — это число, а email — валидный адрес). Это дополнительный слой защиты.
- Принцип наименьших привилегий: Пользователь БД, от имени которого приложение выполняет запросы, должен иметь только необходимые права (например, только
SELECT,INSERT,UPDATEна конкретные таблицы, но неDROP).
Ответ 18+ 🔞
А, SQL-инъекция! Ну это классика, блядь, как "Муму" у Тургенева, только грустнее, потому что твою базу данных могут утопить, а ты потом будешь метаться и орать "Бля, что я, мудак, сделал?!"
Смотри, в чём суть, ёпта. Представь, твоё приложение — это Герасим, здоровый, но немой чувак, который выполняет команды. А злоумышленник — это хитрая жопа, которая шепчет ему на ухо не "Муму", а какую-нибудь пиздопроебибну вроде ' OR 1=1 --.
Вот как это выглядит в коде, если ты распиздяй:
// НЕ ДЕЛАЙ ТАК, А ТО ПИЗДЕЦ!
userInput := "' OR 1=1 --"
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userInput)
// И что у нас получится? А получится пиздец!
// SELECT * FROM users WHERE name = '' OR 1=1 --'
Видишь? Он подсунул Герасиму (то есть твоей БД) такую команду, что условие OR 1=1 всегда истинно, а -- всё остальное закомментирует. И Герасим, вместо одной записи, вывалит тебе ВСЮ таблицу пользователей нахуй! А там и пароли, и почты — овердохуища приватной инфы.
Так как же защититься, чтобы не быть мудаком?
Основной метод — это параметризованные запросы (Prepared Statements). Это как если бы Герасиму дали чёткий, заранее подготовленный шаблон действия, а данные подсовывали отдельно, в специальные карманы. Он уже не перепутает, где команда, а где просто значение.
Вот безопасный код, красава:
// Используем плейсхолдер `?`. Это как карман для данных.
query := "SELECT * FROM users WHERE username = ? AND password = ?"
username := "admin"
password := "some_password"
// А вот сюда суём данные в эти карманы. Драйвер БД сам всё безопасно подставит.
// Никакой самодеятельности, никакого "Муму" от пользователя!
rows, err := db.QueryContext(ctx, query, username, password)
Драйвер базы — он умный, он не даст данным влезть в сам SQL-код. Это как если бы Герасиму сказали: "Вот тебе мешок, положи туда кирпич". Он положит кирпич, а не начнёт орать "Муму" и кидаться этим мешком в озеро.
Ещё пара советов, для полного счастья:
- Используй ORM (типа GORM). Это как нанять для Герасима умного переводчика, который сам формирует безопасные команды. Удобно, но иногда этот переводчик такое наговорит, что сам от себя охуеешь.
- Валидируй всё, что вводит пользователь. Если ждёшь число — проверь, что это число, а не "хуй с горы". Если email — что это похоже на email. Лишний раз не помешает.
- Принцип наименьших привилегий. Зачем давать пользователю БД от приложения права на
DROP TABLE? Это всё равно что дать Герасиму динамит, когда он должен только полить садок. Дай ему толькоSELECT,INSERTиUPDATEна нужные таблицы — и спи спокойно.
Короче, чувак, не склеивай строки для SQL. Используй подготовленные запросы. А то будет тебе трагедия, как у Тургенева, только без высокой литературы, а с одним сплошным "вротберунчик" от начальства.