Beispiel #1
0
    def decode(self, data):
        self._raw_stream_data += data
        while True:
            try:
                (obj, data) = SSLv3Record.decode(
                    self._raw_stream_data,
                    connection=self,
                    payload_auto_decode=False
                )
                version = helper.get_version_by_version_id((
                    obj.version.major,
                    obj.version.minor
                ))

                self._raw_stream_data = data

                if version != self._cur_protocol_version:
                    raise WrongProtocolVersion(
                        record=obj
                    )

                if self._cur_record_type is None:
                    self._cur_record_type = obj.content_Type

                if self._cur_record_type != obj.content_type:
                    self._decode_record_payload()
                    self._cur_record_data = b""
                    self._cur_record_type = obj.content_type

                self._cur_record_data += obj.payload

                self._decode_record_payload()

            except NotEnoughData:
                break
Beispiel #2
0
 def test_not_enough_data(self):
     # Handshake, SSLv3.0, Length 136
     data = binascii.unhexlify(b"1603000088")
     with pytest.raises(NotEnoughData):
         SSLv3Record().decode(data)
     #
     assert binascii.hexlify(data) == b"1603000088"
Beispiel #3
0
    def test_encode(self):
        record = SSLv3Record()
        alert = Alert()
        alert.level = 1
        alert.description = 2
        record.set_payload(alert)

        data = record.encode()
        assert binascii.hexlify(data) == self.alert_01
Beispiel #4
0
    def test_decode(self):
        (record, data) = SSLv3Record.decode(binascii.unhexlify(self.alert_01))
        assert len(data) == 0

        assert isinstance(record, SSLv3Record)
        assert record.version.major == 3
        assert record.version.minor == 0
        assert record.length == 2

        alert = record.payload
        assert isinstance(alert, Alert)
        assert alert.level == 1
        assert alert.description == 2
Beispiel #5
0
    def _connect_with_scsv(self, protocol_version, cipher_suites):
        cipher_suites = cipher_suites[:]
        cipher_suites.append(0x5600)

        conn = self._scanner.handler.connect()
        conn.settimeout(2.0)

        record_tls_hello = self._build_tls_base_client_hello(
            protocol_version, cipher_suites)

        conn.send(record_tls_hello.encode())

        time_start = datetime.now()
        data = b""
        proto_version = (record_tls_hello.version.major,
                         record_tls_hello.version.minor)
        while True:
            tmp_time = datetime.now() - time_start
            if tmp_time.total_seconds() > 5.0:
                conn.close()
                return None

            try:
                tmp_data = conn.recv(4096)
            except ConnectionError:
                conn.close()
                return None

            data += tmp_data
            while True:
                try:
                    (record, data) = SSLv3Record.decode(data)
                except NotEnoughData:
                    break

                if isinstance(record.payload, Handshake):
                    if isinstance(record.payload.payload, ServerHello):
                        conn.close()
                        if proto_version[0] == record.version.major \
                            and proto_version[1] == record.version.minor:
                            return False
                        return None

                elif isinstance(record.payload, Alert):
                    conn.close()
                    if record.payload.level == 2 and \
                        record.payload.description == 86:
                        return True
                    return None
Beispiel #6
0
    def _decode_record_payload(self):
        while len(self._cur_record_data) > 0:
            try:
                (obj, data) = SSLv3Record.decode_raw_payload(
                    self._cur_record_type,
                    self._cur_record_data,
                    payload_auto_decode=True,
                    connection=self
                )
                self._cur_record_data = data
                self.state.update(obj)
                self._decoded_records.append(obj)

            except NotEnoughData:
                break
    def test_heartbeat_type(self):
        record = SSLv3Record()
        hb = Heartbeat()
        hb.type = 1
        hb.payload = b"Heartbeat"
        hb.padding = b"1234567890123456"

        obj = record + hb
        # Heartbeat, SSL 3.0, Length 28
        data = b"180300001c"
        # Type: Request, Length 9
        data += b"010009"
        # Payload
        data += b"486561727462656174"
        # Padding
        data += b"31323334353637383930313233343536"
        assert binascii.unhexlify(data) == obj.encode()
Beispiel #8
0
    def test_decode(self):
        (record, data) = SSLv3Record.decode(
            binascii.unhexlify(
                self.alert_01
            )
        )
        assert len(data) == 0

        assert isinstance(record, SSLv3Record)
        assert record.version.major == 3
        assert record.version.minor == 0
        assert record.length == 2

        alert = record.payload
        assert isinstance(alert, Alert)
        assert alert.level == 1
        assert alert.description == 2
Beispiel #9
0
    def _connect_with_scsv(self, protocol_version, cipher_suites):
        cipher_suites = cipher_suites[:]
        cipher_suites.append(0x5600)

        conn = self._scanner.handler.connect()
        conn.settimeout(2.0)

        record_tls_hello = self._build_tls_base_client_hello(protocol_version, cipher_suites)

        conn.send(record_tls_hello.encode())

        time_start = datetime.now()
        data = b""
        proto_version = (record_tls_hello.version.major, record_tls_hello.version.minor)
        while True:
            tmp_time = datetime.now() - time_start
            if tmp_time.total_seconds() > 5.0:
                conn.close()
                return None

            try:
                tmp_data = conn.recv(4096)
            except ConnectionError:
                conn.close()
                return None

            data += tmp_data
            while True:
                try:
                    (record, data) = SSLv3Record.decode(data)
                except NotEnoughData:
                    break

                if isinstance(record.payload, Handshake):
                    if isinstance(record.payload.payload, ServerHello):
                        conn.close()
                        if proto_version[0] == record.version.major and proto_version[1] == record.version.minor:
                            return False
                        return None

                elif isinstance(record.payload, Alert):
                    conn.close()
                    if record.payload.level == 2 and record.payload.description == 86:
                        return True
                    return None
