Skip to content

Commit 31ec77b

Browse files
committed
Fix dissection of TLS communication with NULL Cipher.
Due to invalid handling of TLS record length, fields (MSG and MAC) were incorrectly interpreted in packets encrypted with NULL Cipher.
1 parent 984e8f8 commit 31ec77b

File tree

3 files changed

+53
-13
lines changed

3 files changed

+53
-13
lines changed

scapy/layers/tls/cert.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,11 @@ def import_from_asn1pkt(self, pubkey):
298298

299299
def encrypt(self, msg, t="pkcs", h="sha256", mgf=None, L=None):
300300
# no ECDSA encryption support, hence no ECDSA specific keywords here
301-
return _EncryptAndVerifyRSA.encrypt(self, msg, t, h, mgf, L)
301+
return _EncryptAndVerifyRSA.encrypt(self, msg, t=t, h=h, mgf=mgf, L=L)
302302

303303
def verify(self, msg, sig, t="pkcs", h="sha256", mgf=None, L=None):
304-
return _EncryptAndVerifyRSA.verify(self, msg, sig, t, h, mgf, L)
304+
return _EncryptAndVerifyRSA.verify(
305+
self, msg, sig, t=t, h=h, mgf=mgf, L=L)
305306

306307

307308
class PubKeyECDSA(PubKey):
@@ -510,10 +511,11 @@ def import_from_asn1pkt(self, privkey):
510511

511512
def verify(self, msg, sig, t="pkcs", h="sha256", mgf=None, L=None):
512513
# Let's copy this from PubKeyRSA instead of adding another baseclass :)
513-
return _EncryptAndVerifyRSA.verify(self, msg, sig, t, h, mgf, L)
514+
return _EncryptAndVerifyRSA.verify(
515+
self, msg, sig, t=t, h=h, mgf=mgf, L=L)
514516

515517
def sign(self, data, t="pkcs", h="sha256", mgf=None, L=None):
516-
return _DecryptAndSignRSA.sign(self, data, t, h, mgf, L)
518+
return _DecryptAndSignRSA.sign(self, data, t=t, h=h, mgf=mgf, L=L)
517519

518520

519521
class PrivKeyECDSA(PrivKey):
@@ -668,10 +670,10 @@ def isSelfSigned(self):
668670

669671
def encrypt(self, msg, t="pkcs", h="sha256", mgf=None, L=None):
670672
# no ECDSA *encryption* support, hence only RSA specific keywords here
671-
return self.pubKey.encrypt(msg, t, h, mgf, L)
673+
return self.pubKey.encrypt(msg, t=t, h=h, mgf=mgf, L=L)
672674

673675
def verify(self, msg, sig, t="pkcs", h="sha256", mgf=None, L=None):
674-
return self.pubKey.verify(msg, sig, t, h, mgf, L)
676+
return self.pubKey.verify(msg, sig, t=t, h=h, mgf=mgf, L=L)
675677

