我们说我有一个名为query.sql
的文件,其中包含以下内容:
SELECT * FROM `users` WHERE `id`!=".$q->Num($_POST['id'])."
在我的php脚本中,它有一个html表单,输入名为" id"在其中,我做了以下技巧:
$sql=file_get_contents('query.sql');
$query= eval("return \"$sql\";");
//here follows something like $mysqli->query($query); and so on..
我不关心关于sql-injections,因为我使用预准备语句并且$q->Num
执行is_int
检查。
但以这种方式使用eval是否安全?
据我了解,这里实际评估的是" $ {_ POST [' id']}"并且它会侵蚀用户输入的某个字符串值。只有当我第二次评估这个字符串时,这才会变得危险。虽然我只是在用户的输入只是字符串时才使用字符串,并且不能通过编译器将其解释为php代码,并且不能进行php注入。
更新 感谢您提出不同的方法并强调使用预准备语句的需要。但这不是我的问题。 我的问题是关于php注入。这样使用eval不好吗?如果是,为什么?
答案 0 :(得分:2)
eval语句 - 虽然我试图找到一种不使用eval的方法 - 但是不容易注入PHP,因为$sql
包含在双引号"
中;人们不能用PHP中的预备变量来结束这种引用。
由于我正在使用预备语句
,因此我不会对sql注入感到遗憾
不是吗? ;) 你是!
为什么要使用'。'将$ id添加到查询中运算符(字符串操作)?如果你真正使用预备语句带来的好处,我会期望像bindParam()
注意如何预处理语句防止SQL注入:SQL查询语法与参数分开。所以服务器会
由于在应用参数之前已经解析了查询,因此参数不能操纵查询语法。
如果您准备使用'。'创建的MySQL查询和外部输入您可能容易受到SQL注入攻击
你在做什么会打败预备陈述的原则
答案 1 :(得分:2)
无需使用eval
- 放入令牌,并将其替换为:
// file query.sql
SELECT * FROM `users` WHERE `id`!="{id}";
//php
$sql = file_get_contents('query.sql');
$query = str_replace("{id}", $_POST['id'], $sql);
<强>更新强>
不,这不安全。有人可以编辑您的query.sql
脚本来执行您想要的任何操作。您可能会说“应用程序仅限内部”,或“我已锁定权限”或其他任何内容 - 但在一天结束时无法保证。
答案 2 :(得分:-1)
让我们考虑以下代码:
$sql=file_get_contents('query.sql');
$query= eval("return \"$sql\";");
危险点是:
如果文件query.sql
已根据您的预期进行修改,则可以使用它来执行程序中的任意代码。
文件名称显示为硬编码;如果不是这种情况,则恶意用户可能会找到一种方法来加载意外文件(甚至可能是远程站点中的文件),再次导致任意代码执行。
为此使用文件的唯一原因(而不是直接在程序中对SQL代码进行硬编码)将是因为您希望将其用作配置文件。这里的问题是该文件中的语法对SQL和PHP都无效。由于它在eval()
中运行的方式,它还要求语法完全正确。使用错误的引号或错过一个,它会爆炸。这可能会导致代码变得很脆弱,当配置稍有不正确时,代码会严重失败而不是优雅。
这里似乎没有直接的SQL注入攻击,但对于eval()
而言,这实际上是您最不担心的。
我个人曾在代码存在的项目中工作,这些项目的工作方式与您所描述的完全一致。系统中存在一些非常讨厌的错误,直接导致这些错误,并且在没有批量重写的情况下很难纠正。我强烈建议退回这个想法并使用合理的模板机制,而不是其他人在评论中所建议的。