解析PHP文件中SQL的最佳方法?

时间:2020-03-05 18:41:38  来源:igfitidea点击:

对于我的高级论文,我开发了一个程序,该程序将使用准备好的语句自动检测并建议对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查询的函数调用。