10.10.1. Suricata 快速模式匹配机制详解

若规则中显式设置了 'fast_pattern' 关键字,Suricata 将直接采用该内容作为快速模式匹配项。每条规则中 'fast_pattern' 关键字仅能设置一次。若未设置,Suricata 会自动选择最合适的内容作为快速模式匹配项。

下文将阐述 Suricata 自动确定快速模式匹配项的逻辑规则。

需注意:当规则中存在正向(非否定)内容匹配项时,否定型内容匹配项在快速模式选择过程中会被忽略。反之,则会纳入考量范围。

快速模式选择标准如下:

  1. Suricata 首先识别规则中具有最高"优先级"的所有内容匹配项。优先级基于匹配的缓冲区类型,通常应用层缓冲区具有更高优先级(数值越小优先级越高)。但 http_method 缓冲区例外,其优先级低于常规的 content 缓冲区。

  2. 在步骤1筛选出的最高优先级内容匹配项中,选择字符/字节长度最长的作为快速模式匹配项。

  3. 若多个内容匹配项具有相同最高优先级且长度相同,则选择字符/字节多样性得分("模式强度")最高者作为快速模式匹配项。具体算法详见 附录A

  4. 若多个内容匹配项具有相同最高优先级、相同长度及相同模式强度,则选择缓冲区("list_id")注册时间最晚者作为快速模式匹配项。

  5. 若多个内容匹配项具有相同最高优先级、相同长度、相同模式强度且属于同一缓冲区(即list_id相同),则选择规则中从左到右最先出现的匹配项作为快速模式匹配项。

值得注意的是,对于具有相同优先级、长度和模式强度的内容匹配项,'http_stat_msg'、'http_stat_code' 和 'http_method' 会优先于常规 'content' 匹配项被选中。

10.10.1.1. 附录

10.10.1.1.1. 附录A - 模式强度算法

算法实现位于 detect-engine-mpm.c。模式强度"得分"初始为零,从左至右扫描字节数组中的每个字符/字节:若该字符/字节首次出现,字母字符加3分;可打印字符或0x00/0x01/0xFF加4分;其他字符加6分。若字符/字节重复出现则加1分。最终返回总分。

/** \brief 计算模式强度值
 *
 *  字符多样性高的模式得分更高
 *  字母字符得分较低
 *  其他可打印字符及特定控制码得分中等
 *  其余字符得分最高
 *  长模式优于短模式
 *
 *  \param pat 模式字节数组
 *  \param patlen 模式长度
 *
 *  \retval s 模式强度得分
 */
 uint32_t PatternStrength(uint8_t *pat, uint16_t patlen) {
     uint8_t a[256];
     memset(&a, 0 ,sizeof(a));
     uint32_t s = 0;
     uint16_t u = 0;
     for (u = 0; u < patlen; u++) {
         if (a[pat[u]] == 0) {
             if (isalpha(pat[u]))
                 s += 3;
             else if (isprint(pat[u]) || pat[u] == 0x00 || pat[u] == 0x01 || pat[u] == 0xFF)
                 s += 4;
             else
                 s += 6;
             a[pat[u]] = 1;
         } else {
             s++;
         }
     }
     return s;
 }