Skip to content

Dissecting TLS with NULL cipher #1976

@wasilukm

Description

@wasilukm

Brief description

Scapy incorrectly dissects TLS packets with NULL cipher - message dissecting is too greedy which results in consuming MAC (and possibly padding)

Environment

  • Scapy version: e44bd373f0839ed67c1c91cbfc94cde58aee8722
  • Python version: 2.7
  • Operating System: Windows

How to reproduce

Execute following code with attached pcap:

from scapy.all import *
from scapy.layers.tls.record import TLS

bind_layers(TCP, TLS)

CLIENT_IP = '10.192.71.100'
SERVER_IP = '10.192.71.150'
from_pcap = rdpcap("handshake.pcapng")

session = None
tls_only = []
for pkt in from_pcap:
    if pkt.haslayer('TLS'):
        if not session:
            session = pkt[TLS].tls_session
        else:
            connection_end = session.rcs.connection_end
            # depending on who is the target switch TLS session state
            if ((pkt[IP].dst == SERVER_IP and connection_end == 'client') or
                (pkt[IP].dst == CLIENT_IP and connection_end == 'server')):
                session.mirror()
        # dissect again TLS with session context
        tls_only.append(TLS(raw(pkt[TLS]), tls_session=session))
tls_only[5].show()

The pcap contains TLS handshake:
image

I marked a TLS record which is a subject of the analysis.

Actual result

###[ TLS ]### 
        type      = handshake
        version   = TLS 1.2
        len       = 36
        iv        = ''
        \msg       \
         |###[ TLS Handshake - Finished ]### 
         |  msgtype   = finished
         |  msglen    = 12
         |  vdata     = 'YX\xacX\xb81\x1fX\x8f\xbe\x1dJ'
         |###[ TLS Handshake - Client Key Exchange ]### 
         |  msgtype   = client_key_exchange
         |  msglen    = 13552178
         |  \exchkeys  \
         |   |###[ Raw ]### 
         |   |  load      = '\xb4\xc3m\xf1\x16c\xdb\xfc\x08\x16\x1d\x82\x83U\x8c\xe1'
        mac       = ''
        pad       = ''
        padlen    = None

Expected result

###[ TLS ]### 
        type      = handshake
        version   = TLS 1.2
        len       = 36    [deciphered_len= 16]
        iv        = ''
        \msg       \
         |###[ TLS Handshake - Finished ]### 
         |  msgtype   = finished
         |  msglen    = 12
         |  vdata     = 'YX\xacX\xb81\x1fX\x8f\xbe\x1dJ'
        mac       = '\x10\xce\xca2\xb4\xc3m\xf1\x16c\xdb\xfc\x08\x16\x1d\x82\x83U\x8c\xe1'
        pad       = ''
        padlen    = None

Related resources

handshake.zip

Fix proposal

I'v got expected result by removing and not isinstance(self.tls_session.rcs.cipher, Cipher_NULL) from

if (decryption_success and

The fix seems to be too easy so I doubt in its correctness. Please provide guidance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions