2016-07-08 3 views
-1

Есть ли что-то, что может избежать санитарии в моем сценарии или это безопасно от most SQL-инъекции? Как я понимаю, если вы передаете запрос в качестве подготовленного аргумента, неважно, как был создан запрос, правильно?Является ли это создание динамического SQL-запроса безопасным от инъекций?

Edit2: Я редактировал код, чтобы отразить предложения связывания значений по $ _POST

$q = $pdo->prepare('SHOW COLUMNS FROM my_table'); 
$q->execute(); 
$data = $q->fetchAll(PDO::FETCH_ASSOC); 
$key = array(); 
foreach ($data as $word){ 
    array_push($key,$word['Field']); 
    } 
$sqlSub= "INSERT INTO other_table("; 
$n = 0; 
foreach ($key as $index){ 
    $sqlSub = $sqlSub.$index.", "; 
    $n = $n + 1; 
} 
$sqlSub = $sqlSub.") VALUES ("; 
for ($i=1; $i<$n;$i++){ 
    $sqlSub = $sqlSub."?, "; 
} 
$sqlSub = $sqlSub.."?)"; 
$keyValues = array(); 
for($i=0;i<n;$i++){ 
    array_push($keyValues,$_POST[$key[$i]]); 
} 
$q->$pdo->prepare($sqlSub); 
q->execute($keyValues); 

EDIT: Это, как окончательный запрос выглядит как после предложенных правок

INSERT INTO other_table($key[0],...,$key[n]) VALUES (?,...,nth-?); 
+4

'если вы передаете запрос в качестве подготовленного аргумента, неважно, как был создан запрос' ... неправильно. Да, это все еще уязвимо. На самом деле, вы так же уязвимы, как если бы вы не подготовили запрос. Способ сделать это безопасным для SQL-инъекции - это не просто подготовить ваш запрос, а подготовить запрос к заполнителям и привязать значения к этим заполнителям. –

+2

Нет! Если вы не используете привязку своих значений, вы небезопасны. – aynber

+1

no, если вы хотите сделать это безопасным, получите список столбцов в таблице, используя ключи «Описать» или «Объяснить», можно изменить, если они, например, являются именами входных данных формы, со списком столбцов, которые вы может перекрестно проверить их. Затем используйте подготовленные инструкции для значений и белый список для ключей. – ArtisticPhoenix

ответ

0

No. пример показан код не безопасен от большинства SQL-инъекций.

Вы понимаете, что это совершенно неправильно.

Что имеет значение, это текст SQL. Если это динамически генерируется с использованием потенциально небезопасных значений, текст SQL уязвим.


Код уязвим в нескольких местах. Даже имена столбцов потенциально опасны.

CREATE TABLE foo 
(`Robert'; DROP TABLE Students; --` VARCHAR(2) 
, `O``Reilly`       VARCHAR(2) 
); 

SHOW COLUMNS FROM foo 

FIELD        TYPE  NULL 
-------------------------------- ---------- ---- 
Robert'; DROP TABLE Students; -- varchar(2) YES 
O`Reilly       varchar(2) YES 

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

+0

Каким образом имена столбцов небезопасны, поскольку они выбираются непосредственно из не изменяемой таблицы на стороне сервера без ввода пользователя? Плюс я отредактировал мой пост –

+2

Я показываю пример того, как идентификаторы столбцов могут быть небезопасными для включения в текст SQL и требуют специальной обработки, чтобы сделать их безопасными. Вот почему вы видите mysqldump и всевозможные инструменты MySQL, которые обертывают идентификаторы в backticks, даже если обратные ссылки не требуются. (Это просто быстрее, чтобы делать это, а не проверять, требуется ли это.) – spencer7593

+0

Теперь я вижу. Если бы я также разрешил пользователям создавать свою собственную схему таблиц, а затем разрешал им запускать этот скрипт, они могли бы делать именно то, что вы говорите через имена столбцов. Имеет смысл, хороший момент. –

-1

Существует ровно один способ предотвратить инъекции SQL: чтобы убедиться, что текст вашей строки запроса никогда не включает в себя предоставленный пользователем контент, независимо от того, как вы можете попытаться «Sanitize» это.

При использовании «заполнители,» как это было предложено, то текст строки SQL содержит (наверное ...) знаки вопроса ... VALUES (?, ?, ?) указать каждое место, где параметр должен быть вставлен. Соответствующий список значений предоставляется отдельно, каждый раз, когда выполняется запрос.

Таким образом, даже если значение поставляется для last_name является "tables; DROP TABLE STUDENTS;", SQL будет никогда увидеть это как «часть строки SQL.» Он просто вставляет, что «самый необычный last_name» в базу данных.

Если вы делаете сыпучих операций, то, что вам нужно подготовить заявление только раз могут сэкономить значительное количество времени. Затем вы можете выполнять оператор столько раз, сколько хотите, передавая ему каждый раз (или тот же) набор значений параметра.

0

Как уже отмечалось, убедитесь, что имена столбцов безопасны.

SQL-инъекция может происходить от любой внешний вход, а не только вход для запроса http.Вы можете быть в опасности, если используете контент, считанный из файла или из веб-службы, или из аргумента функции из другого кода, или возвращаемого значения другого кода, или даже из вашей собственной базы данных ... не доверяйте никому! :-)

Вы можете убедиться, что сами имена столбцов экранированы. К сожалению, в большинстве API-интерфейсов или фреймворков нет встроенной функции. Поэтому вам придется делать это самостоятельно с помощью регулярных выражений.

Я также рекомендую вам ознакомиться с встроенными функциями массива PHP (http://php.net/manual/en/ref.array.php). Большая часть вашего кода может быть быстрее разработана для разработки кода, и это, вероятно, также улучшит производительность во время выполнения.

Вот пример:

function quoteId($id) { 
    return '`' . str_replace($id, '`', '``') . '`'; 
} 

$q = $pdo->query("SHOW COLUMNS FROM my_table"); 
while ($field = $q->fetchColumn()) { 
    $fields[] = $field; 
} 

$params = array_intersect_key($_POST, array_flip($fields)); 
$fieldList = implode(",", array_map("quoteId", array_keys($params))); 
$placeholderList = implode(",", array_fill(1, count($params), "?")); 
$sqlSub = "INSERT INTO other_table ($fieldList) VALUES ($placeholderList)"; 

$q = $pdo->prepare($sqlSub); 
$q->execute($params); 

В этом примере я пересекаться столбцы из таблицы с параметрами после запроса. Таким образом, я использую только те параметры post, которые также находятся в наборе столбцов. Это может привести к созданию инструкции INSERT в SQL с меньшим количеством столбцов, но если недостающие столбцы имеют значения по умолчанию или разрешают NULL, все в порядке.

Смежные вопросы