Fragscapy:绕过防火墙和IDS的新工具

iso60001  403天前

22.png

Fragscapy是什么?

在Amossys公司中,我们经常需要分析防火墙和IDS的功能及其配置,这往往很费时费力。自然,我们需要开发一些基本工具和脚本来进行自动化分析。而Fragscapy旨在对这些工具和脚本进行改进和整合,最终得到一个一个自动化、模块化、可扩展的Python 3项目。顾名思义,Fragscapy是基于Scapy来处理修改网络数据包的。

简而言之,Fragscapy是一个可以测试防火墙保护能力的工具。它背后的原理其实很简单:

33.png

Fragscapy运行的流程是:

  1. 与目标应用进行交互(通常是基于HTTP协议的wget命令,或是更底层协议的ping命令)。

  2. 拦截传输的数据包。

  3. 对数据包进行修改。这是整个过程中最重要的一步,也是fuzz的地方。我们的目标是获得一个经过重重修改后依然可被服务器正确解析但又能绕过防火墙的数据包。

  4. 发送修改后的数据包并等待响应。

  5. 回到步骤1,但是使用不同的修改方法。

如何修改?

好的,大家应该明白这个工具最有趣的部分发生在第3步的修改数据包。那么在这个阶段中到底发生了什么呢?

从技术上讲,修改操作可以看作一个函数,它接收数据包然后再返回不同的数据包。在这期间,任何事情都可能发生:数据包可以被修改、延迟、删除、替换、切分、重新分组……该工具目前包括一些基本的数据包修改,例如:

  • 丢弃数据包(以某种概率执行,或者指定某个特殊的数据包)

  • 延迟数据包传递

  • 对数据包进行过滤和重新排序,

  • 对IPv4和IPv6数据包进行分片

  • 分割TCP数据包

  • 修改数据包的任何字段。

想要知道修改数据包的更多细节,可以在fragscapy/modificatons/中查看详细的python代码

如何使用这个很棒的工具?

示例1:如何发现Linux中的未知特性

先让我们看一个简单的例子。假设有以下场景,我们试图访问目标服务器80和8080端口(涉及web服务),但是iptables拦截了对8080端口的请求。

44.png

使用Fragscapy

现在,先让我们尝试围绕IPv6分片进行fuzz测试。Fragscapy的所有配置都围绕以下两点:

  • 一个JSON配置文件(规定测试行为)

  • 命令行选项(用于输出、日志等)

其中JSON配置文件ipv6_frag.json定义了测试的3个方面:

1.运行的命令:通过curl来获取80和8080端口的连通性,只有当端口80可连通,8080端口被拦截,才说明防火墙正常工作

2.防火墙捕捉的特定数据包:无法确认,因此在默认情况下所有数据包都会被捕捉

3.修改方法:通过指定参数实现,输入和输出都可修改。

{
  "cmd": "/usr/bin/curl -6 -f -m 1 http://www.example.com:80 -o results/http_{i}_{j}.html; e1=$?; /usr/bin/curl -6 -f -m 1 http://www.example.com:8080 -o results/alt_{i}_{j}.html; e2=$? if [ $e1 -eq 0 && $e2 -ne 0 ]; then return 0; else return 1; fi",

  "nfrules": [
    {"host": "www.example.com", "port": 80, "ipv4": false, "input_chain": false}
  ],

  "input": [
  ],

  "output": [
    {
          "mod_name": "ipv6_frag",
          "mod_opts": "range 10 3000 10"
    }
  ]
}

我们计划将数据包进行分段,分段大小从10字节到3000字节,跨度为10。最后,启动下面的命令开始进行测试:

fragscapy start fragment.json \
  -o run/std/stdout_{i}_{j}.txt \
  -e run/std/stderr_{i}_{j}.txt \
  -W run/pcap/local_{i}_{j}.txt \
  -w run/pcap/remote_{i}_{j}.txt

