mpe*_*pen 24 php mysql database sql-injection
基本上,我想要做的是:
mysql_query("SELECT ... FROM ... ORDER BY $_GET[order]")
Run Code Online (Sandbox Code Playgroud)
他们显然可以通过在其中放置无意义来轻松地创建SQL错误,但mysql_query只允许执行1个查询,因此他们不能放置类似的东西1; DROP TABLE ....
除了创建语法错误之外,恶意用户是否可以做任何损害?
如果是这样,我该如何清理查询?
在$_GET['order']变量中有很多逻辑构建在类似SQL的语法中,所以我真的不想改变格式.
澄清$_GET['order']一下,不只是单个字段/列.它可能是这样的last_name DESC, first_name ASC.
Raf*_*afe 30
是的,SQL注入攻击可以使用未转义的ORDER BY子句作为向量.这里有一个解释如何利用它以及如何避免这个问题:
http://josephkeeler.com/2009/05/php-security-sql-injection-in-order-by/
该博客文章建议使用白名单来验证ORDER BY参数,这几乎肯定是最安全的方法.
要响应更新,即使该子句很复杂,您仍然可以编写一个针对白名单验证它的例程,例如:
function validate_order_by($order_by_parameter) {
$columns = array('first_name', 'last_name', 'zip', 'created_at');
$parts = preg_split("/[\s,]+/", $order_by_parameter);
foreach ($parts as $part) {
$subparts = preg_split("/\s+/", $part);
if (count($subparts) < 0 || count($subparts) > 2) {
// Too many or too few parts.
return false;
}
if (!in_array($subparts[0], $columns)) {
// Column name is invalid.
return false;
}
if (count($subparts) == 2
&& !in_array(strtoupper($subparts[1]), array('ASC', 'DESC')) {
// ASC or DESC is invalid
return false;
}
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
即使ORDER BY子句很复杂,它仍然仅使用您提供的值(假设您不允许用户手动编辑它).您仍然可以使用白名单进行验证.
我还应该补充一点,我通常不喜欢在URL或UI中的其他位置公开我的数据库结构,并且通常会在URL中的参数中对这些内容进行别名,并使用哈希将其映射到实际值.
我更喜欢进行白名单,并将http参数字符串视为与插入到SQL查询中的字符串分开.
在下面的PHP示例中,数组键将是作为http参数传递的值,根据您的Web界面,用于不同排序方案的某种符号标签.数组值将是我们想要为这些相应的排序方案插入SQL的内容,例如列名或表达式.
<?php
$orderby_whitelist = array(
"name" => "last_name, first_name",
"date" => "date_created",
"daterev" => "date_created DESC",
"DEFAULT" => "id"
);
$order = isset($_GET["order"])
? $_GET["order"]
: "DEFAULT";
$order_expr = array_key_exists($order, $orderby_whitelist)
? $orderby_whitelist[$order]
: $orderby_whitelist["DEFAULT"];
mysql_query("SELECT ... FROM ... ORDER BY $order_expr")
Run Code Online (Sandbox Code Playgroud)
这有以下优点:
即使在不能使用查询参数的情况下,也可以防御SQL注入.如果客户端传递了无法识别的值,则代码会忽略它并使用默认顺序.
您不必清理任何内容,因为数组中的键和值都是由程序员编写的.客户输入只能选择您允许的其中一个选项.
您的Web界面不会显示您的数据库结构.
您可以制作与SQL表达式或替代ASC/DESC相对应的自定义订单,如上所示.
您可以在不更改Web界面的情况下更改数据库结构,反之亦然.
我在演示文稿,SQL注入神话和谬误,以及我的书" SQL反模式:避免数据库编程的陷阱"中介绍了这个解决方案.