绕过nftables/PacketFilter防火墙过滤规则传输ICMP/ICMPv6数据包的漏洞详解(上)

lucywang Web安全 2019年5月9日发布
Favorite收藏

导语:本文将讲述如何绕过nftables/PacketFilter防火墙过滤规则传输ICMP/ICMPv6数据包的漏洞。

背景知识介绍

目前的防火墙总共分四类:

包过滤防火墙:包过滤防火墙不检查数据区,包过滤防火墙不建立连接状态表,前后报文无关,应用层控制很弱。

应用网关防火墙:不检查IP、TCP标头,不建立连接状态表,网络层保护比较弱。

状态检测防火墙:不检查数据区,建立连接状态表,前后报文相关,应用层控制很弱。

复合型防火墙:可以检查整个数据包内容,根据需要建立连接状态表,网络层保护强,应用层控制细,会话控制较弱。

什么是PacketFilter(包过滤)?

包过滤是一种内置于Linux内核路由功能之上的防火墙类型,其防火墙工作在网络层。传统的包过滤功能在路由器上常可看到,而专门的防火墙系统一般在此之上加了功能的扩展,如状态检测等,它通过检查单个包的地址,协议,端口等信息来决定是否允许此数据包通过。

数据包过滤用在内部主机和外部主机之间, 过滤系统是一台路由器或是一台主机。过滤系统根据过滤规则来决定是否让数据包通过。用于过滤数据包的路由器被称为过滤路由器。

数据包信息的过滤

数据包过滤是通过对数据包的IP头和TCP头或UDP头的检查来实现的,主要信息有:

· IP源地址

· IP目标地址

· 协议(TCP包、UDP包和ICMP包)

· TCP或UDP包的源端口

· TCP或UDP包的目标端口

· ICMP消息类型

· TCP包头中的ACK位

· 数据包到达的端口

· 数据包出去的端口

在TCP/IP中,存在着一些标准的服务端口号,例如,HTTP的端口号为80。通过屏蔽特定的端口可以禁止特定的服务。包过滤系统可以阻塞内部主机和外部主机或另外一个网络之间的连接,例如,可以阻塞一些被视为是有敌意的或不可信的主机或网络连接到内部网络中。

过滤器的实现

数据包过滤一般使用过滤路由器来实现,这种路由器与普通的路由器有所不同。

普通的路由器只检查数据包的目标地址,并选择一个达到目的地址的最佳路径。它处理数据包是以目标地址为基础的,存在着两种可能性:若路由器可以找到一个路径到达目标地址则发送出去;若路由器不知道如何发送数据包则通知数据包的发送者“数据包不可达”。

过滤路由器会更加仔细地检查数据包,除了决定是否有到达目标地址的路径外,还要决定是否应该发送数据包。“应该与否”是由路由器的过滤策略决定并强行执行的。

什么是nftables?  

nftables 是新的数据包分类框架,新的linux防火墙管理程序,旨在替代现存的 {ip,ip6,arp,eb}_tables。简而言之:

1.它在 Linux 内核版本高于 3.13 时方可使用;

2.它有一个新的命令行工具 ntf,它的语法与 iptables 不同;

3.它也包含了一个兼容层,让你在新的 nftables 内核框架之上运行 iptables 命令;

4.它提供了通用的集合基础允许你建立映射和关联。你可以使用这个新特性把你的规则集分类到多维树中,这大大地减少了找到包最终的行为之前需要检查的规则的数量;

nftables 的特点

1.拥有一些高级的类似编程语言的能力,例如定义变量和包含外部文件,即拥有使用额外脚本的能力,nftables也可以用于多种地址簇的过滤和处理。

2.不同于iptables, nftables并不包含任何的内置表。由管理员决定需要哪些表并添加这些表的处理规则。

3.表包含规则链,规则链包含规则。

Synacktiv公司的网络安全专家在对防火墙实施的安全评估中,观察到一个奇怪的防火墙行为,它可能会影响多个IP堆栈的漏洞。

本文分析了Linux nftables和OpenBSD PacketFilter的潜在行为,是如何形成绕过 nftables/PacketFilter 防火墙过滤规则传输 ICMP/ICMPv6 数据包的漏洞的? 

