[Security] DDoS: Distributed Denial of Service Attack

這次要聊的是一個很重要的議題:資訊安全。由於資訊安全真的是個博大精深的領域,所以這應該會是一個系列文。這篇文章會先介紹資訊安全的基本概念,再來看一個網頁攻擊的經典例子:DDoS 分散式阻斷服務攻擊。

The CIA Triad: 資訊安全的三個向度

資訊安全(Infosec: Information Security) 在現今的世界中有越來越重要的地位。這個領域討論的是如何讓資訊在保存與傳遞的過程中,不會發生不預期的修改、竄改、毀損、或未經授權的檢視。一個常見的模型將資訊安全分成三大面向:機密性 Confidentiality, 完整性 Integrity, 可用性 Availability,下面分別介紹。

機密性 Confidentiality

authorization

這個向度在乎的是「身份是否正確」。只有經過授權的身份、實體或是程序才能夠存取資料。資料有價值:個人資料、信用卡號碼、政府機密文件......,機密性的一個特點是它的破壞是不可逆的:假設今天銀行帳戶資訊被竊取,或是一份電子郵件被偷轉發,資料一旦被公開就再也無法還原成「機密」的狀態了,就算抓到犯人也於事無補。

假設今天有一個人向餐廳點了一份蛋炒飯,他要求不要加紅蘿蔔,並且這件事情需要保密。但是傳送訂單的服務生看到了,並且將這件事跟其他人說,於是乎所有人都知道了這個顧客點了一份不加紅蘿蔔的蛋炒飯,這個資訊的機密性就被破壞了。

加密(encryption)是最常見用來保護資料機密性的做法。加密確保只有擁有「鑰匙」的人才能夠存取資料。幾乎所有主要的協議都有使用加密,比如說 HTTPS protocol 就是使用網路傳輸安全協定 SSL 與 TLS。

完整性 Integrity

authenticity

這個向度在乎的是「資料是否能夠信任」,是資料的正確與完整性。也就是說,必須確保資料沒有在未經授權、監督的情況下被修改。假如今天有一份「不加紅蘿蔔的蛋炒飯」的訂單送到餐廳,但是送訂單的服務生偷偷把「不加紅蘿蔔」劃掉,於是廚師就依照這被竄改後的訂單做了一份(有紅蘿蔔的)蛋炒飯,送出來的炒飯,就不是顧客原本預期的樣子了,這就是這份交易的「完整性」被破壞的情況。

如果今天不只是蛋炒飯被誤加紅蘿蔔,而是銀行資料、購物明細被竄改,那事情就變得有點嚴重了。

密碼學(cryptography)就是專門在研究如何確保資訊安全的學問。前面提到的加密也是密碼學的一部份。很常見的做法是將加密前的資料–明文(plaintext)–經由某種演算法加密後變成秘文(ciphertext);傳遞給對方之後,對方再使用鑰匙將秘文還原成明文。如此一來沒有鑰匙的人就無法存取,或是對資料進行修改。

可用性 Availability

accessibility

可用性在乎的是「資料是否可以穩定存取」。一個擁有高可用性(high availability)的系統能夠應付各種可能造成服務中斷的原因,像是包含電力短缺、硬體故障、系統更新等等,而持續提供資源/服務。今天要介紹的主題:DDoS(Distriubted Denial of Service) 就是一個很知名的可用性攻擊手法。

同樣的餐廳點菜例子,假設今天這家有賣蛋炒飯的餐廳常常因為冰箱壞了、員工出走或是老闆忘記開門而不營業,那麼這家餐廳的可用性就很低。另一種情況是,如果今天這家餐廳正常營業,但是突然接到大量惡作劇訂單(假客人)讓這家餐廳變得異常忙碌,在忙著消化大量(假)訂單的同時就無法顧及「不加紅蘿蔔的蛋炒飯」這個真顧客的要求,那麼這位顧客(與其他也想要點餐的真客人)就只能失望的離開了。

