2013-02-15 98 views
1

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

编辑:

该系统适用于例如这样的:db::select()-from('Tablename')->that('rowname')->run()。而且恐怕有一个用户可以做类似that($_GET['foo'])之类的东西。我可以忍受这一点,但我认为必须有一种方法来这样做

+0

在准备好的语句中使用'mysqli_'或'PDO'? – Kermit 2013-02-15 16:20:41

+0

你可以显示一些代码或给出具体用例与你正在使用什么行名称?如果你不能使用准备好的语句,那么你正在做一些非常错误的事情。 – mkaatman 2013-02-15 16:21:21

+0

系统的工作原理如下: – edave 2013-02-15 16:31:54

回答

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字段的值为admin,用于查询我的示例)
为了这个目的,我在我的类中有两个函数,它们都接受允许值的数组。

+0

它让我害怕了一点,看不到这个简单解决方案的任何明显的攻击。我会执行它。 (白名单已经是上面图层的一部分,我的ORM,但是可以单独使用)谢谢! – edave 2013-02-15 19:41:00

-1

由于查询生成器的工作原理,我很遗憾不能使用预处理语句。我怎样才能解决这个问题?

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

很多人都提倡正确的查询参数,但逃避也是安全IF你正确和一贯做到这一点。

参考mysqli::real_escape_string()


重新发表您的评论,好的,我明白你要去哪里了。我很困惑,因为你说“行名”,这不是正确的术语。您必须表示列名称

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

当不可信输入名称表或列时,保护SQL查询的最佳方法是使用白名单。也就是说,根据已知表名或列名称列表来测试参数,您可以手动对其进行编码,也可以从DESCRIBE table中找到它。

见白名单的例子,在我过去的答案:

+0

我已经使用mysqli :: real_escape_string(),但我无法看到如何将其应用于表/行名称,因为它不会过滤'我使用的字符' – edave 2013-02-15 16:58:22