2

我有一个来自,其中 2 个字段如下

<select name="sortfield">
    <option value="name" selected="selected">Name</option>
    <option value="price">Price</option>
    <option value="id">ID Code</option>
</select>
<select name="sortdir">
    <option value="asc" selected="selected">Ascending</option>
    <option value="desc">Descending</option>
</select>

这是通过$_REQUEST[]在下一页上获得的,然后将其添加到查询中以确定查询结果如何排序,快速、肮脏、未清理的方式是这样的

$query .= "ORDER BY ".$_REQUEST['sortfield']." ".$_REQUEST['sortdir'];

显然这可能是 sql 注入的问题,我可以解决这个问题的一种方法是更改​​值并在进行查询以换出值时使用 switch case,就像这样

switch($_REQUEST['sortfield'])
{
    case '5524879':
        $query .= "ORDER BY name";
        break;
    case '4587532':
        $query .= "ORDER BY price";
        break;
    default:
        $query .= "ORDER BY id";
}

虽然这可以帮助防止 sql 注入,但它不是很动态,因为如果查询/表结构发生变化,每次都必须更改页面,我想知道是否有更动态的方法来清理字符串,而不是必须使用switch ... case

4

2 回答 2

1

一种更动态的方法是使用show fields创建一个表字段数组,并在检查您的值时将其用作白名单sortfield

if ( !in_array( $_REQUEST['sortfield'], $table_fields ) ) {
    // error
}

我还建议根本不要使用 $_REQUEST。你应该知道你的变量来自哪里。

$_REQUEST 中的变量是通过 GET、POST 和 COOKIE 输入机制提供给脚本的,因此可以由远程用户修改并且不可信。此数组中列出的变量的存在和顺序是根据 PHP variables_order 配置指令定义的。

于 2013-10-22T05:31:03.467 回答
1

是的,对于 order by 子句,您只能格式化动态标识符,而无需根据白名单对其进行检查。

if (!empty($_GET['sortfield']))
{
    $query .= "ORDER BY `".str_replace("`","``",$_GET['sortfield'])."`";
} else {
    $query .= "ORDER BY id";
}

请注意,它会保护您免受注入,但不会保存 SQL 语法错误 - 因此,最好还是验证字段名称。

此外,表中可能没有id字段,因此此代码也不是很动态。因此,无论如何,最好坚持白名单。毕竟,这并不。有时手动修改比自动修改更好。

于 2013-10-22T05:36:02.533 回答