def build(self, *args, **kargs): """ We overload build() method in order to provide a valid default value for params based on TLS session if not provided. This cannot be done by overriding i2m() because the method is called on a copy of the packet. The 'params' field is built according to key_exchange.server_kx_msg_cls which should have been set after receiving a cipher suite in a previous ServerHello. Usual cases are: - None: for RSA encryption or fixed FF/ECDH. This should never happen, as no ServerKeyExchange should be generated in the first place. - ServerDHParams: for ephemeral FFDH. In that case, the parameter to server_kx_msg_cls does not matter. - ServerECDH*Params: for ephemeral ECDH. There are actually three classes, which are dispatched by _tls_server_ecdh_cls_guess on the first byte retrieved. The default here is b"\03", which corresponds to ServerECDHNamedCurveParams (implicit curves). When the Server*DHParams are built via .fill_missing(), the session server_kx_privkey will be updated accordingly. """ fval = self.getfieldval("params") if fval is None: s = self.tls_session if s.pwcs: if s.pwcs.key_exchange.export: cls = ServerRSAParams(tls_session=s) else: cls = s.pwcs.key_exchange.server_kx_msg_cls(b"\x03") cls = cls(tls_session=s) try: cls.fill_missing() except: pass else: cls = Raw() self.params = cls fval = self.getfieldval("sig") if fval is None: s = self.tls_session if s.pwcs: if not s.pwcs.key_exchange.anonymous: p = self.params if p is None: p = "" m = s.client_random + s.server_random + str(p) cls = _TLSSignature(tls_session=s) cls._update_sig(m, s.server_key) else: cls = Raw() else: cls = Raw() self.sig = cls return _TLSHandshake.build(self, *args, **kargs)
def tls_sign(self, bytes): # sig_alg 0x0401 = sha256+rsa as per our certificate # STUDENT TODO """ 1. Create a TLSSignature object. set sig_alg to 0x0401 2. use this object to sign the bytes """ sig = _TLSSignature(sig_alg=0x0401) sig._update_sig(bytes, self.server_rsa_privkey) return sig
def build(self, *args, **kargs): s = self.tls_session sig = self.getfieldval("responsedata") test = (sig is None and s.sslv2_key_material is not None and s.sslv2_challenge_clientcert is not None and len(s.server_certs) > 0) if test: s = self.tls_session m = (s.sslv2_key_material + s.sslv2_challenge_clientcert + s.server_certs[0].der) self.responsedata = _TLSSignature(tls_session=s) self.responsedata._update_sig(m, s.client_key) else: self.responsedata = b"" return super(SSLv2ClientCertificate, self).build(*args, **kargs)
def build(self, *args, **kargs): s = self.tls_session sig = self.getfieldval("responsedata") test = (sig is None and s.sslv2_key_material is not None and s.sslv2_challenge_clientcert is not None and len(s.server_certs) > 0) if test: s = self.tls_session m = (s.sslv2_key_material + s.sslv2_challenge_clientcert + s.server_certs[0].der) self.responsedata = _TLSSignature(tls_session=s) self.responsedata._update_sig(m, s.client_key) else: self.responsedata = "" return super(SSLv2ClientCertificate, self).build(*args, **kargs)
def build(self, *args, **kargs): sig = self.getfieldval("sig") if sig is None: s = self.tls_session m = "".join(s.handshake_messages) if s.tls_version >= 0x0304: if s.connection_end == "client": context_string = "TLS 1.3, client CertificateVerify" elif s.connection_end == "server": context_string = "TLS 1.3, server CertificateVerify" m = b"\x20"*64 + context_string + b"\x00" + s.wcs.hash.digest(m) self.sig = _TLSSignature(tls_session=s) if s.connection_end == "client": self.sig._update_sig(m, s.client_key) elif s.connection_end == "server": # should be TLS 1.3 only self.sig._update_sig(m, s.server_key) return _TLSHandshake.build(self, *args, **kargs)
def build(self, *args, **kargs): sig = self.getfieldval("sig") if sig is None: s = self.tls_session m = "".join(s.handshake_messages) if s.tls_version >= 0x0304: if s.connection_end == "client": context_string = "TLS 1.3, client CertificateVerify" elif s.connection_end == "server": context_string = "TLS 1.3, server CertificateVerify" m = b"\x20" * 64 + context_string + b"\x00" + s.wcs.hash.digest( m) self.sig = _TLSSignature(tls_session=s) if s.connection_end == "client": self.sig._update_sig(m, s.client_key) elif s.connection_end == "server": # should be TLS 1.3 only self.sig._update_sig(m, s.server_key) return _TLSHandshake.build(self, *args, **kargs)
def process_tls_handshake(self, tls_pkt, tls_msg): if isinstance(tls_msg, TLSClientHello): debug.print("Got client hello") debug.scapy_show(tls_msg) self.session.set_server_rsa_privkey(self.private_key) # STUDENT TODO """ Instructions: 1. process client hello. set the session client random appropriately 2. create the server hello. Set cipher=TLS_DHE_RSA_WITH_AES_128_CBC_SHA.val 3. create the server cert message. Set certs=[self.cert] 4. create server key exchange. params = self.session.server_dh_params sig = <signature you calculate> 5. create server hello done 6. store in the provided server_hello, server_cert, server_key_exchange, and server_hello_done variables """ gmt_unix_time = tls_msg.gmt_unix_time random_bytes = tls_msg.random_bytes version = tls_msg.version cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA.val # set client time and random in session self.session.set_client_random(gmt_unix_time, random_bytes) self.session.set_server_random() server_hello = TLSServerHello( gmt_unix_time=gmt_unix_time, random_bytes=self.session.server_random_bytes, version=version, cipher=cipher ) server_cert = TLSCertificate(certs=[self.cert]) sig = _TLSSignature(sig_alg=0x0401) params = self.session.server_dh_params m = self.session.client_random + self.session.server_random + raw(params) sig._update_sig(m, self.session.server_rsa_privkey) server_key_exchange = TLSServerKeyExchange( params=self.session.server_dh_params, sig=sig ) server_hello_done = TLSServerHelloDone() f_session = tlsSession() f_session.tls_version = 0x303 tls_response = TLS(msg=[server_hello, server_cert, server_key_exchange, server_hello_done], tls_session=f_session) tls_response_bytes = raw(tls_response) debug.scapy_show(tls_response) self.session.record_handshake_message(raw(tls_msg)) self.session.record_handshake_message(raw(server_hello)) self.session.record_handshake_message(raw(server_cert)) self.session.record_handshake_message(raw(server_key_exchange)) self.session.record_handshake_message(raw(server_hello_done)) return tls_response_bytes elif isinstance(tls_msg, TLSClientKeyExchange): debug.print("Got key exchange") debug.scapy_show(tls_msg) # STUDENT TODO """ 1. process the client key exchange by extracting the "exchkeys" 2. These can be passed directly to session.set_client_dh_params """ self.session.record_handshake_message(raw(tls_msg)) exchkeys = tls_msg.exchkeys self.session.set_client_dh_params(ClientDiffieHellmanPublic(exchkeys)) elif isinstance(tls_msg, TLSFinished): debug.print("Got Client Finished") debug.scapy_show(tls_msg) # STUDENT TODO """ 1. process the decrypted TLS finished message. OPTIONALLY, verify the data: local_verify_data = session.compute_handshake_verify("read") local_verify_data ?= tls_msg.vdata 2. Create the change cipher spec 3. store in server_change_cipher_spec """ local_verify_data = self.session.compute_handshake_verify("read") assert(local_verify_data == tls_msg.vdata) self.session.record_handshake_message(raw(tls_msg)) server_change_cipher_spec = TLSChangeCipherSpec() msg1 = TLS(msg=[server_change_cipher_spec]) output = raw(msg1) # STUDENT TODO """ 1. create the TLSFinished message. Set v_data to session.compute_handshake_verify("write") because of scapy weirdness, set tls_session=f_session 2. store in server_finished """ f_session = tlsSession() f_session.tls_version = 0x303 vdata = self.session.compute_handshake_verify("write") assert(vdata != local_verify_data) server_finished = TLSFinished( vdata=self.session.compute_handshake_verify("write"), tls_session=f_session ) msg2 = TLS(msg=[server_finished], tls_session=f_session) msg2.type = 22 # STUDENT TODO """ 1. encrypt the tls finished message (msg2). You already have a method for this. 2. store in encrypted_finished """ encrypted_finished = self.session.encrypt_tls_pkt(msg2) self.session.handshake = False return output+encrypted_finished elif isinstance(tls_msg, Raw): # STUDENT TODO """ 1. This was a HANDSHAKE message scapy couldn't process. It's because it's encrypted 2. decrypt the packet to plaintext_data. You should already have a method for this 3. store in plaintext_data 4. The provided code already re-creates the TLSFinished from your decrypted data """ plaintext_data = self.session.decrypt_tls_pkt(tls_pkt, is_handshake=True) # We re-create the TLS message with the decrypted handshake # Then we call `process_tls_handshake` again with this new message f_session = tlsSession() f_session.tls_version = 0x303 decrypted_msg = TLSFinished(plaintext_data, tls_session=f_session) return self.process_tls_handshake(None, decrypted_msg) return b""