Я знаком с подготовленными заявлениями, и я знаю, что они лучше всего подходят для защиты от MySQL-инъекций. Но мне интересно, как это заявление PHP / MySQL может подвергаться риску инъекции:
$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".$_POST['name']."';");
Мне кажется, что вход пользователя будет содержаться внутри одинарных кавычек. Можете ли вы выполнить несколько запросов в одном операторе mysqli_query
?
Кроме того, сделать выше безопасным так же просто, как это …
$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".mysqli_real_escape_string($_POST['name'])."';");
Мне кажется, что вход пользователя будет содержаться внутри одиночных кавычек
Это произойдет, если вы не включите одинарные кавычки в опубликованное name
, что позволит вам выйти из кавычек. Например, опубликуйте имя как:
' or 1 or '
Предложение WHERE становится:
WHERE id = '' or 1 or '';
Это будет соответствовать и извлекать все строки в таблице из-за одной or 1
части. Как вы можете видеть, он вырывается из кавычек для ввода некоторого SQL, затем он возвращается в кавычки, чтобы сделать запрос действительным.
Можете ли вы выполнить несколько запросов в одном операторе
mysqli_query
?
Нет, но если он был выполнен с помощью mysqli_multi_query
тогда да, вы могли бы добавить несколько запросов к концу.
делает вышеперечисленное безопасным так же просто, как
mysqli_real_escape_string
?
В общем, да, но подготовленное заявление было бы лучше. Используя escaping, WHERE
станет (используя мой пример выше):
WHERE id = '\' or 1 or \'';
Это уже не уязвимо, потому что кавычки не могут быть разбиты и будут соответствовать только строкам, если name
буквально соответствует ' or 1 or '
что явно маловероятно.
Мне кажется, что вход пользователя будет содержаться внутри одиночных кавычек
Все, что должен сделать атакующий, – это поставить одну цитату внутри имени POST, и ее больше не будет.
name=' OR 1=1
Кроме того, сделать вышеуказанный сейф так же просто, как это
Это выглядит хорошо … но мне больно. Используйте подготовленные заявления. Их гораздо легче читать, чем SQL, построенных путем объединения строк вместе.
Основное объяснение:
Если вы просто введете $_POST['name']
в запрос в соответствии с вашим первым примером, результирующая строка SQL будет недействительной, если переменная name
содержит одиночный символ кавычки.
Это будет немедленно раздражать любого, кто по имени О'Брайен, или что-то подобное.
Но это может быть использовано хакером, который может изменить свое «имя», чтобы включить действительный код SQL после одиночной кавычки. Это может быть любой допустимый SQL, позволяющий хакеру что-либо делать с вашей БД или запрашивать что-нибудь от него. То, что он может сделать, будет зависеть от других факторов вашего кода, но достаточно сказать, что даже в лучшем случае он мог бы сделать некоторые довольно разрушительные вещи.
Чтобы ответить на ваш второй вопрос: Да. mysqli_real_escape_string()
с помощью mysqli_real_escape_string()
уменьшит эту проблему.
Однако, чтобы сделать что-то еще на один шаг, вам также может потребоваться расследовать использование подготовленных запросов, что является функцией расширения mysqli
. Это может сделать ваш код намного опрятным, поскольку он избегает необходимости использовать это mysqli_real_escape_string()
длинное mysqli_real_escape_string()
функции mysqli_real_escape_string()
повсюду. Он также имеет другие преимущества, такие как улучшенное кэширование запросов.
Надеюсь, что это поможет ответить на вопрос.
Что, если я передал следующее значение для $_POST['name']
?
'; DELETE FROM users WHERE name <> '
Я бы закрыл первую одинарную цитату, а затем представил повреждающий запрос, который в конце концов имеет только одну открытую цитату, которая будет закрыта одинарной цитатой в исходном запросе.
Второй запрос в порядке. Хотя вы действительно должны рассмотреть использование подготовленных операторов (которые поддерживаются mysqli)
Если вы используете mysqli
вы всегда должны использовать метод SQL-заполнителя для этого. Функции экранирования – это трудный путь.
$stmt = $db->prepare("SELECT name FROM users WHERE id = ?"); $stmt->bind_param('i', $_POST['name']); $stmt->execute();
Если вы не понимаете риска здесь, вам действительно нужно прочитать об атаках SQL-инъекций в целом и прочитать, какие автоматические инструменты взлома могут сделать для тех, которые недостаточно осторожны.