起初, Synacktiv 公司的网络安全专家认为这种攻击方式是他们第一个发现的,但之后他们发现2004年安全专家Fernando Gont也发布了一篇《如何检测你的IPv6地址组件是否易受到攻击》的文章,在文章中他在本文中,探讨了IPv6的不同组件将如何受到基于ND的攻击。但是,这篇文章的局限之处在于它当时没有确定这种攻击是不是发生在Packet Filter和nftables中。

ICMP和ICMPv6

ICMP和ICMPv6是互联网的主要支持协议,这些协议是为连接测试和数据包没有到达目的地时的错误信号而设计的。接收ICMP消息可以让应用程序理解失败的原因,比如数据包太大,没有可用路由等等。

ICMP消息

从协议本身来说,ICMPv6和基于IPv4的ICMP协议发生了很大的变化,是两个不同的协议,所以为了区分两者,基于IPv6的ICMP协议我们用ICMPv6来命名,协议识别号58。而ICMP一般指代传统的IPv4下的协议。而ICMP协议我们最常用的功能莫过于Ping了,这是网络工程师判断故障或问题的第一步。

ICMPv6是IPv6非常重要的基础性协议,在IPv6中许多基础机制都是由ICMPv6定义及完成,例如地址冲突检测、地址解析、无状态自动获取等等。ICMPv6定义了多种消息类型和机制来实现这些功能。在IPv6包头中,NextHeader=58则表示IPv6包头后封装着一个ICMPv6消息。

1.jpg

ICMPv6消息有两大类:差错消息及信息消息。

2.jpg

和ICMP一样,ICMPv6仍然是用于传递错误信息和网络故障诊断的。ICMP V6除了基本的错误反馈和信息控制功能外,还包括一些使用ICMPV6的机制,如路径MTU发现(PDM)机制,PDM机制通过发送长度越来越大的数据包到达目的节点,当一个给定的数据包长度超过到达目的节点路径上最小的MTU时,该数据包将被丢弃,并发送一个数据包太大的消息给源点,从而源地址节点就知道了这条路径上最小的MTU为多少。

出于不同的目的,ICMPv6反馈的消息可以用类型和代码分别标识,每种标识都有不同的含义,例如,ICMP会反馈以下消息:

1.Echo回复和请求(类型1和8);

2.无法到达目的地(类型3);

3. source quench(类型4);

4.时间戳回复和请求(类型14和15);

……

ICMPv6则会反馈以下消息:

1. 无法到达目的地(类型1);

2.数据包太大(类型2);

3. 超时(类型3);

4.参数问题(类型4);

5. 路由器请求和路由器通告(133和134型);

6.邻居请求和邻居通告(类型135和136);

……

目前,其中的很多消息类型已经被弃用,我们可以根据不同目的,大致将ICMP消息分为三类:

1.请求:它们由主机生成以查询某些信息;

2.回复:它们是上述ICMP请求的ICMP响应;

3.错误:它们是由网络设备或主机在无法处理数据包时创建的;

本文重点介绍错误消息,这个类别非常有趣,因为它的消息会被作为带外数据(out-of-band,OOB)进行发送,以响应另一个协议的第4层通信消息。传输层协议使用带外数据(out-of-band,OOB)来发送一些重要的数据,如果通信一方有重要的数据需要通知对方时,协议能够将这些数据快速地发送到对方。为了发送这些数据,协议一般不使用与普通数据相同的通道,而是使用另外的通道。

例如,UDP数据包可能会生成ICMP错误。这些错误通常被封装在ICMP有效载荷、IP标头以及接下来的64字节的出错包中。图1显示了主机B拒绝关闭端口上的数据包的行为:

为:

3.png

带外ICMP错误的示例

已知的攻击和缓解措施

作为信号协议,ICMP消息可以改变接收系统的IP栈的行为。例如,ICMP Redirect和ICMPv6 Router通告可以改变主机的路由表。

恶意用户可以滥用ICMP来破坏网络操作,以下就是过去与ICMP有关的各种攻击方法:

1.ICMP孔http://samy.pl/pwnat/是利用ICMP消息遍历NAT的概念,它要求发起者在NAT之后;

2.ICMP隧道滥用ICMP协议将任意数据封装在ICMP消息之上;

