HeartBleed Python测试脚本
我看到了一段 Python脚本,这个脚本是用来测试服务器是否存在HeartBleed漏洞的。
有没有人能解释一下里面的“hello”是什么内容,它发送了什么,以及这个内容是怎么构造出来的?
我并不是想恶意使用这个脚本。我是被要求测试一个Tomcat 7.0.2服务器是否有这个漏洞的:我确认了tcnative-1.dll确实使用了openssl 1.0.1d,但我尝试的一些独立测试工具却报告说这个服务器没有漏洞。
2 个回答
6
这个页面讲了很多关于这个的内容。
const unsigned char good_data_2[] = {
// TLS record
0x16, // Content Type: Handshake
0x03, 0x01, // Version: TLS 1.0
0x00, 0x6c, // Length (use for bounds checking)
// Handshake
0x01, // Handshake Type: Client Hello
0x00, 0x00, 0x68, // Length (use for bounds checking)
0x03, 0x03, // Version: TLS 1.2
// Random (32 bytes fixed length)
0xb6, 0xb2, 0x6a, 0xfb, 0x55, 0x5e, 0x03, 0xd5,
0x65, 0xa3, 0x6a, 0xf0, 0x5e, 0xa5, 0x43, 0x02,
0x93, 0xb9, 0x59, 0xa7, 0x54, 0xc3, 0xdd, 0x78,
0x57, 0x58, 0x34, 0xc5, 0x82, 0xfd, 0x53, 0xd1,
0x00, // Session ID Length (skip past this much)
0x00, 0x04, // Cipher Suites Length (skip past this much)
0x00, 0x01, // NULL-MD5
0x00, 0xff, // RENEGOTIATION INFO SCSV
0x01, // Compression Methods Length (skip past this much)
0x00, // NULL
0x00, 0x3b, // Extensions Length (use for bounds checking)
// Extension
0x00, 0x00, // Extension Type: Server Name (check extension type)
0x00, 0x0e, // Length (use for bounds checking)
0x00, 0x0c, // Server Name Indication Length
0x00, // Server Name Type: host_name (check server name type)
0x00, 0x09, // Length (length of your data)
// "localhost" (data your after)
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
// Extension
0x00, 0x0d, // Extension Type: Signature Algorithms (check extension type)
0x00, 0x20, // Length (skip past since this is the wrong extension)
// Data
0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03,
0x05, 0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01,
0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02,
0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
// Extension
0x00, 0x0f, // Extension Type: Heart Beat (check extension type)
0x00, 0x01, // Length (skip past since this is the wrong extension)
0x01 // Mode: Peer allows to send requests
};
12
hello
和hb
是用更易读的方式来定义字节串。
h2bin(x)
这个函数负责所有的工作:
def h2bin(x):
return x.replace(' ', '').replace('\n', '').decode('hex')
它会把十六进制数字串中的所有空白去掉,然后把它从十六进制解码成字节:
>>> '16 03 02 00 dc'.replace(' ', '')
'16030200dc'
>>> '16 03 02 00 '.replace(' ', '').decode('hex')
'\x16\x03\x02\x00\xdc'
这其实是一种用十六进制表示一系列字节的简洁方式,里面可以有额外的空白。
这些十六进制数据本身就是一个普通的心跳协议消息,以原始字节的形式存在。hello
这个字符串包含了一个TLS 1.1记录消息,它的第一个字节是16
(十六进制,十进制是22),表示这是一个握手记录,发送的是client_hello
(第六个字节是01
)。这只是为了建立一个TLS会话,告诉服务器客户端支持什么样的加密方式。里面的内容其实没什么特别的,主要是告诉服务器客户端支持心跳扩展(消息末尾有一对00 0f
字节)。
真正有趣的是hb
消息:
hb = h2bin('''
18 03 02 00 03
01 40 00
''')
18
是心跳内容类型记录,03 02
表示TLS 1.1协议版本。00 03
表示消息的有效载荷大小;3个字节,也就是第二行的全部内容。
消息本身的3个字节由心跳类型(01
,表示'请求')和消息长度(40 00
,即16384字节)组成,后面没有实际消息。这会导致一个有问题的SSL服务器返回一个心跳响应,里面包含16KB的内存;这个不存在的0长度请求消息被回显,加上内存以达到请求的长度。