網際網路是為了送達而生,不是為了保護
你在這整座階梯上,一路讚嘆網際網路有多會送達。一個封包就是一張寫了地址的明信片;路由器一跳一跳地把它轉送出去;TCP 把一條會掉東西的路徑,變成一條乾淨、依序的位元組串流。但請注意,那每一個機制都悄悄地假設了一件事:參與的每個人都誠實。一張明信片,沿途經手的每位郵差都讀得到;任何人都能在上面寫任何一個寄件地址;也沒有什麼能阻止陌生人把一張偽造的明信片塞進信箱。網際網路誕生於一小群彼此信任的研究者之間,而「保護訊息不被敵對的一方所害」,根本不在當初那份工作清單上。
這就是這一級令人不安的起點:你研究過的那些層,沒有一層能單憑自己保護你。TCP 可靠卻不安全——它保證你的位元組依序抵達,卻完全不加密任何東西。IP 命名的是一個位置、不是一個人,並且讓任何人都能宣稱自己在任何一個位址上。網域名稱系統,這本網際網路的電話簿,回答問題時既不證明是誰在回答、也不把問題藏起來。網路安全 這門學問,做的正是把保護重新加回一個從未為它而生的系統之上——替一棟「門板當初只為了打開而設計」的房子,補裝上鎖。
我們究竟在保護什麼?CIA 三本柱
在列舉攻擊之前,先替「我們想要什麼」命名會很有幫助。資安界把它總結成 CIA 三本柱——三個目標,而且儘管名字如此,它跟任何情報機構都毫無關係。機密性(Confidentiality)指的是只有預期的當事人能讀到訊息,竊聽者一無所獲。完整性(Integrity)指的是訊息原封不動地抵達;只要連一個位元被改動,接收方都察覺得到。可用性(Availability)指的是服務對合法使用者持續可用,沒有人能把你擠出你自己的房子。
其中有兩個一開始很容易混淆,所以用一張明信片把它們釘牢。機密性,問的是一位好奇的郵差能不能讀懂你的訊息——靠「用一套只有收件人能解開的密碼來寫」來解決。完整性,問的是有沒有人在途中把你的字塗改了——靠的不是把訊息藏起來,而是貼上一道「只要有人碰過就會破掉」的防竄改封印。你可以只有其一而沒有另一:一則訊息可以完美保密、卻被悄悄竄改,也可以完美可驗證、卻人人都讀得到。不同的目標需要不同的工具;而第四個想法——鑑別(authentication),證明你究竟在和誰說話——緊挨在三本柱旁邊,到頭來竟是其中最難的一個。
竊聽:有人正在讀你的明信片
最單純的攻擊,同時也是最安靜的。竊聽 指的是攻擊者讀取了不是給他們的流量、而且什麼也不更改——一種被動攻擊。回想一下:在共享媒介上,一個訊框會抵達該網段上的每一台裝置;而你的資料在橫越世界的途中,會穿過許多你並不掌控的路由器與鏈路。任何坐在那條路徑上的人——你隔壁那家用開放 Wi-Fi 的咖啡店、一台被入侵的路由器、你的網際網路服務商、骨幹纜線上的一個政府監聽點——都能把流過眼前的每一個位元組複製下來,就像郵差讀著他經手分類的每一張明信片。
因為竊聽什麼都不碰,你幾乎永遠偵測不到它;攻擊者不留痕跡。正因如此,我們無法指望「當場逮個正著」。唯一真正的防禦,是讓那些被複製走的位元組變得毫無用處——也就是加密,讓竊聽者擷取到的東西,在沒有金鑰時只是一團亂碼。這一級的誠實說法是:開放網際網路上的機密性,並不是靠「讓資料遠離不可信的路徑」來達成(你通常做不到),而是靠「假定路徑本來就充滿敵意、無論如何都端到端加密」來達成。
偽冒與重放:關於「是誰」和「何時」的謊言
如果說竊聽是「讀」,那麼 偽冒 就是「說謊」。偽冒,就是偽造一則訊息的來源,讓它看起來像是某個其實並非如此的人寄來的。記得嗎,IP 裡沒有任何東西會去驗證那個寄件地址——寄件方只是在封包標頭裡寫進一個來源 IP,而路由器壓根不檢查就樂呵呵地轉送出去。於是攻擊者可以送出蓋著「來自你的銀行」戳記的封包,或冒充成你區域網路上一台受信任的機器。偽冒,是「冒名頂替」這件事的原料:它攻擊的是鑑別,也就是「你究竟在和誰說話」這個問題。
一個鮮明的本地例子是 ARP 偽冒。回想一下 ARP:當你的筆電想連到閘道時,它會廣播「誰擁有這個 IP 位址?」,然後信任任何用一個 MAC 位址回答的人。整個過程沒有任何檢查。同一張網路上的攻擊者,只要搶先且不實地回答——「那個 IP 在我的 MAC 位址上」——你的筆電就會把本該送給閘道的流量送給攻擊者。一則偽造的回覆,就悄悄地把你的對話改道,穿過一台你從未選擇要信任的機器。這是發生在第二層的偽冒,而它正是通往「所有攻擊中最危險那一個」的常見入口匝道。
還有一個更微妙的近親,現在值得替它命名:重放攻擊。在這裡,攻擊者根本不偽造新訊息——他們擷取一則真實、合法的訊息,然後在稍後再送一次。想像你偷聽到一道貨真價實的指令「把門解鎖」,然後只是把那段一模一樣的錄音在明天重新播放一次。訊息是真的,這正是重放陰險之處:光靠機密性與一道防偽封印並擋不住它,因為訊息裡沒有任何東西說明它本該在「何時」被使用。要防禦重放,需要新鮮度——一個一次性數字,或一個時間戳——而這也正是為什麼下一篇的密碼學如此在意「何時」,而不只是「是誰」和「是什麼」。
中間人:藏在你們兩人之間的攻擊
把「讀」與「說謊」合起來,你就得到了這一整級裡最危險的威脅:中間人(MITM)攻擊。在這裡,攻擊者不偏不倚地坐在兩方之間的路徑上——靠 ARP 偽冒、一個流氓 Wi-Fi 存取點,或一個被下毒的 DNS 回覆來抵達那個位置——並在兩方之間轉送訊息,同時讀取、甚至可能更改一切經過的東西。Alice 以為她在和 Bob 說話;Bob 以為他在和 Alice 說話;事實上兩人都在和攻擊者說話,而攻擊者一邊安靜地把他們的話轉送出去,一邊留下一份完美的副本,並隨心所欲地編輯。
WHAT ALICE BELIEVES: Alice <--------------------> Bob
WHAT IS REALLY HAPPENING: Alice <-----> ATTACKER <-----> Bob
(reads + edits
every message,
relays the rest)這裡有一課既深刻又略微令人不安。光靠加密,擋不住中間人。如果攻擊者從第一則訊息起就夾在你們之間,那麼當你試圖建立一條加密通道時,你其實是和攻擊者建立了它——而攻擊者又和真正的遠端建立了第二條加密通道,在中間把一切明文讀光,再重新加密往前送。兩段都完美地加密了;竊聽者卻照讀不誤。缺的那一塊,是鑑別:你需要一種方法,去確定你用來加密的那把金鑰,真的屬於你想要的那個人,而不是屬於「碰巧夾在中間的那位」。
就那單單一道縫隙——我怎麼相信一把金鑰真的屬於我以為的那個人?——是串起這一整級的那條線。正是它,讓我們需要數位簽章、數位憑證,以及憑證授權中心;也正是它,讓 TLS 在任何真正的資料流動之前,於交握期間做了那麼多細緻的工作。把中間人記成這一級的「魔王關」威脅吧:後面每一道防禦,某種程度上,都是在回答那句「但要是有人夾在中間呢?」。
當目標只是要搞砸一切
並非每個攻擊者都想讀取你或冒充你。有些人只想把你打下線,攻擊的是三本柱的第三條腿:可用性。一場 阻斷服務 攻擊,會用大量假流量或大量假請求把目標淹沒,讓合法使用者進不去——就像一群惡作劇的人堵死了一家店唯一的門口,真正的顧客永遠擠不進去。攻擊者並不是想闖進去;他們是想把其他所有人都擋在外面。
這些攻擊倚仗的,是和其他攻擊一樣那份「信任一切」的設計。SYN 洪泛濫用的,正是你研究過的那道三向交握:攻擊者送出一場「只開頭、永不完成」的 SYN 封包風暴,讓伺服器抱著成千上萬條半開連線,直到再也騰不出空間給真正的連線。DNS 放大攻擊則在送給公開伺服器的小小查詢上偽冒受害者的位址,於是那些伺服器用大得多的回答全部砸向受害者——一則小小的偽造請求,觸發一個巨大的回覆,再乘以成千上萬台伺服器。真正棘手的,是分散式的那種,分散式阻斷服務:洪流同時來自一支由大量被入侵裝置組成的龐大軍隊,所以根本沒有單一來源可以一封了之。
退一步,你現在就能看見整個領域的形狀了。機密性受竊聽威脅;完整性與鑑別受偽冒、重放與中間人威脅;可用性受阻斷服務威脅。接下來的四篇,會一一接過這些威脅、建起對應的答案:用密碼學換取機密性與完整性,用憑證與 TLS 鑑別以對抗中間人,用防火牆與 VPN 去控制並保護「跨越邊界的東西」,再用 DDoS 防禦守住可用性。你現在握有這片戰場的地圖了——而這一級剩下的內容,就是我們如何反擊。