在 PHP 文件中解析 SQL 的最佳方法?
Posted
技术标签:
【中文标题】在 PHP 文件中解析 SQL 的最佳方法?【英文标题】:Best Approach to Parse for SQL in PHP Files? 【发布时间】:2010-09-06 10:27:26 【问题描述】:在我的毕业论文中,我开发了一个程序,该程序可以使用准备好的语句自动检测并建议修复 SQL 注入漏洞。特别是 php 的 mysqli 扩展。我对 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 的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章