scapy icon indicating copy to clipboard operation
scapy copied to clipboard

scapy doesn't assemble DNS queries/responses sent over TCP in more than one packet

Open evverx opened this issue 1 year ago • 0 comments

Brief description

When DNS messages are sent over TCP in more than one packet scapy dissects each packet separately and since usually they don't pass the sanity checks their payloads get wrapped into Raw. In theory it should be possible to add DNS.tcp_reassembly that could assemble those messages but due to the sanity checks those packets can never reach it currently.

(It came up in https://github.com/secdev/scapy/pull/4012 but since it's kind of tangential I thought it would be better to move it here)

Scapy version

3da71cb275721292131a3ea5196bfa98883741f2

Python version

3.11.3

Operating system

Linux version 6.3.4-101.fc37.x86_64

Additional environment information

No response

How to reproduce

dns-openpgpkey.pcap contains a response with an OPENPGPKEY RR that arrived in two separate packets.

>>> pkts = sniff(offline='dns-openpgpkey.pcap', session=TCPSession)
INFO: Malformed DNS message: invalid length!
INFO: Malformed DNS message: invalid length!

Actual result

scapy wraps the DNS part of those packets into Raw:

>>> pkts.nsummary()
0000 Ether / IP / UDP / DNS Qry "b'd08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org.'"
0001 Ether / IP / UDP / DNS Ans
0002 Ether / IP / TCP 10.0.2.100:44681 > 1.1.1.1:domain S
0003 Ether / IP / TCP 1.1.1.1:domain > 10.0.2.100:44681 SA
0004 Ether / IP / TCP 10.0.2.100:44681 > 1.1.1.1:domain A
0005 Ether / IP / TCP / DNS Qry "b'd08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org.'"
0006 Ether / IP / TCP 1.1.1.1:domain > 10.0.2.100:44681 A
0007 Ether / IP / TCP 1.1.1.1:domain > 10.0.2.100:44681 PA / Raw
0008 Ether / IP / TCP 10.0.2.100:44681 > 1.1.1.1:domain A
0009 Ether / IP / TCP 1.1.1.1:domain > 10.0.2.100:44681 PA / Raw
0010 Ether / IP / TCP 10.0.2.100:44681 > 1.1.1.1:domain A
0011 Ether / IP / TCP 10.0.2.100:44681 > 1.1.1.1:domain FA
0012 Ether / IP / TCP 1.1.1.1:domain > 10.0.2.100:44681 A
0013 Ether / IP / TCP 1.1.1.1:domain > 10.0.2.100:44681 FA
0014 Ether / IP / TCP 10.0.2.100:44681 > 1.1.1.1:domain A

Expected result

To get the response the Raw payloads should be combined manually using something like

DNS(pkts[7][Raw].load[2:] + pkts[9][Raw].load)
...

The idea is to get DNS.tcp_reassemble to do that :-)

I'm not sure if it's helpful or not but here's what tshark shows:

$ tshark -r dns-openpgpkey.pcap
...
    3   0.404609   10.0.2.100 → 1.1.1.1      TCP 74 44681 → 53 [SYN] Seq=0 Win=64660 Len=0 MSS=1220 SACK_PERM TSval=2859481442 TSecr=0 WS=128
    4   0.431399      1.1.1.1 → 10.0.2.100   TCP 58 53 → 44681 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=65480
    5   0.431475   10.0.2.100 → 1.1.1.1      TCP 54 44681 → 53 [ACK] Seq=1 Ack=1 Win=64660 Len=0
    6   0.431646   10.0.2.100 → 1.1.1.1      DNS 183 Standard query 0xb390 OPENPGPKEY d08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org OPT
    7   0.432353      1.1.1.1 → 10.0.2.100   TCP 54 53 → 44681 [ACK] Seq=1 Ack=130 Win=65535 Len=0
    8   0.831929      1.1.1.1 → 10.0.2.100   TCP 1454 53 → 44681 [PSH, ACK] Seq=1 Ack=130 Win=65535 Len=1400 [TCP segment of a reassembled PDU]
    9   0.831960   10.0.2.100 → 1.1.1.1      TCP 54 44681 → 53 [ACK] Seq=130 Ack=1401 Win=63440 Len=0
   10   0.832338      1.1.1.1 → 10.0.2.100   DNS 1006 Standard query response 0xb390 OPENPGPKEY d08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org OPENPGPKEY OPT

Related resources

dns-openpgpkey.zip

evverx avatar Jun 03 '23 04:06 evverx