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



@Sazanovdm

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

Вопрос состоит лишь в том, имеет ли смысл делать кукую-либо защиту от SQL инъекций, т.к. если я правильно понимаю на UPDATE запросы они не распространяются?


Решения вопроса 4



@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]);

— просто, быстро, удобно и безопасно



26

комментариев


Ответы на вопрос 0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *