Beispiel #1
0
def skip_server_handshake(sock, timeout):
    end_time = time.time() + timeout
    hs_struct = struct.Struct(b'!BBH')
    for i in range(0, 5):
        record, error = read_record(sock, timeout)
        timeout = end_time - time.time()
        if not record:
            raise Failure('Unexpected server handshake! ' + str(error))

        content_type, sslver_num, fragment = record
        if content_type != 22:
            raise Failure('Expected handshake type, got ' + str(content_type))

        sslver = '{0:02x} {1:02x}'.format(sslver_num >> 8, sslver_num & 0xFF)

        off = 0
        # Records may consist of multiple handshake messages
        while off + hs_struct.size <= len(fragment):
            hs_type, len_high, len_low = hs_struct.unpack_from(fragment, off)
            if off + len_low > len(fragment):
                raise Failure('Illegal handshake length!')
            off += hs_struct.size + len_low

            # Server handshake is complete after ServerHelloDone
            if hs_type == 14:
                # Ready to check for vulnerability
                return sslver

    raise Failure('Too many handshake messages')
Beispiel #2
0
def read_hb_response(sock, timeout):
    end_time = time.time() + timeout
    memory = bytearray()
    hb_len = 1  # Will be initialized after first heartbeat
    read_error = None
    alert = None

    while len(memory) < hb_len and timeout > 0:
        record, read_error = read_record(sock, timeout, partial=True)
        if not record:
            break

        record_type, _, fragment = record
        if record_type == 24:
            if not memory:  # First Heartbeat
                # Check for enough room for type + len
                if len(fragment) < 3:
                    if read_error:  # Ignore error due to partial read
                        break
                    raise Failure('Response too small')
                # Sanity check, should not happen with OpenSSL
                if fragment[0:1] != b'\2':
                    raise Failure('Expected Heartbeat in first response')

                hb_len, = struct.unpack_from(b'!H', fragment, 1)
                memory += fragment[3:]
            else:  # Heartbeat continuation
                memory += fragment
        elif record_type == 21 and len(fragment) == 2:  # Alert
            alert = fragment
            break
        else:
            # Cannot tell whether vulnerable or not!
            raise Failure('Unexpected record type {0}'.format(record_type))

        timeout = end_time - time.time()

    # Drop heartbeat padding that is included in buffer
    if len(memory) - 16 == hb_len:
        del memory[hb_len:]

    # Check for Alert (sent by NSS)
    if alert:
        lvl, desc = alert[0:1], ord(alert[1:2])
        lvl = 'Warning' if lvl == 1 else 'Fatal'
        print('Got Alert, level={0}, description={1}'.format(lvl, desc))
        if not memory:
            print('Not vulnerable! (Heartbeats disabled or not OpenSSL)')
            return None

    # Do not print error if we have memory, server could be crashed, etc.
    if read_error and not memory:
        print('Did not receive heartbeat response! ' + str(read_error))

    return memory
Beispiel #3
0
 def readline_expect(reader, expected, what=None):
     line = reader.readline()
     if not line.upper().startswith(expected.upper()):
         if what is None:
             what = expected
         raise Failure('Expected ' + expected + ', got ' + line)
     return line
Beispiel #4
0
    def do_serverhello(self):
        # Read TLS record header
        content_type, ver, rec_len = self.recv_s(b'>BHH', 'TLS record')
        # Session-ID length (1 byte) starts at offset 38
        self.expect(rec_len >= 39, 'Illegal handshake packet')
        if content_type == 0x80:  # SSLv2 (assume length < 256)
            raise Failure('SSL 2.0 clients cannot be tested')
        else:
            self.expect(content_type == 22, 'Expected Handshake type')

        # Read handshake
        hnd = self.request.recv(rec_len)
        self.expect(len(hnd) == rec_len, 'Unable to read handshake')
        hnd_type, len_high, len_low, ver = struct.unpack(b'>BBHH', hnd[:6])
        self.expect(hnd_type == 1, 'Expected Client Hello')
        # hnd[6:6+32] is Random
        off = 6 + 32
        sid_len, = struct.unpack(b'B', hnd[off:off + 1])
        off += 1 + sid_len  # Skip length and SID
        # Enough room for ciphers?
        self.expect(rec_len - off >= 4, 'Illegal handshake packet (2)')
        ciphers_len = struct.unpack(b'<H', hnd[off:off + 2])
        off += 2
        # The first cipher is fine...
        cipher = bytearray(hnd[off:off + 2])

        self.sslver = '{0:02x} {1:02x}'.format(ver >> 8, ver & 0xFF)

        # (1) Handshake: ServerHello
        self.request.sendall(make_hello(self.sslver, cipher))
Beispiel #5
0
    def prepare_ftp(cls, sock):
        reader = Linereader(sock)
        tls = False
        cls.readline_expect(reader, '220 ', 'FTP greeting')

        sock.sendall(b'FEAT\r\n')
        cls.readline_expect(reader, '211-', 'FTP features')
        for i in range(0, 64):
            line = reader.readline().upper()
            if line.startswith(' AUTH TLS'):
                tls = True
            if line.startswith('211'):
                break

        if not tls:
            raise Failure('AUTH TLS not supported')

        sock.sendall(b'AUTH TLS\r\n')
        cls.readline_expect(reader, '234 ', 'AUTH TLS ack')
Beispiel #6
0
    def prepare_smtp(cls, sock):
        reader = Linereader(sock)
        tls = False

        # Server greeting
        cls.readline_expect(reader, '220 ', 'SMTP banner')

        sock.sendall(b'EHLO pacemaker\r\n')
        # Assume no more than 16 extensions
        for i in range(0, 16):
            line = cls.readline_expect(reader, '250', 'extension')
            if line[4:].upper().startswith('STARTTLS'):
                tls = True
            if line[3] == ' ':
                break

        if not tls:
            raise Failure('STARTTLS not supported')

        sock.sendall(b'STARTTLS\r\n')
        cls.readline_expect(reader, '220 ', 'STARTTLS acknowledgement')
Beispiel #7
0
 def expect(self, cond, what):
     if not cond:
         raise Failure(what)