在網路世界中,可能會是一個網站突然無法連上線,或是一個停止運作的應用程式。這可以造成很嚴重的後果。一個好的習慣是「備份」固定做好備份就可以減少因為硬碟損壞、天然災害等等而造成的損傷。下面也會講一些抵擋攻擊的方法。

IP Spoofing

開始談 DDoS 之前,我們必須先暸解什麼是 IP spoofing(IP 位址欺騙)。IP Spoofing 是指創造 IP packets(網路上的資料傳遞包裹)但是將這些 packets 的來源地址—source IP—填入其他人的資料。這樣做可以讓攻擊者達成兩個目的:

  1. 隱藏自己的身份,讓來源無從被追查。
  2. 讓回應的包裹導流到其他地方(被假造的 source IP)。

這兩個特徵本身看起來還算無害,但是有心的攻擊者可以利用 IP spoofing 來做 DDoS 攻擊,與更進階的 Amplification Attack。回到蛋炒飯餐廳的例子。今天有一個小明決定他突然想要讓小美吃蛋炒飯,所以他打了電話(送出請求)給餐廳,點了一份蛋炒飯,而當店員問「要送到哪裡」時,小明說了小美的地址。於是,當蛋炒飯準備好,它就會被送到小美的家(spoofed source IP),而不是小明的家,雖然小明才是發出請求的人。可以想像如果今天小明不只訂了一份蛋炒飯,而是一百份、一千萬份,那麼小美的家就會被蛋炒飯淹沒,而不能正常處理其他事情了。

DDoS: Distributed Denial of Service

上面描述的情況就是阻斷服務攻擊 DoS(Denial of Service)。它的目標只有一個:利用大量的請求癱瘓目標系統,讓目標系統無法正常提供服務或資源。 分散式阻斷服務攻擊 DDoS (Distributed Denial of Service)是 DoS 的進階版。

DoS vs DDoS

阻斷服務攻擊 DoS 攻擊手法是一對一單挑,哪邊性能比較好哪邊就贏。假設今天攻擊者電腦一秒最多可以發動 100 次攻擊,但是目標電腦一秒可以輕輕鬆鬆處理 10,000 個封包,那麼攻擊就無效了。

分散式阻斷服務攻擊 DDoS 不一樣。「分散式」的意思就是「水平擴展」—一台電腦打不贏就用兩台打,兩台電腦打不贏就用 1000 台打,直到數量多到目標電腦招架不住為止。這些被抓進來一起打的電腦不一定是自願的,通常是因為自己系統中有漏洞所以被攻擊者控制的「殭屍」。如此一來,原本一台電腦一秒有 100 個攻擊,1000 台電腦一秒就有 100,000 個攻擊,就算目標電腦還是維持一秒處理 10,000 個封包,還是輸了,因為它只有一個人。

另一個 DDoS 比 DoS 更令人害怕的是他發動攻擊的源頭不只有一個了,所以要對付不能像 DoS 一樣直接抓出作亂的源頭並且封鎖,而要使用更進階的方式(比如說 Ingres Filtering)才能夠防堵。

暸解了 DoS 與 DDoS 的基本概念,我們現在來看看實際上他們都怎麼被實現的。下面介紹兩種 DDoS 攻擊:SYN Flooding 與 Amplification Attack。

SYN Flooding: 利用 TCP 協議的 DDoS 攻擊

SYN 洪水攻擊(SYN Flooding)。在伺服器與客戶端建立連線時,若在 network 層的連線方式是使用 TCP(目前主流的連線方式),則會經過一個三次握手(Three-Way Handshake)的步驟。這三次握手的主要目的是讓雙方在交換資料之前確認彼此是自己想要交換資料的對象,使用 ACK (acknowledgment field significant) 與 SYN (synchronize sequence numbers) 兩個控制位元(Control Bits)來確認。

SYN Flooding 會故意不回傳確認連線的訊息給伺服器,讓第三次握手失敗,這時伺服器的行為會是不停地重試並且等到一定的時間(SYN timeout)之後才會放棄。可以想見若是這種情形大量出現,對於伺服器會是非常大的負擔。SYN Flooding 難防的是它利用的是 TCP/IP 協議中的漏洞,所以使用 TCP/IP 連線的伺服器都有可能遭受這種威脅。