Beispiel #10
0
    def encode(self, records):
        if isinstance(records, Protocol):
            records = [records]

        pkgs = []
        for record in records:
            if isinstance(record, Protocol):
                self.state.update(record)
                tls_record = SSLv3Record(
                    connection=self
                )
                ver_major, ver_minor = helper.get_tls_version(self._cur_protocol_version)
                tls_record.version.major = ver_major
                tls_record.version.minor = ver_minor
                tls_record.set_payload(record)
                pkgs.append(tls_record.encode())
            else:
                raise TypeError("Record must be of type flextls.protocol.Protocol()")

        return pkgs
    def _send_heartbeat(self, protocol_version, cipher_suites):

        record_tls = self._build_tls_base_client_hello(
            protocol_version,
            cipher_suites
        )

        ext_hb = HeartbeatExtension()
        ext_hb.mode = 1
        record_client_hello = record_tls.payload
        record_client_hello.extensions.append(Extension() + ext_hb)

        conn = self._scanner.handler.connect()
        conn.settimeout(2.0)

        conn.send(record_tls.encode())

        time_start = datetime.now()
        server_hello_done = False
        heartbeat_supported = False
        data = b""
        while server_hello_done is False:
            tmp_time = datetime.now() - time_start
            if tmp_time.total_seconds() > 5.0:
                return False

            try:
                tmp_data = conn.recv(4096)
            except:
                return None

            data += tmp_data
            while True:
                try:
                    (record, data) = SSLv3Record.decode(data)
                except NotEnoughData:
                    break

                if isinstance(record.payload, Handshake):
                    if isinstance(record.payload.payload, ServerHello):
                        server_hello = record.payload.payload
                        for ext in server_hello.extensions:
                            if isinstance(ext.payload, HeartbeatExtension):
                                heartbeat_supported = True

                    if isinstance(record.payload.payload, ServerHelloDone):
                        server_hello_done = True

                elif isinstance(record.payload, Alert):
                    if record.payload.level == 2:
                        return None

        # ToDo: use connection state
        if protocol_version == flextls.registry.version.SSLv3:
            ver_minor = 0
        elif protocol_version == flextls.registry.version.TLSv10:
            ver_minor = 1
        elif protocol_version == flextls.registry.version.TLSv11:
            ver_minor = 2
        elif protocol_version == flextls.registry.version.TLSv12:
            ver_minor = 3

        record = SSLv3Record()
        record.version.major = 3
        record.version.minor = ver_minor

        record.payload = binascii.unhexlify(b"014000")
        record.length = 3
        record.content_type = 24

        conn.send(record.encode())
        time_start = datetime.now()
        record_with_heartbeat = None
        data = b""
        while record_with_heartbeat is None:
            tmp_time = datetime.now() - time_start
            if tmp_time.total_seconds() > 5.0:
                return heartbeat_supported

            try:
                tmp_data = conn.recv(4096)
            except:
                return heartbeat_supported

            data += tmp_data
            while True:
                try:
                    (record, data) = SSLv3Record.decode(
                        data,
                        payload_auto_decode=False
                    )
                except NotEnoughData:
                    break

                if record.content_type == record.get_payload_pattern(Heartbeat):
                    record_with_heartbeat = record

                elif isinstance(record.payload, Alert):
                    if record.payload.level == 2:
                        return heartbeat_supported

        return record_with_heartbeat
    def _send_heartbeat(self, protocol_version, cipher_suites):

        record_tls = self._build_tls_base_client_hello(protocol_version,
                                                       cipher_suites)

        ext_hb = HeartbeatExtension()
        ext_hb.mode = 1
        record_client_hello = record_tls.payload
        record_client_hello.extensions.append(Extension() + ext_hb)

        conn = self._scanner.handler.connect()
        conn.settimeout(2.0)

        conn.send(record_tls.encode())

        time_start = datetime.now()
        server_hello_done = False
        heartbeat_supported = False
        data = b""
        while server_hello_done is False:
            tmp_time = datetime.now() - time_start
            if tmp_time.total_seconds() > 5.0:
                return False

            try:
                tmp_data = conn.recv(4096)
            except:
                return None

            data += tmp_data
            while True:
                try:
                    (record, data) = SSLv3Record.decode(data)
                except NotEnoughData:
                    break

                if isinstance(record.payload, Handshake):
                    if isinstance(record.payload.payload, ServerHello):
                        server_hello = record.payload.payload
                        for ext in server_hello.extensions:
                            if isinstance(ext.payload, HeartbeatExtension):
                                heartbeat_supported = True

                    if isinstance(record.payload.payload, ServerHelloDone):
                        server_hello_done = True

                elif isinstance(record.payload, Alert):
                    if record.payload.level == 2:
                        return None

        # ToDo: use connection state
        if protocol_version == flextls.registry.version.SSLv3:
            ver_minor = 0
        elif protocol_version == flextls.registry.version.TLSv10:
            ver_minor = 1
        elif protocol_version == flextls.registry.version.TLSv11:
            ver_minor = 2
        elif protocol_version == flextls.registry.version.TLSv12:
            ver_minor = 3

        record = SSLv3Record()
        record.version.major = 3
        record.version.minor = ver_minor

        record.payload = binascii.unhexlify(b"014000")
        record.length = 3
        record.content_type = 24

        conn.send(record.encode())
        time_start = datetime.now()
        record_with_heartbeat = None
        data = b""
        while record_with_heartbeat is None:
            tmp_time = datetime.now() - time_start
            if tmp_time.total_seconds() > 5.0:
                return heartbeat_supported

            try:
                tmp_data = conn.recv(4096)
            except:
                return heartbeat_supported

            data += tmp_data
            while True:
                try:
                    (record,
                     data) = SSLv3Record.decode(data,
                                                payload_auto_decode=False)
                except NotEnoughData:
                    break

                if record.content_type == record.get_payload_pattern(
                        Heartbeat):
                    record_with_heartbeat = record

                elif isinstance(record.payload, Alert):
                    if record.payload.level == 2:
                        return heartbeat_supported

        return record_with_heartbeat
Beispiel #13
0
 def test_empty_data(self):
     with pytest.raises(NotEnoughData):
         SSLv3Record().decode(b"")