安全规则中的正则表达式

admin 2023年12月18日08:59:12评论20 views字数 1632阅读5分26秒阅读模式

背景

不论是商业安全产品还是开源安全产品,在规则运营中,写正则一直是很重要的一个事情,而正则使用中有一些基础知识,可能会被很多人忽视。

比如 ^号是匹配每一行的开头还是匹配一个文件的开头呢?在 yara、modsecurity、suricata 等开源安全产品引擎中答案都是一样的吗?

比如 捕获分组、断言 等用法是所有引擎都支持的吗?

捕获分组、断言 等用法是所有引擎都支持的吗?

每个产品用的正则引擎库可能是不同的,所以能支持的特性、写法会稍微有些差别。

在c语言中,pcre库[1]应该是应用最广泛的正则引擎库,modsecurity、早期的yara都是用的它。

你可以在 https://www.debuggex.com/cheatsheet/regex/pcre 这个站点查看 PCRE、JavaScript、Python 支持的用法区别。

^号是匹配每一行的开头还是匹配一个文件的开头呢?

举个例子,在应用广泛的waf规则集crs中,有一条规则是检查响应内容是不是以 #!/ 开头,已检查 #!/bin/bash 等脚本源码泄露,它的规则如下

SecRule RESPONSE_BODY "@rx ^#!s?/" 
    "id:950140,
    ...

实际上这条规则就和预期不同。在 modsecurity v3版本中,实际上它是在匹配响应内容"每一行"是否以 #!/ 开头。

modsecurity的正则引擎是pcre,所以 ^号是匹配每一行的开头还是匹配一个文件的开头,这取决于 PCRE_MULTILINE 修饰符是否开启。

在 https://github.com/SpiderLabs/ModSecurity/blob/v3.0.9/src/utils/regex.cc#L68

PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(pattern.c_str());
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
if (ignoreCase) {

代码中看到 PCRE_MULTILINE选项 默认是开启的,所以^号匹配每一行的开头。所以上面的规则可以优化成

SecRule RESPONSE_BODY "@rx ^(.{10})"           // 先取出响应头前十个字节
    "id:950140,
    ...
    setvar:'tx.first_ten_chars=%{tx.1}',
    chain"

    SecRule TX:FIRST_TEN_CHARS "@rx ^#!s?/"    // 针对前十个字节做匹配
      ..."

更多讨论,可以看 https://github.com/coreruleset/coreruleset/issues/3266。modsecurity v3、modsecurity v2、Coraza 等表现都不一致。

其他语言的正则库提供的接口也会提供MULTILINE修饰符,比如Python如下

>>> import re
>>> re.findall("^2","1n2n3")        # 默认没有开启MULTILINE,^就只匹配文本的开头
[]
>>> re.findall("^2","1n2n3",re.MULTILINE)   # 开启MULTILINE,^就会匹配每一行的开头
['2']
>>> re.findall("(?m)^2","1n2n3")      # (?m) 也可以开启MULTILINE
['2']

总结

虽然正则初学者可以用大模型去写正则,但是也应该了解到不同引擎支持的正则特性不同、正则的修饰符等基础知识。

在规则编写前,也应该清楚正则引擎默认开启的修饰符选项有哪些。

参考资料

[1]

pcre库: https://www.pcre.org/


原文始发于微信公众号(leveryd):安全规则中的正则表达式

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月18日08:59:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   安全规则中的正则表达式http://cn-sec.com/archives/2311409.html

发表评论

匿名网友 填写信息