DDoS Amplification Attack

DDoS Amplification Attack 是一種讓 DDoS Attack 更上一層樓的攻擊方式。它利用請求封包與回應封包之間的大小差異來進行攻擊。簡單的說,它找到一種方式讓伺服器產生的回應封包比請求的大小還要大,於是可以發出很小的請求就觸發很大的回應,將許多小請求疊加(記得我們的殭屍嗎),並利用 IP spoofing 將回應的封包全部導流到目標伺服器,就可以事半功倍地癱瘓目標伺服器。

一個常見的攻擊是 DNS Amplification Attack。這是利用 open DNS resolver 的功能來達到攻擊的目的。每一個機器人都用一個 IP-spoofed 的位址向 open DNS resolvers 發出請求,而這些 open DNS resolvers 就會將處理過後的,「被放大」後的回應封包丟給受害者伺服器。

大致上一個 DNS Amplification Attack 的流程有四步:

  1. 攻擊者找到一個沒有被保護的節點,並且利用 IP-spoofed 的來源位址送 UDP packets 給一個 DNS recursor。這個被竄改的位址指向受害者的 IP。
  2. 每一個 UDP packet 都會對一個 DNS resolver 發出請求,這個請求唯一的目的就是能夠讓 response packet 越大越好。實作上常常會看到像是使用 ANY 的參數。
  3. DNS resolver 盡責地處理好請求,將回應封包丟給不知情的受害者。
  4. 受害者的位址被大量的回應封包給淹沒,造成服務中斷,甚至可能影響到網路基礎。

Reflector 的角色

Reflector 是無知的幫兇。它們是在網路上提供某種服務/資源的伺服器,比如說 DNS 服務。這些伺服器存在某種漏洞,或是說,攻擊者知道如何操縱這些伺服器,讓它們變成攻擊者拿去對付其他人的傀儡。在 DNS Amplification Attack 中,DNS server 就是 reflector。

UDP protocol: Amplification Attack 的功臣

幾個常見的 Amplification Attack 包含利用 DNS (Domain Name Service), NTP (Network Time Protocol), SNMPv2 (Simple Network Management Protocol v2) 這些協議的漏洞來進行攻擊。它們的共通點有兩個:

  1. 它們都是在 OSI model 中 application 層級的網路協議
  2. 它們在 network 層級都是使用 UDP protocol 來傳遞資料

如果是使用 TCP,那麼就不會有「放大」的效果產生,因為攻擊發生在互相回傳確認碼的階段,所以請求與回應都只有大概 60 Bytes。UDP 則不一樣。使用 UDP 的雙方在開始傳送資料前不需要先經過握手,因此一個請求只要經過好好設計,就可以讓回應的大小比請求大許多,比如說從 1Gbps 增加到 100s Gbps,所謂事半功倍。現實中,一個 15 bytes 的請求可以導致 750kB 的回應,大約是 51,200 倍的放大,非常有效。

一般而言,當一個伺服器的一個阜(port) 接受一個 UDP 封包,會經過兩步驟:

  1. 伺服器首先確定該阜是否有應用程式在待命(listening for requests)。
  2. 如果該阜沒有應用程式在待命,那麼伺服器會回傳一個 ICMP (Internet Control Message Protocol)(ping) 封包,告訴對方它指定的目的地不存在。

故意傳資料給一個伺服器不存在的阜,讓伺服器將 ICMP packet 傳到目標伺服器,這就是一種用 UDP protocol 做的 DDoS Attack.

DDoS Amplification Attack 實際案例:GitHub

