==Phrack Inc.== www.phrack.org Volume 0x0b, Issue 0x3f, Phile #0x13 of" name="description" />
自己翻译的一篇来自phrack的技术文章,已经得到原作者的许可。
主要讲述如何穿透Linux下的Netfilter防火墙,挺经典的。
完整的pdf文档下载 Breaking_Firewall.pdf
MILY: 宋体"> ==Phrack Inc.==
www.phrack.org
Volume 0x0b, Issue 0x3f, Phile #0x13 of 0x14
|=------=[ Breaking through a Firewall using a forged FTP command ]=-----=|
|=-----------------------------------------------------------------------=|
|=-------------=[ Soungjoo Han <kotkrye@hanmail.net> ]=------------------=|
|=---使用伪造的FTP命令穿透防火墙---=|
|=-----------翻译: pidan-----------=|
|=-----------日期: 2005/8----------=|
目录
1 - 简介
2 - FTP,IRC和Netfilter的状态检测
3 - 攻击场景I
3.1 - 第一次欺骗
3.2 - 第一次欺骗细节
4 - 攻击场景II - 非标准命令行
4.1 - 第二次欺骗细节
5 - 攻击场景III
5.1 - 被动FTP:背景信息
5.2 - 第三次欺骗细节
6 - 附录I 第二次欺骗的示范工具
7 - 附录II第二次攻击欺骗的示范例子
-[ 1 - 简介 ]
FTP协议使用两个连接。一个叫控制连接,另一个叫数据连接。FTP的命令和应答通过控制连接来交换,这个连接会存在于整个FTP会话过程中。另一方面,一个文件(或一个文件列表)通过数据连接来传送,这个连接是当每次文件传输时才新建立的。
通常出于网络安全的考虑,大多数防火墙不允许除FTP控制连接之外的任何连接连到FTP的服务端口(默认是TCP的21端口)。虽然如此,当一个文件传输时,防火墙临时地认可数据连接。为了做到这点,防火墙跟踪控制连接的状态,并检测跟文件传输相关的命令。这就是所谓的状态检测。
我已经试过三次攻击欺骗,通过使用一个伪造的FTP命令,欺骗防火墙的连接跟踪,可以使防火墙允许一个非法的连接通过。
我在Netfilter/IPTables上试验过,它是Linux2.4和2.6内核默认安装的防火墙。我肯定第一个欺骗能在Linux2.4.18内核上工作,第二个(第一个的变种)能在Linux2.4.28内核(Linux内核的最新版本)上工作。
这个缺陷已经告知了Netfilter项目组,他们会在Linux2.6.11内核版本中修正它。
-[ 2 - FTP,IRC和Netfilter的状态检测 ]
首先,让我们考察一下FTP,IRC(后面你会知道为什么要提到IRC)和Netfilter的状态检测。如果你已经掌握了,可以跳过这一章。
如前所述,FTP使用一个控制连接来交换命令和应答(以ASCII形式表示),相比之下,文件传输使用一个数据连接。
比如,当你在FTP提示符下输入“ls”或“get <a file name>”,FTP服务器(主动模式)会主动建立一个到FTP客户端的一个TCP端口号(数据端口)的数据连接,也就是你的主机。客户端要事先用PORT命令(一个FTP命令)发送数据端口号。
PORT命令的格式如下:
PORT<space>h1,h2,h3,h4,p1,p2<CRLF>
这里字符串“h1,h2,h3,h4”表示点分十进制的客户端的IP地址“h1.h2.h3.h4”。字符串“p1,p2”表示一个数据端口号(= p1 * 256 + p2)。地址和端口号都是十进制数。数据端口由客户端动态指定。另外,命令和应答以<CRLF>字符序列结尾。
Netfilter跟踪一个FTP控制连接,并获取TCP序列号和包含一个FTP命令行(以<LF>结尾)的数据包的数据长度。然后基于这些信息,它计算出下一个命令数据包的序列号。当一个这样序列号的数据包到达时,Netfilter分析数据包中的数据是否包含一个FTP命令。如果数据的头部是“PORT”,并且数据以<CRLF>结尾,于是Netfilter认为它是一个有效的PORT命令(实际的代码会更复杂),并从中取出IP地址和端口号。然后,Netfilter“期待”服务器主动建立一个到客户端指定的端口号的数据连接。当数据连接请求确实到达时,它会认可连接,同时连接建立。一个没完成的命令,即所谓的“不完全的”命令,会因为无法真实的跟踪而丢弃。
IRC(Internet中继聊天)是一个Internet聊天协议。一个IRC客户端可以用一个直接连接跟另一个客户端讲话。当一个客户端登录到服务器上时,他/她连接到一个IRC服务器(默认是TCP的6667端口)。另一方面,当客户端想跟别人通信时,他/她要建立一个直接连接到对端。为此,客户端事先发送一个所谓的DCC CHAT命令,类似于一个FTP PORT命令。Netfilter也跟踪IRC连接,它期待和认可一个直接聊天连接。
-[3 - 攻击场景I ]
---[ 3.1 - 第一次欺骗 ]
我成功的试过在Linux内核2.4.18上,通过欺骗连接跟踪模块,非法的连接到一个由Netfilter保护的FTP服务器的任何TCP端口。
大多数情况下,为了认可一些Internet服务如IRC聊天和FTP文件传输,IPTables管理员要配置状态数据包过滤规则。通常他们插入下列规则到IPTables的规则列表中:
iptables –A FORWARD –m state –state ESTABLISHED, RELATED –j ACCEPT
假定一个恶意用户从外部网络登录上FTP服务器,发送一个使用TCP的6667端口(这是一个缺省的IRC服务器端口号)的PORT命令,然后尝试从服务器下载一个文件。
FTP服务器主动建立一个到攻击者主机的数据端口6667的数据连接。在前面提到的状态数据包过滤规则下,防火墙认可这个连接。一旦连接被建立,防火墙的连接跟踪模块(在Linux内核2.4.18中)就有了安全的漏洞,把它错当成一个IRC连接。这样攻击者的主机能假装成一个IRC服务器。
如果攻击者下载一个文件,其由一个和DCC CHAT命令有相同样式的字符串组成,连接跟踪模块会错把数据包内容当作是一个DCC CHAT命令的文件传输。
结果,按规则要求需认可IRC相关的连接,防火墙允许任何主机连接假的IRC客户端(FTP服务器)上的在假的DCC CHAT命令中指定的TCP端口。为此,攻击者必须在入侵前上传这个文件。
总之,攻击者能够建立一个到FTP服务器任何TCP端口的连接。
---[ 3.2 - 第一次欺骗细节 ]
为了详细描述,我们假设网络的配置如下。
(a) 一个Netfilter/Iptables终端保护一个网络上的FTP服务器。所以外网用户只能连接到FTP服务器的服务端口。被许可的用户才能登录服务器和上传/下载文件。
(b) 受保护网络中的用户,包括FTP服务器主机,只能连接到外网的IRC服务器。
(c) 一旦(a)和(b)中提到的一个Internet服务被建立时,第二个与服务相关的连接(例如,FTP数据连接)会被临时地认可。
(d) 其它任何连接将被阻塞。
为了实现对IRC和FTP的状态检测,管理员要加载叫做ip_conntrack的IP连接跟踪模块到防火墙中,它包括分别对FTP和IRC进行跟踪的ip_conntrack_ftp和ip_conntrack_irc。Ipt_state也必须加载。
在这种条件下,攻击者能够轻松的建立一个程序登录到FTP服务器,然后使服务器主动地建立一个到他/她的主机的一个任意TCP端口的FTP数据连接。
假设他/她传输一个6667(缺省的IRC服务器端口)数据端口的PORT命令。
PORT 192,168,100,100,26,11\r\n
跟踪这个连接的ip_conntrack_ftp模块分析这个PORT命令并“期待”FTP服务器主动打开到攻击者主机指定端口的连接。
然后,攻击者发送一个FTP命令来下载一个文件,“RETR <a file name>”。服务器尝试连接攻击者主机的6667端口。在状态数据包过滤规则下,Netfilter认可这个FTP数据连接。
一旦连接被建立,ip_conntrack模块误认为这是一个IRC连接。ip_conntrack认为FTP服务器是一个IRC客户端,攻击者的主机是一个IRC服务器。如果假的IRC客户端(FTP服务器)为FTP数据连接传送数据包,ip_conntrack_irc模块会尝试从数据包中寻找一个DCC协议消息。
攻击者可以通过下面的手段使FTP服务器发送假的DCC CHAT命令。在入侵前,攻击者要事先上传一个由和DCC CHAT命令有相同样式的字符串组成的文件。
据我所知,一个DCC CHAT命令的格式如下:
"DCC<a blank>CHAT<a blank>t<a blank><The decimal IP address of the IRC
client><blanks><The TCP port number of the IRC client>\n"
例如:"DCC CHAT t 3232236548 8000\n"
在这个例子中,Netfilter允许任何主机主动打开到IRC客户端的例子中指定的TCP端口号的连接。当然,攻击者可以随意指定伪造的DCC CHAT命令消息中的TCP端口号。
如果这种数据包穿越防火墙,ip_conntrack_irc模块会误认为这个消息是一个DCC CHAT命令,并“期待”任意主机主动打开到FTP服务器上的指定TCP端口号的连接来进行直接聊天。
结果,依据状态检测规则,Netfilter允许攻击者连接到FTP服务器的端口。
总之,通过这种骗局,攻击者可以非法的连接到FTP服务器的任意TCP端口。
-[ 4 - 攻击场景II - 非标准命令行 ]
---[ 4.1 - 第二次欺骗细节 ]
Linux 2.4.20(之后的版本)内核中的Netfilter已经得到了修正。由主连接认可的第二个连接(比如一个FTP数据连接)不再会误认任何其他协议了。这样FTP数据连接的数据内容就不再会被IRC连接跟踪模块解析了。
尽管如此,我还是尝试了一种使用非标准命令行来躲避Netfilter的连接跟踪的方法,建立了到FTP服务器任何TCP端口的连接。如前面所述,我肯定它能在Linux2.4.28内核上工作。
在前一章所述的条件下,攻击者能够轻松的建立一个程序登录到FTP服务器,然后传送一个非标准命令行。
例如,攻击者可以传送一个行尾没有<CR>字符的PORT命令。命令行只以<LF>结尾。
例如:"PORT 192,168,100,100,26,11\n"
相比之下,一个标准的FTP命令以<CRLF>序列来表明一行的结束。
如果ip_conntrack_ftp模块收到一个这种类型的非标准命令行,它首先检测命令并查找<CR>字符以便解析。因为没有找到,ip_conntrack_ftp认为这是一个“不完整的”命令并丢弃数据包。
在这之前,ip_conntrack_ftp预先算出下一个包含FTP命令行的数据包的序列号,并更新相应信息。这个号码是依据“不完整的”PORT命令数据包的TCP序列号和数据长度计算出来的。
尽管如此,TCP客户端通常会重传同样的PORT命令数据包,因为所期望的应答没有返回来。在本例中,ip_conntrack_ftp不会认为这个重传的数据包是一个FTP命令,因为它的序列号跟所期待的下一个FTP命令的不一样。从ip_conntrack_ftp的观点来看,数据包有一个“错误的”序列号。
ip_conntrack_ftp模块仅是认可这个数据包而不分析它。FTP服务器最终会接收这个来自攻击者的重传数据包。
尽管ip_conntrack_ftp认为这个“不完整的”命令是无效的,但有些FTP服务器比如wu-FTP和IIS FTP会认为这个没有<CR>的PORT命令是有效的。总之,在这种情况下,防火墙不可能“期待”FTP数据连接。
当攻击者发送一个RETR命令从服务器下载一个文件时,服务建立一个到攻击者主机的“不完整的”PORT命令中指定的TCP端口号的连接。
假设TCP端口号是6667(IRC服务端口),在非状态数据包过滤规则下而不是在状态过滤规则下,防火墙认可这个连接,因为非状态数据包过滤规则允许IRC连接。因此IP连接跟踪模块会误认为这是一个IRC连接。
下一步攻击就跟前一章提到的一样了。
总之,攻击者能够非法的连接受Netfilter防火墙保护的FTP服务器上的任意TCP端口。
[补充]
还有一个改进的办法来规避Netfilter的连接跟踪。它使用默认数据端口。这个数据端口不是由PORT命令指定,FTP服务器主动打开从服务器的20端口到客户端控制连接使用的同一个端口号的连接。
为此,客户端需要事先在本地端口上侦听。另外,他/她必须把本地端口绑定在6667(IRCD)上,并设置socker选项“SO_REUSEADDR”来重用端口。
因为一个PORT命令不会穿过Netfilter,防火墙不能预计数据连接。我确定它能在Linux2.4.20内核上工作。
一个实例工具和攻击的例子会在附录I和附录II中分别讲述。
-[ 5 - 攻击场景III ]
---[ 5.1 - 被动FTP:背景信息 ]
FTP服务器也能够被动的打开数据连接,称作被动FTP。相反主动打开数据连接称作主动FTP。
在被动模式中,文件传输之前,客户端发送一个PASV命令,服务器回应一个包含数据端口号的消息给客户端。如下所示。
-> PASV\r\n
<- 227 Entering Passive Mode (192,168,20,20,42,125)\r\n
类似一个PORT命令,IP地址和端口号被逗号分隔开。同时,当你输入一个用户名时,下面的命令和回应会被交互。
-> USER <a user name>\r\n
<- 331 Password required for <the user name>.\r\n
---[ 5.2 - 第三次欺骗细节 ]
在用户建立了一个到FTP服务器的连接后,服务器会要求一个用户名。当客户端在FTP提示符中输入一个登入名字时,会发送一个USER命令,并且跟用户名同样的字符序列会作为回应的一部分返回来,类似于echo。例如,一个用户在FTP提示符中输入字符串“Alice Lee”作为登入名,下列命令行会通过控制连接发送。
-> USER Alice Lee\r\n
FTP服务器回应如下。
<- 331 Password required for Alice Lee.\r\n
(Alice Lee被回显了。)
空格也被包含在用户名里。
一个恶意用户能够把一个任意模式字串插入到名字中。例如,当与被动FTP的回应一样的模式字串被插入时,回应的一部分就像与被动FTP相关的回应一样被返回。
-> USER 227 Entering Passive Mode (192,168,20,29,42,125)\r\n
<- 331 Password required for 227 Entering Passive Mode
(192,168,20,29,42,125).\r\n
防火墙会误把它当作一个“真正的”被动FTP回应吗?大多数防火墙不会被欺骗,因为模式字串在回应行的中间。
虽然如此,假设连接建立时,连接的TCP窗口大小域被攻击者适当的调整,那么这部分内容就会被分成两部分,好像两个分开的回应一样。
(A) ----->USER xxxxxxxxx227 Entering Passive Mode
(192,168,20,29,42,125)\r\n
(B) <-----331 Password required for xxxxxxxxx
(C) ----->ACK(with no data)
(D) <-----227 Entering Passive Mode (192,168,20,20,42,125).\r\n
(这里“xxxxxxxxx”是插入的垃圾字符串,用来调整数据长度)
我在Netfilter/IPTables上试验过,确信Netfilter不会误认为行(D)是一个被动FTP回应。
原因如下。
(B)不是一个以<LF>结尾的完全的命令行,因此,Netfilter不会把(D)看作是(B)的下一个回应,从而不会试图解析它。
但是,如果有一个不关心连接跟踪的防火墙,攻击者就会成功了。
在这种情况下,粗心的防火墙会期待客户端主动打开一个到FTP服务器上的伪造的回应中指定的TCP端口的连接。当攻击者初始化一个到服务器目标端口的连接时,防火墙最终会认可这个非法的连接。