Дан кусок SQL: query = "SELECT * FROM users WHERE name = '" + name + "'"; — объясните уязвимость, возможные последствия и конкретные способы исправления для разных СУБД

18 Фев в 14:15
17 +1
1
Ответы
1
Уязвимость
- Код строит SQL через конкатенацию:
query = "SELECT * FROM users WHERE name = '" + name + "'";
Это — классическая SQL‑инъекция: attacker управляет переменной namenamename и может изменить структуру запроса.
Пример эксплуатации
- Если name=name = name= ′′OR′1′=′1′'' OR '1'='1'′′OR1=1 результат запроса становится всегда истинным и вернёт все записи.
- Более вредоносно: name=name = name= ′′;DROPTABLEusers;−−''; DROP TABLE users; --′′;DROPTABLEusers; — может удалить таблицу (если СУБД и контекст позволяют).
Возможные последствия
- Чтение конфиденциальных данных (утечка пользователей, паролей, кредитных карт).
- Модификация/удаление данных (INSERT/UPDATE/DELETE, DROP).
- Проброс команд, выполнение нескольких запросов (в СУБД, поддерживающих многоинструкционный SQL).
- Аутентификация/эскалация прав (bypass логина).
- Диверсия на ОС (в определённых конфигурациях, через расширения) и RCE.
- Длительные простои, компрометация целостности и соответствия.
Конкретные способы исправления (по СУБД / платформам)
Общее правило: не конкатенировать строки — использовать параметризованные запросы (prepared statements / bind parameters), проверку и минимальные привилегии.
1) MySQL (PHP, Java, Python и др.)
- PHP PDO (рекомендуется):
- $stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->execute(['name' => $name]);
- mysqli (если нельзя PDO): использовать подготовленные выражения или как минимум mysqli_real_escape_string (крайний случай).
- Java JDBC:
- PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
ps.setString(1, name);
- Python (mysqlclient / PyMySQL / mysql-connector):
- cursor.execute("SELECT * FROM users WHERE name = %s", (name,))
2) PostgreSQL
- psycopg2:
- cur.execute("SELECT * FROM users WHERE name = %s", (name, ))
- Java JDBC — тоже PreparedStatement.
- Никогда не подставлять параметры через текст запроса; для динамических идентификаторов (имя таблицы/столбца) — использовать жёсткий белый список.
3) Microsoft SQL Server
- ADO.NET:
- using (var cmd = new SqlCommand("SELECT * FROM users WHERE name = @name", conn)) { cmd.Parameters.AddWithValue("@name", name); ... }
- Для динамического SQL — использовать sp_executesql с параметрами:
- EXEC sp_executesql N'SELECT * FROM users WHERE name = @name', N'@name nvarchar(100)', @name = @p0;
- Не разрешать прямую конкатенацию строк для SQL.
4) Oracle
- cx_Oracle (Python) / OCI / JDBC:
- cursor.execute("SELECT * FROM users WHERE name = :name", {"name": name})
- Использовать привязки (bind variables).
5) SQLite
- Python sqlite3:
- cur.execute("SELECT * FROM users WHERE name = ?", (name,))
- Для других языков — аналогичные bind placeholders.
Дополнительные рекомендации (все СУБД)
- Валидировать вход: для ожидаемых форматов (email, id) — применять белые списки/регулярные выражения. Для идентификаторов (имя таблицы/столбца) — разрешать только заранее определённые значения.
- Принцип наименьших привилегий: аккаунт БД для приложения не должен иметь прав DROP/ALTER/ADMIN, если это не нужно.
- Логирование и мониторинг подозрительных запросов.
- Использовать ORM/Query builders — но проверять, что они корректно параметризуют запросы.
- Если невозможно параметризовать (напр. динамические имена столбцов), тщательно валидировать/включать в белый список.
- Экранирование (escape) — только как временная мера; bind‑параметры предпочтительнее.
Краткое резюме
- Уязвимость: SQL‑инъекция из‑за конкатенации строк.
- Исправление: всегда использовать параметризованные запросы / bind variables; дополнительно — валидация, белые списки для идентификаторов, минимальные привилегии и мониторинг.
18 Фев в 14:20
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир