首页 > 编程知识 正文

java 正则匹配,grep只显示匹配内容

时间:2023-05-03 12:12:34 阅读:137359 作者:4867

正在使用mod安全规则https://github.com/spider labs/owasp-modsecurity-CRS清理用户输入的数据。 面临着cpu激增和延迟使用户输入与mod安全规则的正则表达式相匹配的问题。 通常,它包含500多个正则表达式,并检查各种类型的攻击(xss、badrobots、generic和sql )。 针对每个请求,检查所有参数,并对照所有这500个正则表达式进行检查。 正在使用Matcher.find检查参数。 在这种情况下,一些参数会陷入无限循环。 我用以下技术解决了这个问题。

是否要取消长期运行的正则表达式竞赛?

清理用户请求大约需要500毫秒,CPU%会急剧增加。 在测试套件的可执行文件中使用visualvm.java.net进行了分析。

CPU配置文件输出

可以减少CPU使用率和平均负荷吗?

截图显示,checkPattern被调用212148825次,总共调用6100774ms,即每次调用0.02ms。 在那里看不到性能问题——绝对没有证明每次调用500毫秒。

如果存在导致长时间延迟的特殊模式,则需要确定并将其包括在问题中。

@Holger花费的时间不是问题。 我只关心负载和cpu的使用情况。 我想并行处理参数,这样的话,平均负荷就变成4。 我使用jstack -l进行线程转储,使用thread -H -b -p找到最大消耗线程,并将id转换为可在Matcher.find上运行的十六进制代码。

@bharathi :果然是同样的问题。 许多图案可能很便宜,但其中一些很贵。 要集中精力优化这些特定模型,需要确定昂贵的工具。 值得一提的是,Matcher.find会为分析器的默认过滤规则调用其他未显示的方法。 修改这些规则以允许查看JDK的方法,可以花大部分时间,也就是说,花在CPU负载匹配的内部位置。

我认为这是问题的根源,而不是正则表达式的性能本身:

For each request,igothroughallparametersandcheckagainstallthese 500 regular expressions

不管正则表达式多快,这仍然需要做很多工作。 我不知道你有多少参数,但是不管你只有多少参数,每个请求都要检查几千个正则表达式。 那会杀了你的CPU。

虽然预编译和/或简化显然可以提高正则表达式的性能,但您也可以通过执行以下操作来减少正则表达式检查的数量:

根据参数类型使用用户输入的肯定验证。 比如说。 如果参数必须是简单的数字,请不要浪费时间检查是否包含恶意XML脚本。 只需检查它是否符合[0-9] (或类似的简单内容)。 如果可能,跳过所有500个正则表达式的检查。

试着找到可以排除所有攻击类别的简单正则表达式——在正则表达式中找到常见的。 例如,如果您已经有100个正则表达式,并且要检查是否存在一些HTML标记,请首先检查内容是否至少包含一个HTML标记。 否则,可以立即保存100个正则表达式。

缓存结果。 webapps生成的许多参数是重复的。 记住最终的验证结果,而不是一次又一次地检查同样的内容。 请注意,为了避免DOS攻击,请限制高速缓存的最大大小。

还应注意,否定验证通常容易被绕过。 只有几个字符更改为恶意代码,正则表达式不匹配。 为了防止新的攻击,需要扩展正则表达式的“数据库”。 没有这个缺点,验证更有效。

你好,我做了前两个步骤。 现在,总的执行时间比以前更好。 获得约60ms。

我建议你读这篇论文:

'为了更快的字符串匹配而超过入侵检测或Snort的速度'

有比进行你说明的匹配更好的方法。 基本上,可以采用要匹配的500个模式,并将其编译为单个后缀树。 在此树中,一次将输入与所有规则匹配非常高效。

说明了该方法由Dan Gusfield记述为“正确一致的Boyer-Moore方法”。

Boyer-Moore是有名的字符串匹配算法。 本文介绍了冷静立方体(Boyer-Moore )用于集合匹配的变体。

如果可能的话,只编译一次正则表达式并保留它们。 请勿重复(隐式)编译,尤其是在循环中。

请参阅Java.util.regex-pattern.com pile ()的重要性? 详情在这里。

我已经这样做了。 预编译所有匹配的架构,并保存架构列表。

避免以下情况:

多行

不区分大小写

等等

您可能要考虑对正则表达式进行分组,然后应用基于用户输入的一组正则表达式。

这是完全错误的。 为什么对多行/大小写不敏感? Java中的正则表达式匹配基于NFA回溯,因此区分大小写等对性能的影响不大。 更重要的是,例如,避免倒退。 *,然后进行更改(a | b | c )。

正如您所说,搜索多行时区分大小写对性能没有什么影响。 这是声明

它们影响性能的另一种方法。根据性能要求,它可能是相关的,也可能不是。如果需要性能,则不得使用回溯。决不。

在这500个中,必须有一个有问题的正则表达式子集。这样的正则表达式

String s ="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB";

Pattern.compile("(A+)+").matcher(s).matches();

将需要数年才能完成。

因此,在您的情况下,我会将所有有问题的正则表达式及其有问题的输入记录下来。找到这些后,您可以手动重写这几个有问题的正则表达式,并与原始版本进行测试。总是可以使用更简单,更易读的Java函数来重写正则表达式。

另一个选择虽然不能解决上面的问题,但您也可以使用速度更快(在某些情况下为x20)和更受限的正则表达式库。它在Maven Central中可用。

如果您有大量的正则表达式,则可以使用trie算法(http://en.wikipedia.org/wiki/Trie)将它们分组(至少其中一些)。

这个想法是,如果您有例如/abc[0-9-]/,/abde/,/another example/,/.something else/和/.I run out of ideas/之类的正则表达式,则可以将它们组合成单个正则表达式

/a(?:b(?:c[0-9-]|de)|nother example)|.(?:I run out of ideas|something else)/

这样,匹配器只需要运行一次即可,而不是运行四次,并且由于上面的正则表达式中编写了常见的起始部分,因此避免了很多回溯。

嗨,pydbl,我不能分组。因为,我需要获取匹配的规则(mod安全规则,每个规则都有其自己的属性)详细信息。

原则上,如果匹配的规则只是500条规则中的一部分,则可以使用上述过程为每个程序包制作一个较大的正则表达式,以准备正则表达式程序包。当其中一个大正则表达式找到匹配项时,您可以检查构成程序包的原始规则。为使此方法有效,您应该将更可能同时出现的规则聚类。我希望它可行。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。