3.ICMP ECHO放大使用广播执行DoS;

4.通过攻击MTU发现进程或数据包拥塞信号,降低网络数据,拥塞(Congestion)是评价一个后端设计是否能绕线绕的通的重要评价指标;

5.ICMPv6 NDP攻击,类似于IPv4中的ARP攻击;

6.ICMPv6 MLD发现外加DoS,类似于IGMP攻击;

通过正确配置操作系统的IP堆栈,可以缓解以上攻击。有趣的是,可以在不使用操作系统的防火墙特性下(例如:sysctl,netsh,…)启用各种ICMP保护。

在Linux上使用sysctl的示例:

# sysctl -a -r '^net\.ipv[46]\.(icmp|conf\.default\.accept)' | cut -d= -f1
net.ipv4.conf.default.accept_local 
net.ipv4.conf.default.accept_redirects 
net.ipv4.conf.default.accept_source_route 
net.ipv4.icmp_echo_ignore_all 
net.ipv4.icmp_echo_ignore_broadcasts 
net.ipv4.icmp_errors_use_inbound_ifaddr 
net.ipv4.icmp_ignore_bogus_error_responses 
net.ipv4.icmp_msgs_burst 
net.ipv4.icmp_msgs_per_sec 
net.ipv4.icmp_ratelimit 
net.ipv4.icmp_ratemask 
net.ipv6.conf.default.accept_dad 
net.ipv6.conf.default.accept_ra 
net.ipv6.conf.default.accept_ra_defrtr 
net.ipv6.conf.default.accept_ra_from_local
...
net.ipv6.conf.default.accept_redirects 
net.ipv6.conf.default.accept_source_route 
net.ipv6.icmp.ratelimit

在理想情况下,危险的ICMP消息应该被每个主机的IP堆栈阻止,而不需要防火墙。但在实践中,安全加固通常由广域网和受限局域网之间的防火墙来实现。这就会产生一个问题,即ICMP和ICMPv6应该如何过滤?

ICMP应该如何过滤?

RFC建议的内容

在过滤ICMP消息时,阻止所有消息类型并不是一个好的缓解方式。它会降低整体用户体验,例如,阻止“太大的数据包” 类型,实际上就会完全阻止IPv6工作,并可能严重降低IPv4的性能。

RFC4890[10](2007)在第4.3.1章是明确说明允许ICMPv6的错误消息的,它们是不能被阻止的:

Error messages that are essential to the establishment and
maintenance of communications:
-  Destination Unreachable (Type 1) - All codes
-  Packet Too Big (Type 2)
-  Time Exceeded (Type 3) - Code 0 only
-  Parameter Problem (Type 4) - Codes 1 and 2 only

草案“过滤ICMP消息的建议”(2013)曾建议;“当设备充当网关或防火墙时,哪些ICMP和ICMPv6消息应该被接受、限制速率或拒绝。”该草案建议允许接受或限制以下消息:

ICMPv4-unreach-(net|host|frag-needed|admin);
ICMPv4-timed-(ttl|reass);
ICMPv6-unreach-(no-route|admin-prohibited|addr|port|reject-route);
ICMPv6-too-big;
ICMPv6-timed-(hop-limit|reass);
ICMPv6-parameter-unrec-option;
ICMPv6-err-expansion.

似乎人们对什么是安全的ICMP数据有不同的看法,通常认为,防火墙应该阻止来自WAN的所有入站ICMP和ICMPv6数据包(NDP除外),除非它们与已知的现有连接相关,,而已知的现有连接可以由有状态检测防火墙跟踪。

注意:草案“过滤ICMP消息的建议”(2013)目前已被升级更新了。

状态检测防火墙和配套的信息反馈机制

状态检测是比包过滤更为有效的安全控制方法。对新建的应用连接,状态检测检查预先设置的安全规则,允许符合规则的连接通过,并在内存中记录下该连接的相关信息,生成状态表。对该连接的后续数据包,只要符合状态表,就可以通过。这种方式的好处在于:由于不需要对每个数据包进行规则检查,而是一个连接的后续数据包(通常是大量的数据包)通过散列算法,直接进行状态检查,从而使得性能得到了较大提高;而且,由于状态表是动态的,因而可以有选择地、动态地开通1024号以上的端口,使得安全性得到进一步地提高。

