mysql清理行名

时间:2013-02-15 16:18:59

标签: php sql mysqli

我目前正在编写一个专注于安全性的php框架。我使用查询构建器生成SQL语句,因此它不绑定到MySQL。 (或者一般的SQL)我发现用户可以注入行名的某些可能性,所以它必须以某种方式逃避它们。由于查询构建器的工作原理,我遗憾地无法使用预处理语句。我该如何解决这个问题?

编辑:

系统的工作原理如下:db::select()-from('Tablename')->that('rowname')->run()。我担心一个用户可能会做that($_GET['foo'])之类的事情。我可以忍受这一点,但我认为必须有一种方法来对此进行整理

2 个答案:

答案 0 :(得分:0)

要逃避反击,你必须double it。这是我班级的一项功能

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']);

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

whitelist它总是更好,因为可能有一个字段,虽然名称正确,但用户没有访问权限。 (因此,从这个角度来看,基于模式的解决方案仍然很危险。想象一下,对于来自我的示例的查询,存在值为role的{​​{1}}字段。
为此我在类中有2个函数,它们都接受一组允许的值。

答案 1 :(得分:-1)

  

由于查询构建器的工作方式,我遗憾地无法使用预准备语句。我该如何解决这个问题?

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

很多人正确地提倡查询参数,但逃避也是安全的 IF 你正确而一致地做到了。

比照。 mysqli::real_escape_string()


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

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

在不受信任的输入名称表或列使用白名单时保护SQL查询的最佳方法。也就是说,根据已知表名或列名列表测试参数,您可以手动编写代码,也可以从DESCRIBE table发现它。

根据我过去的答案查看白名单示例: