#php #sql-injection #code-injection
#php #sql-инъекция #внедрение кода
Вопрос:
Если у меня есть php-файл, который получает $ _GET[‘value’], безопасно ли запускать мой php-файл с помощью sql-инъекции или code-injection
if (in_array($_GET['value'], $allowed_values);)
{ /* normal pa&e code handlin& the $_GET['value'] */
} else { unset($_GET['name'])
}
$allowed values — это, очевидно, массив всех значений, которые я ожидаю как безопасные для $_Get[‘value’]. Это все еще небезопасно? Спасибо.
Комментарии:
1. В зависимости от значений в
$allowed_values
и фактического кода, который у вас есть, но да. Когда вы можете ограничить ввод таким образом, и возможные значения не могут быть использованы для внедрения кода / sql-инъекции, тогда это save .2. Да, но не явно. Это форма проверки ваших входных данных, и это то, что вы всегда должны делать, но технически это ничего не делает для предотвращения SQL-инъекции на техническом уровне. Например, если одно из ваших значений allow было на самом деле
' or 1=1--
, оно все равно было бы введено, по сравнению с использованием параметров для фактического запрета SQL-инъекции.3. Вам нужно выработать привычку принимать ответы , которые помогут вам решить ваши проблемы. Вы будете зарабатывать очки, и другим будет предложено помочь вам.
Ответ №1:
Да, это распространенный и безопасный метод, который можно использовать в ситуациях, когда параметры запроса не могут быть использованы. Например, если значение будет использоваться как имя таблицы или столбца, вы не можете предоставить его в качестве параметра запроса, вам придется подставлять его непосредственно в строку SQL. Подобный белый список является рекомендуемым способом убедиться, что это безопасно.
Ответ №2:
Это зависит от значений в $allowed_values
массиве и от того, как вы интерполируете значение в свой SQL-запрос.
Например:
$allowed_values = [ 'a word' ];
if (in_array($_GET['value'], $allowed_values)) {
$sql = "SELECT * FROM mytable WHERE id = {$_GET['value']};";
}
Определенно небезопасно. Это приводит к SQL:
SELECT * FROM mytable WHERE id = a word;
Это синтаксическая ошибка.
Почему бы вам просто не использовать параметры SQL-запроса? Тогда вам не нужно беспокоиться, безопасно это или нет. Параметры запроса отделяют значения от синтаксического анализа SQL, поэтому никакое значение не может вызвать SQL-инъекцию.
Вам не обязательно иметь $allowed_values
массив. Вам не нужно будет проверять, находится ли ввод GET в массиве. Вам не придется беспокоиться о кавычках или экранировании.
Верно, что параметры запроса работают только для значений, которые находятся вместо строкового литерала в кавычках или литерала даты-времени в кавычках или числового литерала. Если вам нужно, чтобы другие части вашего запроса были динамическими, например, имя таблицы или столбца или ключевые слова SQL и т.д., Тогда используйте решение с разрешенным списком, подобное тому, которое вы показываете.
Но более распространенный случай интерполяции динамических значений лучше обрабатывается параметрами запроса:
$sql = "SELECT * FROM mytable WHERE id = ?";
$stmt = $pdo-&&t;prepare($sql);
$stmt-execute( [ $_GET['value'] ] );
Комментарии:
1. Идеальный ответ. Четко сформулировано и лаконично. Спасибо.
Ответ №3:
давайте обсудим эту вещь в небольших деталях:
Ваш код выглядит следующим образом :
if (in_array($_GET['value'], $allowed_values);) {
...........
$sql = "SELECT * FROM mytable WHERE id = $_GET['value']";
...........
}
else {
unset($_GET['name'])
}
теперь давайте предположим, что у вас есть некоторые значения :
функция in_array() допускает только некоторые предопределенные значения, у вас не может быть возможности принимать пользовательский ввод с помощью $ _GET, но поскольку разрешены только предопределенные значения, любая команда SQL будет безопасна внутри оператора if .
теперь возьмем этот пример массива $allowed_values :
$allowed_values = ['some details' , 'another details' ,3, ' 105; DROP TABLE mytable;', 22 , 'ok'];
Если какое-либо из этих значений массива содержит строку, которая может иметь потенциальную возможность SQL-инъекции, то возникнет проблема. но я думаю, что вы не будете помещать какую-либо такую строку в массив $allowed_values. ( в этом вышеупомянутом примере индекс 3, ‘ 105; УДАЛИТЬ ТАБЛИЦУ mytable;’ может удалить таблицу mytable ). в противном случае команда SQL будет безопасной.
теперь вы можете добавить дополнительный уровень безопасности в код, используя PDO для любого SQL-запроса. (в этом примере вам это не нужно, так как функция in_array() на 100% безопасна, если только вы сами не поместили какой-либо вредоносный код в массив, как в моем вышеупомянутом примере). но для других типов пользовательского ввода, где вам нужно выполнить некоторый SQL-запрос, зависящий от пользовательского ввода, вы можете использовать инструкцию, подготовленную PDO.
примером PDO является это :
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn-&&t;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn-&&t;prepare("INSERT INTO photos (username, kname) VALUES (?, ?)");
$stmt-&&t;execute([ $username , $kname ]);
Для получения дополнительной информации попробуйте ссылку w3school: https://www.w3schools.com/php/php_mysql_prepared_statements.asp
Комментарии:
1. Спасибо вам, мистер Пахари, от меня это была действительно связь между вашим ответом и ответом мистера Карвина, его ответ был таким кратким, но охватывал много вопросов, а ваш был более подробным в некоторых областях. У каждого есть свои достоинства. Невозможно выбрать.
2. если быть кратким: in_array() — самая безопасная вещь, но вы принимаете только предопределенные входные данные. если чего-либо нет в массиве «$allowed_values», оператор if не пройдет. но если вы хотите использовать пользовательский ввод там, где вы не знаете, каким будет ввод: используйте REGEX и PDO-Prepare stamement для защиты sql-инъекции.