事实上,状态检测防火墙实现了相关数据包的概念。这些相关数据包是与附加到现有连接的带外数据匹配的数据包。与此相关的概念不仅用于ICMP,还用于其他协议,如可能使用辅助TCP数据传送的FTP。

关于ICMP、带内和带外数据之间的关联是通过从封装在ICMP错误消息中的IP分组中提取“状态标识符”来完成的,如果连接已知,则使用此标识符在表中查找。

为了说明这个概念,我会举以下一个例子。在一个简单的网络中,如果我们希望只允许LAN上的主机通过端口1234上的UDP与WAN上的任何主机连接,且仍然希望A接收带外错误。在这种情况下,将使用以下高级防火墙配置:

1.允许从LAN到WAN udp端口1234的输入;

2.如果数据包与现有的允许连接相关,则允许从WAN到LAN的输入;

3.阻止所有输入;

传出的带内UDP数据将匹配规则1,输入的带外ICMP错误消息将匹配规则2,如图2所示,规则3将拒绝任何其他数据包。

6.png

通过提取内层对ICMP错误进行状态过滤

实际上,根据防火墙配置的语义不同,规则2实现的方式也不同。

什么是连接状态?

到目前为止,我们知道有状态防火墙会根据ICMP(或ICMPv6)错误推断状态。但剩下的问题是,哪些信息实际上是从内部IP数据包中提取的?

由于第4层协议具有不同的语义,每个协议都有自己的提取器,但我们在Packet Filter和nftables衍生物中观察到以下内容:

TCP使用以下字段构造状态:

1.内部IP源和IP目的地;

2.内部源和目标端口;

3.SEQ和ACK字段仅用于包过滤,但不用于nftables;

而UDP使用以下字段构造状态:

1.内部IP源和IP目的地;

2.内部源和目标端口;

而ICMP使用以下字段构造状态:

1.内部IP源和目的地;

2.不同类型的ICMP字段;

对于其他协议:

1.内部IP源和IP目的地;

2.协议的id;

3. 如果防火墙支持协议提供的属性(如SCTP或UDP-Lite端口),则将使用协议提供的属性(nftables可以,而Packet Filter不可以);

总而言之,当防火墙收到带外ICMP反馈的错误消息时,它会执行以下操作:

1.解码IP/ICMP或IPv6/ICMPv6标头;

2.从封装的IP或IPv6数据包中提取状态;

3.尝试匹配现有状态列表中的“状态标识符”;

4.如果内部IP数据包状态与现有状态匹配,则将数据包标记为相关。

获取ICMP 

我们发现当提取内部包来寻找状态时,与外部数据包的相关性都将丢失。这意味着,只要封装的数据包可以与现有连接相关,整个数据包就会被标记为相关。然后,在大多数情况下这个数据包将被允许通过。

被恶意篡改的ICMPv6数据包经常滥用此行为,这种攻击会以使用过滤规则的主机为攻击目标。攻击时,该恶意数据包会被封装在一个具有合法状态的数据包中,如下所示。

ICMP-Reachable packet:
[ IP [email protected] [email protected] type=ICMP ]
[ ICMP ty[email protected] [email protected] ]
[ IP [email protected] [email protected] ]
[ UDP [email protected] dport=Pa ]
M: the attacker IP
H: the destination IP on which ICMP should be filtered
A: host IP from which the attacker knows an existing session with B
B: host IP from which the attacker knows an existing session with A
Pa: the port used by A its UDP session with B
Pb: the port used by B its UDP session with A
Type: the ICMP type of an out-of-band error packet (example 3)
Code: the ICMP code of an out-of-band error packet (example 3)

在这种情况下,恶意ICMPv6数据包就会运行被通过, nftables和Packet Filter在实现时都受此攻击的影响。

8.png

状态ICMP过滤被攻击的过程

接下来,我将介绍Linux和OpenBSD的实现细节,以剖析这种恶意数据包为何会通过以及这种行为如何被预防。

本文翻译自:https://www.synacktiv.com/posts/systems/icmp-reachable.html如若转载,请注明原文地址: https://www.4hou.com/web/17523.html
点赞 1
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论