ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Suricata SDP 关键字完整指南:用 sdp.* sticky buffer 精确匹配 SIP 消息中的会话描述字段

Suricata SDP 关键字完整指南:用 sdp.* sticky buffer 精确匹配 SIP 消息中的会话描述字段 网络安全【免费下载链接】suricataSuricata is a network Intrusion Detection System, Intrusion Prevention System and Network Security Monitoring engine developed by the OISF and the Suricata community.项目地址https://gitcode.com/gh_mirrors/su/suricata点击查看免费下载SDPSession Description Protocol是 SIP 信令中承载媒体会话描述的载体通常作为 SIP 请求如 INVITE或响应如 200 OK的消息体出现描述会话发起人、会话名称、媒体类型、端口、编解码器、带宽等关键信息。Suricata 将 SDP 字段实现为一组sdp.*检测关键字它们以 sticky buffer 形式工作让规则可以直接匹配结构化解析后的 SDP 字段而不是退化为对原始字节流的盲搜。读完本文你将掌握全部 17 个sdp.*关键字的语法与语义、会话级与媒体级字段的区分、底层 Rust 解析器与检测注册机制的工作原理并能编写针对 VoIP 会话劫持、媒体参数篡改等场景的检测规则。一、SDP 关键字概览SDP 关键字全部实现为sticky buffer粘性缓冲用于匹配 SDP 消息中的各个字段。Suricata 会先由 Rust 解析器将 SDP 消息体解析为结构化对象对应 rust/src/sdp/parser.rs 中的SdpMessage结构体再把各字段按需提供给检测引擎规则中的content等关键字随后在这些字段内容上执行匹配。当前仓库实现的关键字及其方向支持如下所有关键字方向均为 Both即对 SIP 请求与响应均可匹配关键字方向匹配字段SDP 行sdp.originBotho 发起人sdp.session_nameBoths 会话名称sdp.session_infoBothi 会话信息sdp.uriBothu 会话 URIsdp.emailBothe 邮箱地址sdp.phone_numberBothp 电话号码sdp.connection_dataBothc 连接数据sdp.bandwidthBothb 带宽信息sdp.timeBotht 会话激活时间sdp.repeat_timeBothr 重复时间sdp.timezoneBothz 时区调整sdp.encryption_keyBothk 加密密钥sdp.attributeBotha 会话属性sdp.media.mediaBothm 媒体描述媒体级sdp.media.session_infoBothi 媒体标题媒体级sdp.media.connection_dataBothc 连接数据媒体级sdp.media.encryption_keyBothk 加密密钥媒体级说明原文档的关键字汇总表未单列sdp.phone_number但正文中该关键字有完整的语法与示例章节且源码 rust/src/sdp/detect.rs 中明确注册了sdp.phone_number缓冲区因此上表将其补全为 17 个关键字。二、通用语法sticky buffer 的书写方式所有 SDP 关键字的用法一致以sdp.xxx作为缓冲区修饰符sticky buffer后接content关键字指定要匹配的内容以分号结尾。基本语法为sdp.field; content:匹配内容;content中可同时指定多个内容片段此时它们按顺序依次匹配也可配合nocase、depth、offset、within、distance等标准的 Suricata content 修饰符细化匹配行为。由于字段值是解析后的精确内容不含o等行前缀content必须与解析器产出的字段值一致——例如sdp.origin匹配的是o行去掉前缀后的完整字符串。三、会话级字段逐个掌握全部关键字3.1 sdp.origin匹配 SDP 请求或响应中的发起人Originator对应 SDP 的o行。该行包含用户名、会话 ID、会话版本、网络类型、地址类型和单播地址六段信息。sdp.origin; content:origin;其中origin是遵循 SDP Origino格式的发起人字符串。示例sdp.origin; content:SIPPS 105015165 105015162 IN IP4 192.168.1.2;从解析器看o行由parse_origin_line解析rust/src/sdp/parser.rs解析后将六个字段以空格重新拼接为完整字符串。测试用例oClarent 120386 120387 IN IP4 200.57.7.196得到Clarent 120386 120387 IN IP4 200.57.7.196与规则中content的写法完全对应。3.2 sdp.session_name匹配会话名称对应s行。sdp.session_name; content:session_name;其中session_name是遵循 SDP Session names格式的名称。示例sdp.session_name; content:SIP call;parse_session_namerust/src/sdp/parser.rs允许字母、数字和空格字符组成会话名测试用例sClarent C5CM解析为Clarent C5CM。3.3 sdp.session_info匹配会话信息对应可选的i行提供人类可读的会话说明。sdp.session_info; content:session_info;其中session_info是遵循 SDP Session informationi格式的描述。示例sdp.session_info; content:Session Description Protocol;3.4 sdp.uri匹配会话描述中的 URI对应可选的u行。sdp.uri; content:uri;其中uri是遵循 SDP scheme 的 URI。示例sdp.uri; content:https://www.sdp.proto原文档示例结尾未带分号为保持规则语法一致建议写作sdp.uri; content:https://www.sdp.proto;。解析器通过parse_urirust/src/sdp/parser.rs按 URI 合法字符集is_request_uri_char提取内容。3.5 sdp.email匹配联系人邮箱地址对应可选的e行格式通常为地址 (姓名)。sdp.email; content:email其中email是遵循 SDP scheme 的邮箱地址e。示例sdp.email; content:j.doeexample.com (Jane Doe);3.6 sdp.phone_number匹配联系人电话号码对应可选的p行。该关键字在原文档表格中未列出但在正文与源码注册rust/src/sdp/detect.rs中均有完整定义。sdp.phone_number; content:phone_number其中phone_number是遵循 SDP scheme 的电话号码p。示例sdp.phone_number; content:1 617 555-6011 (Jane Doe);3.7 sdp.connection_data匹配连接数据对应c行声明会话或媒体的连接地址网络类型、地址类型、连接地址可选 TTL 与地址数量。sdp.connection_data; content:connection_data;其中connection_data是遵循 SDP scheme 的连接信息c。示例sdp.connection_data; content:IN IP4 192.168.1.2解析器parse_connection_datarust/src/sdp/parser.rs对地址做了类型校验IP 地址必须是合法 IPv4/IPv6通过IpAddr::from_str校验多播地址要求至少带 TTL如IN IP4 224.2.36.42/127单播 IPv4 带 TTL/数量时格式为addr/ttl或addr/ttl/count测试用例cIN IP4 224.2.36.42/127/2解析为IN IP4 224.2.36.42/127/2而裸的多播地址cIN IP4 224.2.36.42会被判为解析失败。3.8 sdp.bandwidth匹配带宽信息对应b行。SDP 规范允许会话级出现零到多条b行因此该关键字支持多值匹配见第五节源码原理。sdp.bandwidth; content:bandwidth其中bandwidth是遵循 SDP scheme 的带宽信息b。示例sdp.bandwidth; content:AS:64parse_bandwidthrust/src/sdp/parser.rs目前仅接受CT、AS、TIAS三种带宽修饰符输出形如AS:64的修饰符:值字符串。3.9 sdp.time匹配会话激活时间对应t行格式为起始时间与结束时间两个十进制数字NTP 时间戳形式。sdp.time; content:time其中time是遵循 SDP scheme 的时间t。示例sdp.time; content:3034423619 30424624193.10 sdp.repeat_time匹配重复时间对应r行说明会话的重复周期包含间隔、时长等四个参数支持d/h/m/s后缀如7d 1h 0 25h。sdp.repeat_time; content:repeat_time其中repeat_time是遵循 SDP scheme 的重复时间r。示例sdp.repeat_time; content:604800 3600 0 900003.11 sdp.timezone匹配时区调整对应z行格式为时间 偏移对的序列。sdp.timezone; content:timezone其中timezone是遵循 SDP scheme 的时区z。示例sdp.timezone; content:2882844526 -1h 2898848070 03.12 sdp.encryption_key匹配加密密钥对应k行用于在 SDP 承载于安全通道时传递加密密钥信息。sdp.encryption_key; content:encryption_key其中encryption_key是遵循 SDP scheme 的密钥k。示例sdp.encryption_key; content:prompt3.13 sdp.attribute匹配会话属性对应a行。属性是 SDP 的扩展点可为零到多条因此同样支持多值匹配。属性可带属性名:属性值形式如rtpmap:8 PCMA/8000/1也可只有属性名如sendrecv。sdp.attribute; content:attribute其中attribute是遵循 SDP scheme 的属性a。示例sdp.attribute; content:sendrecvparse_attributesrust/src/sdp/parser.rs会把asendrecv解析为sendrecv、artpmap:8 PCMA/8000/1解析为rtpmap:8 PCMA/8000/1。四、媒体描述级字段m 行的子字段SDP 会话可以包含零或多个媒体描述Media Description每个媒体描述以m行开始其后可跟媒体级的i、c、b、k、a行。Suricata 提供四个媒体级子字段关键字用于区分会话级与媒体级的同类信息例如会话级c与媒体级c含义不同匹配时必须使用对应关键字。4.1 sdp.media.media匹配媒体描述中的媒体子字段对应m行包含媒体类型、端口可带/端口数、传输协议及格式列表。sdp.media.media; content:media其中media是遵循 SDP scheme 的媒体m。示例sdp.media.media; content:audio 30000 RTP/AVP 0 8 97 2 3解析器parse_media_descriptionrust/src/sdp/parser.rs对m行做了较严格的约束媒体类型仅接受audio、video、text、application、message五种端口为 15 位数字测试中70000因超范围解析失败传输协议仅接受udp、RTP/AVP、RTP/SAVP。测试用例maudio 40392 RTP/AVP 8 0解析为audio 40392 RTP/AVP 8 0。4.2 sdp.media.session_info匹配媒体描述中的会话信息子字段对应媒体级i行媒体标题。sdp.media.session_info; content:session_info其中session_info是遵循 SDP scheme 的描述i。示例sdp.media.session_info; content:Session Description Protocol4.3 sdp.media.connection_data匹配媒体描述中的连接数据子字段对应媒体级c行。sdp.media.connection_data; content:connection_data其中connection_data是遵循 SDP scheme 的连接c。示例sdp.media.connection_data; content:IN IP4 192.168.1.24.4 sdp.media.encryption_key匹配媒体描述中的加密密钥子字段对应媒体级k行。sdp.media.encryption_key; content:encryption_key其中encryption_key是遵循 SDP scheme 的密钥k。示例sdp.media.encryption_key; content:prompt五、源码级原理解析、注册与匹配链路理解底层实现有助于判断匹配内容的边界条件与适用场景。SDP 支持链路贯穿以下几个文件1. Rust 解析器rust/src/sdp/parser.rs 基于 nom 解析库实现。入口函数sdp_parse_messagerust/src/sdp/parser.rs严格按照 RFC 4566 的会话描述格式顺序解析v协议版本→o→s→ 可选i/u/e/p/c/b→ 一个或多个t/r时间描述 → 可选z/k/a→ 可选多个媒体描述每个m行后可跟媒体级i/c/b/k/a。解析结果保存在SdpMessage结构体中其中bandwidths、attributes、media_description为列表字段time_description为TimeDescription结构体数组每个包含time与可选的repeat_time。同文件内还包含覆盖各字段的单元测试rust/src/sdp/parser.rs可直接作为字段解析语义的参考。2. SIP 消息体挂接SDP 解析发生在 SIP 事务层。在 rust/src/sip/parser.rs 中parse_request与parse_response在解析完请求行/状态行与头部后对消息体调用opt(sdp_parse_message)因此Request.body/Response.body的类型是OptionSdpMessage。这也印证了 SDP 关键字对 SIP 请求与响应Direction: Both均可生效。3. 检测引擎注册rust/src/sdp/detect.rs 中的SCDetectSdpRegisterrust/src/sdp/detect.rs完成全部关键字的注册。每个关键字注册时使用SigTableElmtStickyBuffer声明名称、描述与文档锚点 URL调用SCDetectSignatureSetAppProto(s, ALPROTO_SIP)将签名绑定到 SIP 应用层协议意味着使用sdp.*关键字的规则只会在 SIP 流量上生效通过SCDetectHelperBufferMpmRegister或SCDetectHelperMultiBufferMpmRegister注册缓冲获取回调*_get函数后者依据方向从tx.request.body或tx.response.body取出对应字段内容交给 MPM 匹配。值得注意的差异sdp.origin、sdp.session_name、sdp.session_info、sdp.uri、sdp.email、sdp.phone_number、sdp.connection_data、sdp.timezone、sdp.encryption_key属于单值字段使用helper_keyword_register_sticky_buffer注册而sdp.bandwidth、sdp.time、sdp.repeat_time、sdp.attribute、sdp.media.media、sdp.media.session_info、sdp.media.connection_data、sdp.media.encryption_key由于字段本身可多次出现注册为多缓冲区multi bufferlocal_id参数用于索引第 N 个字段值规则可以对列表中的每个值分别匹配如多组b或a行、多个媒体描述。4. 日志联动解析出的 SDP 结构化数据同样用于 EVE JSON 日志输出。在 rust/src/sip/log.rs 中SCSipLogJson会为请求与响应分别调用sdp_log输出sdp对象其字段结构attributes、bandwidths、connection_data、email、encryption_key、media_descriptions、origin、session_name、time_description等定义在 etc/schema.json。检测与取证日志共享同一份解析结果。六、实战组合规则编写示例将多个sdp.*关键字与 SIP 关键字组合可以精确刻画 VoIP 会话特征。以下规则检测携带特定会话名、发起人与媒体类型组合的 SIP INVITE 请求alert sip any any - any any (msg:SDP: suspicious SIP call setup; sdp.session_name; content:SIP call; sdp.origin; content:SIPPS 105015165 105015162 IN IP4 192.168.1.2; sdp.media.media; content:audio 30000 RTP/AVP 0 8 97 2 3; sid:1000001; rev:1;)编写时需注意的约束必须匹配解析后的完整字段值content匹配的是去掉行前缀o、s等之后的字符串且多字段以空格分隔。例如sdp.origin匹配SIPPS 105015165 105015162 IN IP4 192.168.1.2而不是oSIPPS ...。字段边界由解析器决定如连接数据中的地址必须合法IP 校验、媒体端口必须为 15 位数字、带宽修饰符仅CT/AS/TIAS。与解析器语义不符的报文可能直接解析失败规则自然不会命中。仅作用于 SIP 流量sdp.*规则自动绑定ALPROTO_SIP不会在其他协议上误报。区分会话级与媒体级同一字段名如i、c、k在会话级与媒体级存在两套关键字规则需要按目标信息所在层级选择。多值字段的匹配语义sdp.bandwidth、sdp.attribute、sdp.media.media等会针对字段列表中的每一项逐一提供缓冲因此content命中任意一条即视为命中。七、适用前提与版本说明本文所述关键字以当前仓库文档 doc/userguide/rules/sdp-keywords.rst 为准实现代码位于 rust/src/sdp/detect.rs 与 rust/src/sdp/parser.rs属于 Rust 实现的 SIP/SDP 解析与检测模块源码注释标明编写于 2024 年。要使用这些关键字需保证构建的 Suricata 包含 Rust 支持且启用了 SIP 应用层协议解析。规则调试时可结合suricata -T规则语法检查与 EVE JSON 日志中输出的sip.sdp对象核对字段实际解析值再据此调整content内容。赞分享网络安全【免费下载链接】suricataSuricata is a network Intrusion Detection System, Intrusion Prevention System and Network Security Monitoring engine developed by the OISF and the Suricata community.项目地址https://gitcode.com/gh_mirrors/su/suricata点击查看免费下载相关推荐aiortc SDP 协议深度解析会话描述协议的生成与解析终极指南aiortc SDP 协议深度解析会话描述协议的生成与解析终极指南 aiortc 是 Python 中基于 asyncio 的 WebRTC 和 ORTC 实音视频通信Suricata 规则编写指南integer-keywords 整数匹配关键字全解析Suricata 规则编写指南integer keywords 整数匹配关键字全解析 本文是一份面向 Suricata 规则编写者的技术指南系统讲解基于无符网络安全Suricata 解码层事件匹配decode-event 规则关键字完全指南Suricata 解码层事件匹配decode event 规则关键字完全指南 decode event 是 Suricata 规则语言中用于匹配 解码层de网络安全上一篇技术深度解析STL到STEP转换的核心算法与工程实现下一篇Windows-universal-samples 之 CameraOpenCVUWP 中基于 MediaFrameReader 与 OpenCV 逐帧图像处理的完整实现解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进