安全规则中的正则表达式

背景

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

比如 ^号是匹配每一行的开头还是匹配一个文件的开头呢?在 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):安全规则中的正则表达式

版权声明:admin 发表于 2023年12月17日 下午11:47。
转载请注明:安全规则中的正则表达式 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...