scapy icon indicating copy to clipboard operation
scapy copied to clipboard

[TLS] bytes(TLS_Ext_CSR) gives wrong result when TLS_Ext_CSR.len=0

Open micpez opened this issue 7 years ago • 7 comments

Brief description

bytes(TLS_Ext_CSR) returns one additional byte when with TLS_Ext_CSR.len=0

The reason should be that:

  • raw_packet_cache is not considered in _GenericTLSSessionInheritance.__bytes__()
  • <Field (TLS_Ext_CSR).stype>.i2m() method returns 0 even if val is None.

Environment

  • Scapy version: 2.4.0.dev601
  • Python: 3.6.5
  • Operating System: Ubuntu

How to reproduce

ext_csr = TLS_Ext_CSR(b'\x00\x05\x00\x00')
>>> ext_csr.show()
###[ TLS Extension - Certificate Status Request ]### 
  type      = status_request
  len       = 0
  stype     = None
  \req       \

Actual result

>>> bytes(ext_csr)
b'\x00\x05\x00\x00\x00'

Expected result

>>> ext_csr.raw_packet_cache
b'\x00\x05\x00\x00'

As a consequence, the length (and bytes) of the TCP payload is also wrong, e.g. in the example in the picture, instead of length=1360:

>>> len(pkt[TCP].payload)
1361

image

Related resources

traces / sample pcaps (stripped to the relevant frames), related standards, RFCs or other resources

micpez avatar Nov 30 '18 13:11 micpez

I have been reading the RFC4366 and I think that current Scapy behavior is correct. I believe that the best solution is to use TLS_Ext_Unknown(type=5, len=0) to generate such extension.

Is is something that you are trying to inject, of sniff from the network? Could you share some packets? I did not manage to capture similar ones.

guedou avatar Apr 02 '19 12:04 guedou

Sorry, I cannot retrieve the packet. I was sniffing from the network, the picture is a real case.

micpez avatar Apr 02 '19 13:04 micpez

If I understand correctly, you sniffed the Server Hello message, dissected it with Scapy, then tried to build it again?

The real extension was 4 bytes, but Scapy returned 5. Am I correct?

guedou avatar Apr 02 '19 14:04 guedou

I sniffed Server Hello. len(bytes(pkt[TCP])) gives 1380, which is correct. len(bytes(pkt[TCP].payload)) gives 1361 bytes instead of 1360, as in picture. bytes(pkt[TCP][TLS_Ext_CSR]) gives b'\x00\x05\x00\x00\x00'. bytes(pkt[TCP][TLS_Ext_CSR].raw_packet_cache) gives b'\x00\x05\x00\x00', as it should be per picture. From here the extra byte in overall length 1361 vs. 1360.

The example above is reconstructing just the TLS Ext for sake of easy reproduction, the results is the same.

micpez avatar Apr 02 '19 20:04 micpez

Thanks for the report.

I will try to find a correct fix. As of today, Scapy encodes the Certificate Status Request on 5 bytes. It still did not find an explanation in RFCs but other implementations seem to consider that empty extensions exist and are encoder on 4 bytes.

guedou avatar Apr 03 '19 13:04 guedou

Scapy encodes on 5 bytes due to:

  • raw_packet_cache is not considered in _GenericTLSSessionInheritance.bytes()
  • <Field (TLS_Ext_CSR).stype>.i2m() method returns 0 even if val is None.

I do not know if this is wanted due to an RFC or not.

micpez avatar Apr 03 '19 16:04 micpez

Fixed (indirectly) by #4012.

gpotter2 avatar Aug 03 '23 16:08 gpotter2