自己翻譯的一篇來自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 <[email protected]> ]=------------------=|
|=---使用偽造的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端口的連接。當攻擊者初始化一個到服務器目標端口的連接時,防火牆最終會認可這個非法的連接。