繞過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防火牆管理程序,旨在替代現存的 _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消息。
ICMPv6消息有兩大類:差錯消息及信息消息。
和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拒絕關閉埠上的數據包的行為:
為:
帶外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將拒絕任何其他數據包。
通過提取內層對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 src=@M dst=@H type=ICMP ]
[ ICMP type=@Type code=@Code ]
[ IP src=@B dst=@A ]
[ UDP sport=@Pb 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在實現時都受此攻擊的影響。
狀態ICMP過濾被攻擊的過程
接下來,我將介紹Linux和OpenBSD的實現細節,以剖析這種惡意數據包為何會通過以及這種行為如何被預防。
※ISPsystem漏洞分析
※請「同我們一起慢慢變老的網易郵箱」守護好我們的回憶!
TAG:嘶吼RoarTalk |