更好的安全和审计正则表达式?

时间:2015-06-01 00:48:11

标签: php regex security

为了个人使用和工作,我编写了各种正则表达式来查找PHP中的所有变量。我的正则表达式的目的是出于安全原因,特别是VET脚本和插件。表达式如下:

\${1,1}[\w]+[" +"]{0,}=[" +"]{0,}['"][a-zA-Z0-9" "]+['"]+[;]{0,}

上面的正则表达式将找到所有$vars以及它们的设置。我使用它来使用Dreamweaver搜索整个目录和站点。以下是我的上述正则表达式中将找到哪种PHP变量的示例。

$var = 'sample';
$var = "sampletext"
$var="sampletext"
$$$var  = "sampletext"
$var      = "sampletext"
$var=     'sampletext';
$var = 'here is some sample text';
var = 'here is more sample text';

您可以看到上述所有变量都有轻微变化。有些使用双引号,单引号,有些使用分号,有些则没有,也有空格的变体。

所以,我的问题,你能简化我的正则表达式吗?你们都有其他正则表达式用于VET和ANALYIZE任何代码,但特别是PHP会很好。非常感谢您抽出时间阅读并提供帮助。

1 个答案:

答案 0 :(得分:3)

问题回答中的正则表达式都在寻找变量赋值表达式;如果您只是在寻找第一项任务,这将使问题复杂化,并且您更好 - 正如@mario所说 - 使用 PHP_Parser

这个正则表达式有很多奇怪的方面。首先是一个奇怪的正则表达式构造的小枚举:

  1. \${1,1}

    {1,1}表示一个一个之间的时间。这是无用的,可以用\$替换。

  2. [\w]+

    在这里,您只使用一种类型的字符,一个语义上等效的表达式为\w,但这部分有问题。这个document表示变量的名称只能以字母或下划线开头。其次是字母,下划线和数字\w仅表示最后一个类别。因此,$0之类的表达式将匹配。但是文档显示了如何指定变量名称:

    [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
    
  3. [" +"]{0,}

    在这里,我并不完全确定你的目标是什么;您似乎为正则表达式提供零或更多引号重复("),空格()和加号(+)的选择。如果您想要零个或多个间距字符,则可以使用\s*。分配后的部分也是如此。

  4. =

    这里假设您只能使用赋值声明变量。事实并非如此:PHP允许使用默认值,例如写$var += 3;。在这种情况下,$var将&#34; 初始化&#34;使用3,因为默认值为0。我同意这是糟糕的设计。您可以选择使用([+-*/%.&|^]|<<|>>)?

  5. 再次间隔;见第4号。

  6. ['"][a-zA-Z0-9" "]+['"]+[;]{0,}

    表达式,很难解析赋值运算符旁边的PHP表达式。它可以是常量,如数字,但这些可以是变量,字符串,函数调用,...函数调用甚至可以在f(1,2,g(3,'a'))等级联。通过标准正则表达式,这些调用甚至无法正确处理:它是一个常规语言抽取引理的结果。然而,PHP允许平衡括号扩展,所以理论上它可以完成。在这种情况下,你需要深入研究PHP的上下文免费语法,使其变得更加困难。

    您还要说明一些表达式不以分号结尾。然而,php -a交互式shell似乎并不喜欢这个想法:

    $ php -a
    php > $var
    php > echo $var;
    PHP Parse error:  syntax error, unexpected 'echo' (T_ECHO) in php shell code on line 2
    

    您可以使用分号作为查找表达式何时终止的方法。例如:

    .*?;
    

    这会有效,但是有一个问题:分号也可以放在字符串中。在这种情况下,需要忽略分号。您可以使用正则表达式替换点.

    ([^"']|(["'][^"]*["']))*?
    

    但这又会导致问题,因为引用可以转义(如"\"");在这种情况下,您不希望正则表达式将第二个"解释为字符串的结尾。你可以通过使正则表达式更复杂来解决这个问题:

    ([^"']|(["']([^"\\]|\\.)*["']))*?
    
  7. 因此,正则表达式可以读取:

    \$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\s*([+-*/%.&|^]|<<|>>)?=\s*([^"']|(["']([^"\\]|\\.)*["']))*?;
    

    regex101 demo

    如前所述要求表达式以分号结尾。字符串环境中的分号将被忽略。