fragscapy命令有多个选项来指定输出哪些日志(标准输出和错误信息等)。这样我们就可以查看在测试中到底发生了什么。{i}{j}只是python格式语法,会被数字所替代。

想了解命令的更多信息,可以通过以下方式了解:

fragscapy --help
fragscapy start --help

“惊喜”的结果

有多种方法可以检验测试是否正确。首先,fragscapy start命令显示了测试结果(0 = pass, other = fail)。

100%|██████████████████████████████████████████████████████████████████|300/300
Results (300 tests done over 300 scenarios)
==================
Pass : 174
    n°0_0, n°127_0, n°128_0, n°129_0, n°130_0, n°131_0, n°132_0, n°133_0, ...
Fail : 126
    n°1_0, n°2_0, n°3_0, n°4_0, n°5_0, n°6_0, n°7_0, n°8_0, n°9_0, n°10_0, ...
Not Done : 0

从以上进度条可以看出来,总共需要进行300次测试,结果包括三个部分:

  • 通过的测试(这里是174个)

  • 未通过的测试(这里是126)

  • 尚未完成的测试(这里是0),主要指测试程序中断时的状况

其中174个通过的测试是指成功获取80端口的页面,但没能获取8080端口页面。我们可以轻易发现,前126个测试(片段大小在10到1270之间)未包含在内。这时我们就可以通过日志来了解到底发生了什么。

通过查看results/目录下的日志文件,我们可以看到8080端口的页面从未成功获取,但是80端口的页面在#1#126的结果中也未能获取。到底发生了什么?

run/pcap/目录中有我们所捕获的数据包。经过简短的研究,发现小于1280字节的片段都被拒绝了……同时,1280是IPv6数据包的下限,这可能不是一个巧合。

后来我们发现,只要小于1280字节的片段都会被拒绝,但没有任何文档记录了这一点。我们只能猜测是Linux内核丢弃了这些片段,而在Linux 5.0中这一现象已不存在。

这就是Fragscapy的使用方法:配置、测试、分析日志和结果。当然,在以上这个简单的例子中,我们没能绕过iptables,但是却意外发现了iptables的一个奇怪行为。

示例2:如何绕过防火墙

现在,让我们更深入地使用Fragscapy进行测试。以下示例来自一个真实的场景,情况如下:

55.png

我们将从“User”区域fuzz在DMZ中的web服务器。中间的防火墙已经配置好,会拦截带有特定参数的请求。让我们进行多种测试,看看会发生什么:

fragment_ipv4.json:

{
  "cmd": "/usr/bin/curl -f -m 1 http://www.example.com/index.html?azerty -o results/{i}_{j}.html",

  "nfrules": [
    {"host": "www.example.com", "port": 80, "ipv6": false, "input_chain": false}
  ],

  "input": [
  ],

  "output": [
    {
          "mod_name": "ipv4_frag",
          "mod_opts": "range 1 1000"
    },
    {
          "mod_name": "drop_proba",
          "mod_opts": "seq_float 0.1 0.2 0.3 0.4 0.5",
          "optional": true
    },
    {
          "mod_name": "duplicate",
          "mod_opts": "seq_str first last random",
          "optional": true
    },
    {
          "mod_name": "reorder",
          "mod_opts": "seq_str reverse random",
          "optional": true
    }
  ]
}

segment_tcp.json:

{
  "cmd": "/usr/bin/curl -f -m 1 http://www.example.com/index.html?azerty -o results/{i}_{j}.html",

  "nfrules": [
    {"host": "www.example.com", "port": 80, "input_chain": false}
  ],

  "input": [
  ],

  "output": [
    {
          "mod_name": "tcp_segment",
          "mod_opts": "range 1 1000"
    },
    {
          "mod_name": "drop_proba",
          "mod_opts": "seq_float 0.1 0.2 0.3 0.4 0.5",
          "optional": true
    },
    {
          "mod_name": "duplicate",
          "mod_opts": "seq_str first last random",
          "optional": true
    },
    {
          "mod_name": "reorder",
          "mod_opts": "seq_str reverse random",
          "optional": true
    }
  ]
}

