如何使用 Snort 检测 DNS 标签解码 DoS(DNS 解压缩时的交叉引用)?

如何使用 Snort 检测 DNS 标签解码 DoS(DNS 解压缩时的交叉引用)?

我想添加一些规则或下载一些现成的规则来检测 DNS 标签解码 DoS(DNS 解压缩时的交叉引用),有人知道我该怎么做吗?

答案1

我不知道有任何已知的针对 DNS 使用的标签解码/压缩技巧的 DoS 攻击(也许是引用?)。也就是说,您可以设计一个规则来检测压缩指针的存在,如下所示byte_testbyte_test:2,&,0xc000,0;。这使用按位与来屏蔽除两个最高位之外的所有位,并查看它们是否都是“11”,这是压缩指针的标记(其余 14 位指定从有效负载的开头到引用的 DNS 标签的偏移量)。如果该 byte_test 返回 true,则您已检测到这样的指针,然后您可以围绕它构建规则的其余部分。您需要遍历 DNS 数据包,直到到达您期望存在此类指针的位置。

查看 DNS 协议来了解这个巧妙技巧的更多奇怪之处。


编辑:

仔细想想,我认为这实际上只能通过数据包的第二个字节来实现。不幸的是,除非你为任何选项doe_ptr指定一个,否则 Snort 会将每个新规则选项的 重置为有效负载的开头(我relativebyte_*思考)。我不认为一个字节选项可以相对于前一个字节选项,而只能相对于内容匹配。

因此,考虑到 99% 的 DNS 数据包永远不会使用第二个高字节的剩余 6 位,您可以先查找十六进制值0xc0,二进制为11000000。这可以替换第一个byte_test

alert udp any 53 -> any 1024: (msg:"DNS recursive Ptr test"; content:"|c0|"; byte_extract:1,0,dns_comp_ptr,relative,little; byte_test:1,=,dns_cmp_ptr,dns_comp_ptr,little; sid:12345; rev:1; classtype:yadda-yadda;)

为了:

  1. content:"|c0|";- 找到一个压缩指针。
  2. byte_extract:1,0,dns_comp_ptr,relative,little;- 抓取下一个字节并将其存储到变量中dns_comp_ptr(未经测试!我的偏移量可能不正确 - 可能需要添加+1)。
  3. byte_test:1,=,dns_cmp_ptr,dns_comp_ptr,little;- 测试一个字节,看它是否等于存储在的值dns_comp_ptrdns_comp_ptr以小端格式(我们在 Wireshark 中看到的显示方式)跳过指示的值。

如果最后一条byte_test返回 true,则规则的其余部分将验证并发出警报。当然,这都是理论上的。完全没有经过测试,我无法保证它会起作用。但它包含了需要检查 DNS 响应中的每个压缩指针的基本思想(对于 Google 域的响应,预计会有其中几个),以查看该指针是否通过至少跟踪一次指向自身。

无论如何,我能想到的唯一测试两个字节的方法是,您需要一种方法来将 跳转doe_ptr到紧接在压缩指针之前的字节,即通过内容。Snort 没有直接规定将 移动doe_ptr指定值的规则选项(尽管说实话,这确实是一个很酷的想法)。

正确放置后doe_ptr,您可以使用byte_test:2,&,0xc000,1,relative,little;屏蔽除前两位之外的所有位,看看它们是否与十六进制匹配。然后0xc000执行。再次未经测试,所以我的偏移量可能是错误的。我忘记了 Snort 如何精确地调整字节位置。byte_extract:2,0,dns_comp_ptr,little,bitwiseand 0x3fff;byte_test:2,=,dns_comp_ptr,dns_comp_ptr,little;

另外,这个bitwiseand 0x3fff东西是我自己创造的。 byte_extract目前没有办法进行位掩码(按位与运算)来只提取字节中的几个位。我编造了操作数。

PS,我没有可用的数据包来实际测试这一点。也许我可以找个时间拼凑一个并尝试一下。

相关内容