在我的脚本中是否有某些东西可能会逃脱卫生设施,或者大多数 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);
编辑:这是建议编辑后最终查询的样子
INSERT INTO other_table($key[0],...,$key[n]) VALUES (?,...,nth-?);
答案 0 :(得分:0)
没有。显示的示例代码是大多数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
在使用另一个反引号转义列标识符中的任何反引号后,您需要将列标识符括在反引号中。
答案 1 :(得分:0)
正如其他人所说,请确保您的列名是安全的。
SQL注入可以从任何外部输入发生,而不仅仅是http请求输入。如果您使用从文件,Web服务或其他代码的函数参数,或其他代码的返回值,甚至从您自己的数据库中读取的内容,您可能会面临风险...... trust什么都没有!: - )
您可以确保列名称本身已转义。不幸的是,在大多数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请求参数相交。这样我只使用也在列集中的那些post参数。它最终可能会在SQL中生成一个INSERT语句,其中包含的列数少于所有列,但如果缺少的列具有默认值或允许为NULL,则表示没问题。
答案 2 :(得分:-1)
有一种一种方法可以阻止SQL注入:确保查询字符串永远不会的文本包含用户提供的内容内容,无论你如何尝试“消毒”它。
当您按照建议使用“占位符”时,SQL字符串的文本包含(可能是......)问号... VALUES (?, ?, ?)
指示要插入参数的每个位置。每次执行查询时,都会提供相应的参数值列表 。
因此,即使为last_name
提供的值为"tables; DROP TABLE STUDENTS;"
,SQL也永远不会将其视为“SQL字符串的一部分”。它只会将“最不寻常的last_name
”插入数据库。
如果您正在进行批量操作,那么您只需一次准备语句这一事实可以节省大量时间。然后,您可以根据需要多次执行该语句,每次都会向其传递一组不同的(或相同的)参数值。