SQL инъекция в UPDATE возможна ли?

Есть запрос формата:
UPDATE table SET test WHERE id = $id

Вопрос состоит лишь в том, имеет ли смысл делать кукую-либо защиту от SQL инъекций, т.к. если я правильно понимаю на UPDATE запросы они не распространяются?
  • Вопрос задан
  • 595 просмотров
Решения вопроса 4
FanatPHP
@FanatPHP
Помогаю и новичкам, и старичкам
Инъекция может быть через любой запрос.
И защищать тоже надо любые запросы.
Никогда не надо торговаться, "а можно я не буду защищать именно этот запрос? Ну мааааам!"
Надо просто всегда следовать простым правилам - любая переменная попадает в запрос только через плейсхолдер

Важно понимать, что в рассуждениях про инъекции люди постоянно путают два понятия - самой уязвимости, и конкретных способов ей воспользоваться.

Уязвимость — это сама возможность с помощью переданных в запрос данных изменить его код.
Даже если ты не знаешь ни одного способа ей воспользоваться, уязвимость от этого никуда не девается.
Даже если та возможность, про которую ты знаешь, в данном случае не прокатит - остаются ещё тысячи других.
Если есть уязвимость, то способы ей воспользоваться всегда найдутся.

То есть сама уязвимость никак не зависит ни от каких второстепенных факторов - типа запроса, передаваемых данных, способов их валидации, твоих знаний SQL. Это сам факт. Можно подставить свой код в запрос? Значит он уязвим. А как конкретно можно нагадить - это отдельная тема.

Кроме того, любая уязвимость - это всегда ошибки. Если в $id будет пусто, то запрос вызовет ошибку. Если в $id будет слово select то запрос вызовет ошибку. Если будет слово "привет", то запрос вызовет ошибку. Оно тебе надо?

При этом разных вариантов возможных ошибок и способов воспользоваться уязвимостью - тысячи, им посвящены целые учебники и статьи. Но для того чтобы защищаться, не надо знать ни одного. Потому что защищаться надо не от отдельных способов эксплуатации, а закрывать саму уязвимость. И сделать это очень просто:
  1. Любые данные должны добавляться в запрос только через плейсхолдеры
  2. Любые другие элементы запроса должны выбираться из белого списка - заранее прописанных в нашем коде значений.


Если вопрос "а можно я не буду защищаться?" вызван ленью, то это тоже решаемо. В принципе, лень - это очень важное качество для программиста. Главное - направить её в нужное русло.

Если каждый раз писать по три строчки долго
$sql = "INSERT INTO users SET email = ?, password = ?"; // заменяем на знаки вопроса
$stmt = $db->prepare($sql); // подготавливаем запрос, получаем stmt
$stmt->bind_param("ss", $email, $hash); // два знака вопроса - две переменных - две буквы s
$stmt->execute(); // выполняем запрос

То надо воспользоваться такой вещью, как программирование. И написать функцию, которая возьмет на себя всю рутинную работу.
function prepared_query($mysqli, $sql, $params, $types = "")
{
    $types = $types ?: str_repeat("s", count($params));
    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    return $stmt;
}

и в итоге предыдущие 4 строчки превратятся в одну:
prepared_query($db, "INSERT INTO users SET email = ?, password = ?", [$email, $hash]);

или твой запрос:
prepared_query($db, "UPDATE table SET test WHERE id = ?", [$id]);

- просто, быстро, удобно и безопасно
Ответ написан
Fernus
@Fernus
Техник - Механик :)
Смысл есть!

UPD:
Поясню...я тебе в $id передам 9999 or 1 = 1 и все записи нафиг потерпят изменения!
Ответ написан
BojackHorseman
@BojackHorseman Куратор тега PHP
...в творческом отпуске...
возможна. распространяются. обязательно
Ответ написан
AndyPike
@AndyPike
Программист, full-stack developer.
Точку с запятой можно впендюрить и продолжать запрос.
UPDATE table SET test WHERE id = 0; DELETE * FROM users;
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы