Что касается многих полезных ответов, я надеюсь добавить некоторую ценность этой теме.
SQL-инъекция - это атака, которая может быть осуществлена через пользовательские вводы (вводы, которые заполняются пользователем, а затем используются внутри запросов). Шаблоны SQL-инъекций - это правильный синтаксис запросов, хотя мы можем его назвать: плохие запросы по плохим причинам, и мы предполагаем, что может быть плохой человек, который пытается получить секретную информацию (в обход контроля доступа), которая затрагивает три принципа безопасности (конфиденциальность) , целостность и доступность).
Теперь наша цель - предотвратить угрозы безопасности, такие как атаки с использованием SQL-инъекций, задать вопрос (как предотвратить атаку с использованием SQL-кода с использованием PHP), быть более реалистичным, фильтрация или очистка входных данных - это тот случай, когда пользовательские данные вводятся внутрь. такой запрос, использующий PHP или любой другой язык программирования, не соответствует действительности, или как многие люди рекомендуют использовать современные технологии, такие как подготовленные операторы или любые другие инструменты, которые в настоящее время поддерживают предотвращение SQL-инъекций, считаете, что эти инструменты больше не доступны? Как вы защищаете свое приложение?
Мой подход против внедрения SQL-кода: очистка данных, вводимых пользователем, перед отправкой в базу данных (перед использованием в любом запросе).
Фильтрация данных для (преобразования небезопасных данных в безопасные данные)
Учтите, что PDO и MySQLi недоступны. Как вы можете защитить свое приложение? Вы заставляете меня использовать их? А как насчет других языков, кроме PHP? Я предпочитаю давать общие идеи, так как они могут быть использованы для более широкой границы, а не только для конкретного языка.
- Пользователь SQL (ограничение привилегий пользователя): наиболее распространенными операциями SQL являются (SELECT, UPDATE, INSERT), тогда зачем давать привилегию UPDATE пользователю, который в этом не нуждается? Например, страницы входа и поиска используют только SELECT, тогда зачем использовать пользователей БД на этих страницах с высокими привилегиями?
ПРАВИЛО: не создавайте одного пользователя базы данных для всех привилегий. Для всех операций SQL вы можете создать свою схему, такую как (deluser, selectuser, updateuser) в качестве имен пользователей для простоты использования.
Смотрите принцип наименьших привилегий .
Фильтрация данных: перед созданием любого пользовательского ввода запроса его следует проверить и отфильтровать. Для программистов важно определить некоторые свойства для каждой пользовательской переменной:
тип данных, шаблон данных и длина данных . Поле, которое является числом между (x и y), должно быть точно проверено с использованием точного правила, а для поля, которое является строкой (текст): шаблон имеет место, например, имя пользователя должно содержать только несколько символов, давайте скажем [a-zA-Z0-9_-.]. Длина варьируется между (x и n), где x и n (целые числа, x <= n).
Правило: создание точных фильтров и правил проверки - лучшие практики для меня.
Используйте другие инструменты: Здесь я также согласен с вами в том, что подготовлены оператор (параметризованный запрос) и хранимые процедуры. Недостатки здесь в том, что эти способы требуют продвинутых навыков, которых нет у большинства пользователей. Основная идея здесь состоит в том, чтобы различать SQL-запрос и данные, которые используются внутри. Оба подхода могут использоваться даже с небезопасными данными, потому что вводимые пользователем данные здесь ничего не добавляют к исходному запросу, например (any или x = x).
Для получения дополнительной информации, пожалуйста, прочитайте OWASP Шпаргалку по предотвращению инъекций .
Теперь, если вы опытный пользователь, начните использовать эту защиту по своему усмотрению, но для новичков, если они не могут быстро реализовать хранимую процедуру и подготовить оператор, лучше отфильтровать входные данные, насколько это возможно.
Наконец, давайте рассмотрим, что пользователь отправляет этот текст ниже вместо ввода своего имени пользователя:
[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'
Этот вход можно проверить заранее без каких-либо подготовленных операторов и хранимых процедур, но для большей безопасности их использование начинается после фильтрации и проверки пользовательских данных.
Последний пункт - обнаружение неожиданного поведения, которое требует больших усилий и сложности; это не рекомендуется для обычных веб-приложений.
Неожиданным поведением в вышеприведенном вводе пользователя является SELECT, UNION, IF, SUBSTRING, BENCHMARK, SHA и root. Как только эти слова обнаружены, вы можете избежать ввода.
ОБНОВЛЕНИЕ 1:
Пользователь прокомментировал, что этот пост бесполезен, хорошо! Вот что предоставил OWASP.ORG :
Первичная защита:
Опция № 1: Использование подготовленных выражений (параметризованных запросов)
Опция №2: Использование хранимых процедур
Опция №3: Экранирование всего введенного пользователем ввода
Дополнительные защиты:
Также Принудительно: Наименьшая привилегия
Также Выполнить: Проверка ввода белого списка
Как вы, возможно, знаете, утверждение статьи должно быть подтверждено действительным аргументом, хотя бы одной ссылкой! В противном случае это считается атакой и плохим требованием!
Обновление 2:
Из руководства по PHP, PHP: Подготовленные заявления - Руководство :
Экранирование и внедрение SQL
Связанные переменные будут автоматически экранированы сервером. Сервер вставляет свои экранированные значения в соответствующих местах в шаблон оператора перед выполнением. Подсказка должна быть предоставлена серверу для типа связанной переменной, чтобы создать соответствующее преобразование. Смотрите mysqli_stmt_bind_param () для получения дополнительной информации.
Автоматическое экранирование значений на сервере иногда считается функцией безопасности для предотвращения внедрения SQL. Та же степень безопасности может быть достигнута с помощью неподготовленных операторов, если входные значения экранированы правильно.
Обновление 3:
Я создал контрольные примеры, чтобы узнать, как PDO и MySQLi отправляют запрос на сервер MySQL при использовании подготовленного оператора:
PDO:
$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));
Журнал запросов:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
189 Quit
MySQLi:
$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();
Журнал запросов:
188 Prepare SELECT * FROM awa_user WHERE username =?
188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\''
188 Quit
Понятно, что готовое заявление также ускользает от данных, ничего больше.
Как также упоминалось в приведенном выше заявлении,
Автоматическое экранирование значений на сервере иногда считается функцией безопасности для предотвращения внедрения SQL. Та же степень безопасности может быть достигнута с помощью неподготовленных операторов, если входные значения экранированы правильно
Следовательно, это доказывает, что проверка данных, например, intval()
является хорошей идеей для целочисленных значений перед отправкой любого запроса. Кроме того, предотвращение злонамеренных пользовательских данных перед отправкой запроса является правильным и корректным подходом .
Пожалуйста, посмотрите этот вопрос для более подробной информации: PDO отправляет необработанный запрос в MySQL, в то время как Mysqli отправляет подготовленный запрос, оба дают одинаковый результат.
Ссылки:
- Шпаргалка по SQL-инъекциям
- SQL-инъекция
- Информационная безопасность
- Принципы безопасности
- Валидация данных