相关命令如下:

fragscapy start fragment_ipv4.json segment_tcp.json \
  -o run/std/stdout_{i}_{j}.txt \
  -e run/std/stderr_{i}_{j}.txt \
  -W run/pcap/local_{i}_{j}.txt \
  -w run/pcap/remote_{i}_{j}.txt \
  --append

基本上,我们运行Fragscapy的目的是为了能顺利获取带有参数azertyindex.html页面内容。除了IPv4数据包切片处理,还有其他很多混淆设置。在运行了144000个测试,数小时后,结果如下:

100%|██████████████████████████████████████████████████████████████|72000|72000
Results (666000 tests done over 72000 scenarios)
==================
Pass : 0

Fail : 666000
    n°0_0, n°1_0, n°2_0, n°2_1, n°2_2, n°2_3, n°2_4, n°2_5, n°2_6, n°2_7, ...
Not Done : 0

100%|██████████████████████████████████████████████████████████████|72000|72000
Results (666000 tests done over 72000 scenarios)
==================
Pass : 98
    n°0_0, n°1_0, n°2_0, n°2_1, n°2_2, n°2_3, n°2_4, n°2_5, n°2_6, n°2_7, ...
Fail : 665987
    n°22_5, n°23_3, n°25_5, n°32_1, n°32_6, n°33_8, n°34_1, n°35_6, n°35_7, ...
Not Done : 0

结果的上半部分显示了IPv4数据包分片测试的结果。没有什么特别的,全都失败了,这意味着要么防火墙拦截了数据包,要么传递的数据包对web服务来说无法解析。

但是,结果的下半部分,TCP分片测试则得到了一些成功的结果。从results/目录的内容上看,防火墙并没有很好地处理从大小1到46的片段,自然就没有触发拦截规则,但web服务可以完美地重构请求并响应。

没错,这个防火墙的缺陷被我找到了,通过使用较小的数据包片段就能绕过防火墙。

示例3:劫持Fragscapy以获取乐趣

让我们最后用一个有趣的例子来演示Fragscapy还可以做什么。我们现在知道它可以用于针对安全产品进行测试,但我们也可用其中的机制做其他的事。我们可以把Fragscapy配置为HTTP代理,只是看起像但不是。

相关配置文件如下:

{
  "cmd": "while true; do sleep 1; done",

  "nfrules": [
    {"port": 80, "output_chain": false},
    {"port": 8080, "input_chain": false}
  ],

  "input": [
    {
          "mod_name": "field",
          "mod_opts": ["TCP", "sport", 8080]
    },
    {
          "mod_name": "field",
          "mod_opts": ["TCP", "chksum", "none"]
    }
  ],

  "output": [
    {
          "mod_name": "field",
          "mod_opts": ["TCP", "dport", 80]
    },
    {
          "mod_name": "field",
          "mod_opts": ["TCP", "chksum", "none"]
    }
  ]
}

以上这个配置文件只会运行一个无限循环的命令,它实际上不进行任何测试。它把8080端口接收到的数据包传递给80端口,再把80端口的响应传递给8080端口。

fragscapy start http_proxy.json

现在,你可以通过8080端口访问80端口,至少你本地的浏览器和工具是这样的。你可以尝试访问http://www.example.com:8080,应该会得到80端口的页面。

欢迎改进

如果你想深入了解Fragscap,并基于现有的模块进行改进,可以访问Amossys的Github。如果你有勇气对核心代码进行修改,我们也是欢迎的。

本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://blog.amossys.fr/fragscapy-fuzzing-protocols-to-evade-firewalls.html

最新评论

昵称
邮箱
提交评论