1

我目前正在编写一个专注于安全性的 php 框架。我使用查询生成器来生成 SQL 语句,这样它就不会绑定到 MySQL。(或一般的 SQL)我发现用户可以注入行名的某些可能性,所以它必须以某种方式转义它们。由于查询生成器的工作方式,我很遗憾不能使用准备好的语句。我怎样才能解决这个问题?

编辑:

例如,该系统的工作方式如下:db::select()-from('Tablename')->that('rowname')->run(). 而且我担心一个用户可能会做类似的that($_GET['foo'])事情。我可以忍受,但我认为必须有一种方法来净化它

4

2 回答 2

0

要逃避反引号,您必须将其加倍。这是我班上的一个函数

private function escapeIdent($value)
{
    if ($value)
    {
        return "`".str_replace("`","``",$value)."`";
    } else {
        $this->error("Empty value for identifier (?n) placeholder");
    }
}

//example:
$db->query("UPDATE users SET ?u=?s", $_POST['field'], $_POST['value']);

因此,它将创建一个语法正确的标识符。

但最好将其列入白名单,因为可能有一个字段,尽管名称正确,但用户没有访问权限。(因此,从这个角度来看,基于模式的解决方案仍然很危险。想象一下,我的示例中有一个role带有查询值的字段) 我的类中有 2 个用于此目的的函数,它们都接受一个允许值的数组。admin

于 2013-02-15T18:07:05.353 回答
-1

由于查询生成器的工作方式,我很遗憾不能使用准备好的语句。我怎样才能解决这个问题?

如果您不能使用查询参数,请更改查询构建器以将转义应用于其参数,然后再将它们插入 SQL 表达式。

很多人正确地提倡查询参数,但如果你正确且一致地进行转义,转义也是安全的。

参照。mysqli::real_escape_string()


回复你的评论,好吧,我知道你要去哪里。我很困惑,因为您说的是“行名”,而这不是正确的术语。您必须指的是列名

是的,你是对的,任何 MySQL API 中都没有函数可以正确转义表或列标识符。转义函数仅适用于字符串文字和日期文字。

当不受信任的输入命名表或列时,保护 SQL 查询的最佳方法是使用白名单。也就是说,针对已知表名或列名列表测试参数,您可以手动编码,也可以从DESCRIBE table.

请参阅我过去的答案中的白名单示例:

于 2013-02-15T16:50:55.253 回答