Является ли функция in_array безопасным способом блокировки внедрения кода / sql-инъекции?

#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-инъекции.