截至目前(2019 年 8 月)為止發生過最嚴重的 DDoS attack 是在 2018 年 2 月 28 號, Github 網站斷線了五分鐘。這是一個利用 Memcached(一個開源的資料庫分散式快取系統)伺服器做的 DDoS Amplification attack。事件發生的當週 Cloudflare 正發佈了一個安全漏洞:Memcached 伺服器的預設設定有支援 UDP protocol,而有將 UDP 打開的伺服器很容易成為 reflector 標的。本次事件就是攻擊者找到了這個漏洞,被利用拿來進行 Amplification Attacks 放大攻擊。巔峰時刻,網路流量達到 1.35 Tbps (terabytes per second),封包數量也達到每秒 126.9 million。

Cloudflare 表示 memcached protocol 對於攻擊者而言非常方便,因為它沒有檢查機制,資料可以非常快速的傳送,並且小型的請求就可以造成巨大的回應(到達 1 MB)。在 Github 事件中,這個放大效果甚至達到超過 50,000 倍。

攻擊的程序很簡單:首先攻擊者鎖定一個沒有防護的 Memcached server,開始向 port UDP 11211 傳送大量資料,然後攻擊者偽造(spoof)GET 請求的 source IP,將回應導流到 Github IP。

Github 首先從網路監控系統中偵測到資料流入(ingres traffic)與流出量(egress traffic)的比例異常,資料流入量超過了 100 Gbps。當下的決定是將流量導到能夠提供更多網路節點的 Akamai,將大概 40 Gbps 的資料從網絡中移走,同時也啟動保護機制,所以這起 DDoS 攻擊持續 20 分鐘後就落幕了。

Ingress Filtering: 試圖對付 DDoS 的嘗試

修改 source IP 是 TCP/IP 與生俱來的設計,因此很難有根絕疑慮的方法,只能盡量將風險降到最低。其中一個常見的方法是 Ingress Filtering。Ingress Filtering 是在 RFC2728 中建議的 best practice,許多 ISP (Internet Service Provider) 現在都有實做。

基本原理是這樣:Ingress Filtering 一種放在網路節點(network edge)上的封包過濾(packet filtering)機制,它會檢視每個進來的封包,像是查看是否 source IP 跟 origin 一樣。如果是一個內部網路來的 packet, 卻有一個外部網路的 source IP,那麼很有可能這個 packet 有被 IP-spoofed 了。當它發現了可疑的封包,就會將之拒絕/過濾掉。

與 Ingres Filtering 相反的是 Egress Filtering,顧名思義這種方法會檢查所有從該網路發出去的封包,確認他們都有合法的 source header。

其他抵擋/預防 DDoS 的方法

不要太相信預設設定

很多起 DDoS 攻擊之所以能夠得逞就是因為發現了伺服器預設設定的漏洞。像是在 9.4.1 版的 BIND DNS server 預設設定是允許 recursion 的,這讓 amplification attack 變得非常容易。Memcached server 也是一個很好的例子。

使用 Anycast

大部分的網路傳送是使用 Unicast,也就是說,每一個網路中的節點(node)都會有自己的一個獨一無二的 IP address。當一個 packet 要從一個地方傳送到另一個地方,會經過很多個路由器(routers)。路由器們會保存一張 IP address 的地圖,當它收到一個要送廣其他地方的 packet,就會試圖將這個 packet 送到下一個離目的地更近的路由器(hop)。我們可以在終端機使用 traceroute 指令來看。

Anycast,顧名思義(?),就是一種可以讓多台機器使用同一個 IP address 的方式。它與 Unicast 同樣是一對一(one-to-one)的關係,只是 Anycast 中的接收端是一個網絡中的任何一個點,所以更精確地說是「一對多個中的一」(one to one of many)的關係。今天一個請求進來的時候,Anycast 會依照其地理位置,將它傳遞給離他最近的可用節點。這樣做的好處除了速度之外,也代表當今天如果不幸的這個節點被攻擊了,那麼後續的請求還是不會被切斷,因為資料依然可以傳給下一個最近的節點。這裡有一份對於 Anycast 如何可以減緩 DDoS 攻擊的研究

就這樣

下次應該會講 MITM: Man in the Middle Attack. 下篇文章見!

Resources


  • Find me at