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

Posted

技术标签:

【中文标题】在 PHP 文件中解析 SQL 的最佳方法?【英文标题】:Best Approach to Parse for SQL in PHP Files? 【发布时间】:2010-09-06 10:27:26 【问题描述】:

在我的毕业论文中,我开发了一个程序,该程序可以使用准备好的语句自动检测并建议修复 SQL 注入漏洞。特别是 phpmysqli 扩展。我对 SO 社区的问题是:您首选的方法是检测 PHP 源代码中的 SQL?

我使用了一个包含SQL keywords (SELECT, INSERT, ...) 的枚举,并且基本上解析了每一行,遍历枚举以确定是否存在任何 SQL。此外,我必须确保解析器没有错误地检测到 html(例如 )。

对我来说,这个解决方案运行良好,但现在我手头有更多时间,并考虑重构代码以使用更优雅(和高效)的解决方案。请将您的解决方案限制为使用 C#,因为这是我编写程序时使用的。

【问题讨论】:

【参考方案1】:

您的解决方案对我来说似乎很好。另一种方法是使用 PHP 语法使用 Lex/Yacc 解析器解析 PHP 文件,有一个很好的 C# 语法解析工具,称为 Coco/R http://www.ssw.uni-linz.ac.at/coco/.

但是我相信,如果您确实解析了语言,您最终会花费太多时间(在开发和计算中)而没有额外的结果。

我会坚持你的机会主义方法,但会针对各种 PHP 代码对其进行测试并对其进行调整以涵盖所有可能的情况。

【讨论】:

【参考方案2】:

也许在针对BNF 解析文本行时,比如SQL92,并根据片段与语法的匹配程度对每一行进行评分。

虽然听起来有些繁重。您的简单方法已经可以捕捉到如此大比例的真实案例。

【讨论】:

【参考方案3】:

我不知道 C# 中变量的具体细节,因此您将不得不原谅或否决我使用 PHP,但 70% 的时间我的 SQL 查询会进入这样的变量

$sql = "SELECT * FROM table;";

除此之外,我想不出你可以做些什么来改进你已经拥有的东西。

您是否考虑了通过多行创建的语句并在字符串中使用变量? (下例)

$sql = "SELECT * FROM table WHERE fname = $fname OR snmae = $sname";

【讨论】:

【参考方案4】:

我会说最好是查找函数调用而不是查找 SQL 本身。可能修改 PHP 解析器以查找导致运行 SQL 查询但不是准备好的查询的函数调用。

【讨论】:

【参考方案5】:

我不知道 C# 中变量的具体细节,因此您将不得不原谅或否决我使用 PHP,但 70% 的时间我的 SQL 查询会进入这样的变量..

是的,我最初的方法是只查找 $sql 变量,因为这是大多数人使用的,但是在针对一些 PHP 应用程序进行测试后,我很快就放弃了该解决方案,因为一些开发人员使用一些时髦的变量名...

您是否考虑了通过多行创建的语句并在字符串中使用变量? (下例)

是的。我还尝试处理有条件生成的语句,但这并不总是那么好。 ;)

【讨论】:

【参考方案6】:

一个简单的正则表达式来检测所有与函数一起使用的 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);

【讨论】:

以上是关于在 PHP 文件中解析 SQL 的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中解析无效 HTML 的最佳方法

在 PHP 中解析无效 HTML 的最佳方法

在 PHP 中处理大型 XML 的最佳方法 [重复]

在 PHP 中避免代码注入的最佳方法

PHP 和 SQL 解析

在 Ruby 中解析制表符分隔文件的最佳方法是啥?