【发布时间】:2020-03-15 16:02:51
【问题描述】:
使用 PHP 7 和 MySQL 8
首先让最终用户生成一个新列并不是最好的主意,但在这种情况下(以及其他不易使用常见 PDO 策略的情况),提供针对 SQL 的安全性的解决方案是什么注射?
我正在尝试做的事情: 我有一个动态注册表,它从数据库中获取输入,并且该网站的所有者可以在此表单中添加字段。当然,如果在表单中添加了一个新字段,那么数据库中也必须添加一个新列来存储数据。直接插入没有问题,但如果有人侵入管理系统,他们可以轻松添加 sql 注入。因此,我试图找到一种更安全的方法。
工作(不安全)代码:
//$fName is the field name and also the column name
$fName= $_POST['fName'];
$sql2=$pdo->prepare("ALTER TABLE attendee ADD $fName VARCHAR( 255 )");
$go2=$sql2->execute();
我尝试过的: 我研究过白名单,但我认为这不是最佳选择,因为列名称的可能性是无穷无尽的。
//Tried using named paramater PDO array (also tried unnamed ? version)
$data2=[
'fName'=>$fName
];
$sql2=$pdo->prepare("ALTER TABLE attendee ADD :fName VARCHAR( 255 )");
$go2=$sql2->execute($data2);
//Using PDO Quote indirectly
$roger=$pdo->quote($fName);
$sql2=$pdo->prepare("ALTER TABLE attendee ADD $roger VARCHAR( 255 )");
$go2=$sql2->execute();
//Using PDO Quote Directly with concatenation
$sql2=$pdo->prepare("ALTER TABLE attendee ADD" . $pdo->quote($fName) . " VARCHAR( 255 )");
$go2=$sql2->execute();
【问题讨论】:
-
您可以考虑一个可接受的列名的白名单,并检查该名称是否在该列表中。
-
啊,谢谢尼克的回答!我还将把它添加到我尝试过/考虑过的内容中。我不认为白名单在这种情况下会起作用,因为他们将来会为该列命名的内容超出了我的范围。
-
我只是使用正则表达式验证或过滤用户选择的列名。只允许普通字符和格式,例如/^[a-z][a-z0-9-]{1,20}$/i .之后就可以安全使用了。不要忘记检查重复的列名。同样重要的是:在列名和表名周围使用反引号`。但我支持@Your Common Sense,即编号的列名可以工作并且完全兼容 PDO。批量添加列(每 10 个左右)也将最小化表重建。
标签: php mysql security pdo code-injection