676678
def remainingDays(self, now=None):
677679
"""

scapy/layers/tls/record.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,7 @@ def pre_dissect(self, s):
485485

486486
frag = self._tls_decompress(cfrag)
487487

488-
if (decryption_success and
489-
not isinstance(self.tls_session.rcs.cipher, Cipher_NULL)):
488+
if decryption_success:
490489
self.deciphered_len = len(frag)
491490
else:
492491
self.deciphered_len = None

test/tls.uts

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
% Tests for TLS module
2-
#
2+
#
33
# Try me with :
44
# bash test/run_tests -t test/tls.uts -F
55

@@ -15,7 +15,7 @@
1515

1616
+ Test HMACs
1717

18-
= Crypto - Hmac_MD5 instantiation, parameter check
18+
= Crypto - Hmac_MD5 instantiation, parameter check
1919
from scapy.layers.tls.crypto.h_mac import Hmac_MD5
2020
a = Hmac_MD5("somekey")
2121
a.key_len == 16 and a.hmac_len == 16
@@ -32,7 +32,7 @@ t7 = a(b'\xaa'*80).digest("Test Using Larger Than Block-Size Key and Larger Than
3232
t1 and t2 and t3 and t4 and t5 and t6 and t7
3333

3434

35-
= Crypto - Hmac_SHA instantiation, parameter check
35+
= Crypto - Hmac_SHA instantiation, parameter check
3636
from scapy.layers.tls.crypto.h_mac import Hmac_SHA
3737
a = Hmac_SHA("somekey")
3838
a.key_len == 20 and a.hmac_len == 20
@@ -986,6 +986,45 @@ from scapy.layers.tls.record import _TLSMsgListField
986986
assert isinstance(_TLSMsgListField.m2i(_TLSMsgListField("", []), TLS(type=0), '\x00\x03\x03\x00\x03abc'), Raw)
987987

988988

989+
###############################################################################
990+
####### Read handshake with TLS_ECDHE_ECDSA_WITH_NULL_SHA #####################
991+
###############################################################################
992+
993+
+ Read handshake with NULL Cipher
994+
995+
= Reading test session - Loading unparsed TLS records
996+
p1_ch = b'\x16\x03\x01\x00{\x01\x00\x00w\x03\x03\x86C\xf2\xe4x\xbaL\x9a`\xc3\x9aR\xa8\xb4\xac\xd0\r\xe2\xa3N\xe6\xa8]g5z$j\xb1(%\xe3\x00\x00\x08\xc0\x06\xc0#\xc0$\x00\xff\x01\x00\x00F\x00\x0b\x00\x04\x03\x00\x01\x02\x00\n\x00\n\x00\x08\x00\x1d\x00\x17\x00\x19\x00\x18\x00#\x00\x00\x00\x16\x00\x00\x00\x17\x00\x00\x00\r\x00 \x00\x1e\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03'
997+
p2_sh = b'\x16\x03\x03\x006\x02\x00\x002\x03\x03C\nm.s\x07W\xef\x91\xf0\xc7\xd8\xaa\xc3NL}\xb0tw?\xd8\n\x8f\x8d\xc4\xee,fhY\x85\x00\xc0\x06\x00\x00\n\x00\x0b\x00\x02\x01\x00\x00\x17\x00\x00'
998+
p3_cert = b'\x16\x03\x03\x02\xca\x0b\x00\x02\xc6\x00\x02\xc3\x00\x02\xc00\x82\x02\xbc0\x82\x02\x1d\xa0\x03\x02\x01\x02\x02\x02\x04\xd20\n\x06\x08*\x86H\xce=\x04\x03\x020v1\x0b0\t\x06\x03U\x04\x06\x13\x02PL1\x0b0\t\x06\x03U\x04\x08\x0c\x02PL1\x0c0\n\x06\x03U\x04\x07\x0c\x03KTW1\x0c0\n\x06\x03U\x04\n\x0c\x03ORG1\x0e0\x0c\x06\x03U\x04\x0b\x0c\x05OUNIT1\x110\x0f\x06\x03U\x04\x03\x0c\x08SomeName1\x1b0\x19\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x0cemail@adress0\x1e\x17\r190404065502Z\x17\r270621065502Z0\x81\x881\x0b0\t\x06\x03U\x04\x06\x13\x02PL1\x0b0\t\x06\x03U\x04\x08\x0c\x02PL1\x0c0\n\x06\x03U\x04\x07\x0c\x03KTW1\x0c0\n\x06\x03U\x04\n\x0c\x03ORG1\x110\x0f\x06\x03U\x04\x0b\x0c\x08SomeUnit1\x110\x0f\x06\x03U\x04\x03\x0c\x08SomeName1\r0\x0b\x06\x03U\x04\x05\x0c\x0412341\x1b0\x19\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x0cemail@adress0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\x00\x04\x97\xfcij\xa2\xeeZh>\x94\n\xad\x1f\x16\x91\x80\x89\xc5\xb3\xc4\xb7\xd1A\xf0(\x96\x93UJ\xca\x98Y\xdec\xad\xa0\xbb\xd9\xebl\x15\xc7\xf2\xa9\xcfl\xbf\x0f\xed"\x08%\x8f\xaf\xd7\xf1K\x98\xf1\xf9\x04.\x05\x81\xa3\x81\x870\x81\x840\t\x06\x03U\x1d\x13\x04\x020\x000\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x03\xa80\'\x06\x03U\x1d%\x04 0\x1e\x06\x08+\x06\x01\x05\x05\x07\x03\x04\x06\x08+\x06\x01\x05\x05\x07\x03\x02\x06\x08+\x06\x01\x05\x05\x07\x03\x010\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14\xb2\x12\x8c\xe4\x16\x17XjZ%+4G\xa0\xfd\x0b!\x91\xc7\xec0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xe2\x17\xb1\xb1\xe1\xca3\xe8\xed\xfd\x86\x13\x10\xe7x5H\xdf1\xf50\n\x06\x08*\x86H\xce=\x04\x03\x02\x03\x81\x8c\x000\x81\x88\x02B\x01\xeb\xc9\xbe\xa1^\x12\x85\x10\x03\x9f$\xc6(\xce\xd7x\xc3w\x00\xd2\x8an\\r\xe8\xb3\xb9\x92Q\x8f\x9f\x81v\xa7*\xa0\xb2\xd8\x17\x12\xbe\xef\x04c\x97T\x8c;&B[\xda\xf8\x81c7\xd25\xfb\xae\x19\x81A\x9b\xc6\x02B\x012\xe9G\xd9;9\x97\x9c\xed_\xa19K\xef\x1b\xf1\x8f\x01\x86icw\r\xa1\x19\xb7\xa6\xe6\xc7\xef\xd6\x1bTr\xb1~\x8ae:4\xdb\xdb\x07\xcf&\xd4\xc0,\xf7\xf5\xa7\'m\xe1a\x06\xb5>\xec\xf1kDB\xf7\\'
999+
p4_ske = b'\x16\x03\x03\x00\x93\x0c\x00\x00\x8f\x03\x00\x17A\x04\xb4\xd4\xf6^\x87(\x97\xc4\xe5)\x19E\xe1\x9e\xfdPOf\x91\xa1PTdk\xdcU\n\xb9\x07\x93\xc8\xd1\xb0\tA\xce\xf9\xcd\x0e\xb6\xd7\xf0\r\xc7\xba\xaa\xd9zA\xe8\x8f(\xe1\x0fE[+&9\x90\xd4\n`O\x06\x03\x00F0D\x02 -\x04\xe5.g\x92\xca\xbe\xe4\x87\x9a\x88\x80~<\x10Q&v\xfa~\xf4h\x7f\xd0\xa1\x16\xf2\xfdN\x8b\xdf\x02 eI\xf0{E6mU0bRt\xb9\xc4\xcff\xf9\x87\xfdL\xdd\xa3d\xcf1\xab| ~"<\xcd'
1000+
p5_shd = b'\x16\x03\x03\x00\x04\x0e\x00\x00\x00'
1001+
p6_cke_ccs_cfin = b'\x16\x03\x03\x00F\x10\x00\x00BA\x04w_\xba\x8cX9\xab\x1f\x1drw\xaa\x08"\xe6\x05\x8eS\x8637\xb75\xe4\x1f\xc3H-\x12\xf4\xbb\x10\xf8\xb8.[?\x11sG\x0b\x18\x03}\x16n\n\xdb\x7f\x92\xear\xd1\x1a\x07.e;\xfc\xcer\x1f\xebA\x14\x03\x03\x00\x01\x01\x16\x03\x03\x00$\x14\x00\x00\x0cYX\xacX\xb81\x1fX\x8f\xbe\x1dJ\x10\xce\xca2\xb4\xc3m\xf1\x16c\xdb\xfc\x08\x16\x1d\x82\x83U\x8c\xe1'
1002+
p7_ccs = b'\x14\x03\x03\x00\x01\x01'
1003+
p8_sfin = b'\x17\x03\x03\x00$\x14\x00\x00\x0c8\x1f\x18\xb6f\x98\xe3\xc0\xa4\xe2\xf8\xba\n\xd7\xd0\xb93y]\x1a\n\xeb\xc39nd\xa5\xd7\x8c\xe5\xf9\x91'
1004+
1005+
= Reading TLS test session
1006+
t1 = TLS(p1_ch)
1007+
t2 = TLS(p2_sh, tls_session=t1.tls_session.mirror())
1008+
t3 = TLS(p3_cert, tls_session=t2.tls_session)
1009+
t4 = TLS(p4_ske, tls_session=t3.tls_session)
1010+
t5 = TLS(p5_shd, tls_session=t4.tls_session)
1011+
t6 = TLS(p6_cke_ccs_cfin, tls_session=t5.tls_session.mirror())
1012+
1013+
= Verify TLSClientKeyExchange
1014+
cke = t6.msg[0]
1015+
assert isinstance(cke, TLSClientKeyExchange)
1016+
1017+
= Verify TLSChangeCipherSpec
1018+
ccs = t6.payload.msg[0]
1019+
assert isinstance(ccs, TLSChangeCipherSpec)
1020+
1021+
= Verify TLSFinished
1022+
cfin = t6.payload.payload.msg[0]
1023+
assert isinstance(cfin, TLSFinished)
1024+
1025+
= Verify MAC - TLSFinished record
1026+
assert (t6.payload.payload.mac == b'\x10\xce\xca2\xb4\xc3m\xf1\x16c\xdb\xfc\x08\x16\x1d\x82\x83U\x8c\xe1')
1027+
9891028
###############################################################################
9901029
################## Reading TLS vulnerable test session ########################
9911030
###############################################################################
@@ -1193,14 +1232,14 @@ def test_tls_tools():
11931232
assert save_comp is not comp
11941233
block_size = 8
11951234
_tls_add_pad(comp, block_size)
1196-
assert isinstance(comp, TLSCompressed)
1235+
assert isinstance(comp, TLSCompressed)
11971236
assert comp.len == save_comp.len + -save_comp.len % block_size + 1
11981237
had_pad = _tls_del_pad(comp)
11991238
assert had_pad
12001239
assert comp == save_comp
12011240
block_size = save_comp.len // 2
12021241
_tls_add_pad(comp, block_size)
1203-
assert isinstance(comp, TLSCompressed)
1242+
assert isinstance(comp, TLSCompressed)
12041243
assert comp.len == save_comp.len + -save_comp.len % block_size + 1
12051244
had_pad = _tls_del_pad(comp)
12061245
assert had_pad

0 commit comments

Comments
 (0)