解析PHP文件中SQL的最佳方法?
对于我的高级论文,我开发了一个程序,该程序将使用准备好的语句自动检测并建议对SQL注入漏洞的修复。特别是PHP的mysqli扩展。对于SO社区,我的问题是:在PHP源代码中检测SQL的首选方法是什么?
我使用了一个包含SQL关键字(SELECT,INSERT,...)的枚举,并基本上解析了每一行,遍历该枚举以确定是否存在任何SQL。另外,我必须确保解析器不会错误地检测到html(例如<\ select>)。
对我来说,这个解决方案效果很好,但是现在我有更多时间可以使用,并且已经考虑过重构代码以使用更优雅(更有效)的解决方案。请限制我们使用我编写程序的Cas的解决方案。
解决方案
回答
解决方案对我来说似乎不错。另一种方法是使用Lex / Yacc解析器使用PHP语法解析PHP文件,有一个很好的Cgrammar解析工具称为Coco / R
http://www.ssw.uni-linz.ac.at/coco/。
但是我相信,如果我们解析语言,最终将花费太多时间(在开发和计算中)而没有其他结果。
我会坚持使用机会主义的方法,但是要针对各种PHP代码进行测试,并对其进行调整以涵盖所有可能的情况。
回答
在针对BNF的文本行(例如SQL92)上进行解析,以及对片段与语法的匹配程度进行评分,可能会有些许麻烦。
虽然听起来有些沉重。简单方法已经可以捕获大量实际案例。
回答
我不知道C中变量的详细信息,因此我们将不得不原谅或者拒绝我使用PHP,但是70%的时间我的SQL查询进入这样的变量
$sql = "SELECT * FROM table;";
除此之外,我无法想到我们可以做的任何事情来改进现有的功能。
我们是否考虑了在多行上创建的语句并在字符串中使用变量? (下面的示例)
$sql = "SELECT * FROM table WHERE fname = $fname OR snmae = $sname";
回答
I do not know the specifics of variables in C# so you will have to forgive or down-vote me for using PHP but 70% of the time my SQL query goes into a variable like so ..
是的,我最初的方法是只查找$ sql vars,因为这是大多数人使用的方法,但是在对一些PHP应用程序进行测试后,我迅速放弃了该解决方案,因为一些开发人员使用了一些时髦的变量名...
Do you take into account statements that are created over several lines and use variables within the string? (Example below)
是的。我还尝试处理有条件地生成的语句,但这种方法并非总是能很好地工作。 ;)
回答
一个简单的正则表达式,用于检测与函数一起使用的所有CRUD sql语句(假设$ script包含整个php脚本)
preg_match_all('/\(\s*?"(?:SELECT|INSERT|UPDATE|DELETE) .*?"\s*?\)\s*?;/is', $script, $matches);
如果将它们放在括号和双引号中,则它应与所有可能的SELECT,INSERT,UPDATE,DELETE语句匹配。这是区分大小写的,还应该匹配跨越多行的语句。
编辑#1:正则表达式用于匹配CRUD语句,例如字符串分配;
preg_match_all('/$\w+\s*?=\s*?"(?:SELECT|INSERT|UPDATE|DELETE) .*?"\s*?;/is', $script, $matches);
编辑#2:
// $variable detecting version of #1 regex preg_match_all('/\(\s*?"(?:SELECT|INSERT|UPDATE|DELETE) .*?(?:$\w+){1}.*?"\s*?\)\s*?;/is', $script, $matches);
回答
我会说最好是寻找函数调用,而不是寻找SQL本身。可能修改PHP解析器以查找导致运行不是准备好的查询的SQL查询的函数调用。