DNS: 'decompression loop' corner-case

This commit is contained in:
gpotter2 2017-10-27 13:15:39 +02:00
parent 5eec1f40f4
commit a680815378
2 changed files with 19 additions and 6 deletions

View File

@ -24,10 +24,11 @@ import scapy.modules.six as six
from scapy.modules.six.moves import range
class InheritOriginDNSStrPacket(Packet):
__slots__ = Packet.__slots__ + ["_orig_s"]
__slots__ = Packet.__slots__ + ["_orig_s", "_orig_p"]
def __init__(self, _pkt=None, _orig_s=None, *args, **kwargs):
def __init__(self, _pkt=None, _orig_s=None, _orig_p=None, *args, **kwargs):
self._orig_s = _orig_s
self._orig_p = _orig_p
Packet.__init__(self, _pkt=_pkt, *args, **kwargs)
class DNSStrField(StrField):
@ -141,12 +142,12 @@ class DNSRRField(StrField):
ret = s[p:p+10]
type,cls,ttl,rdlen = struct.unpack("!HHIH", ret)
p += 10
rr = DNSRR(b"\x00"+ret+s[p:p+rdlen], _orig_s=s)
rr = DNSRR(b"\x00"+ret+s[p:p+rdlen], _orig_s=s, _orig_p=p)
if type in [2, 3, 4, 5]:
rr.rdata = DNSgetstr(s,p)[0]
del(rr.rdlen)
elif type in DNSRR_DISPATCHER:
rr = DNSRR_DISPATCHER[type](b"\x00"+ret+s[p:p+rdlen], _orig_s=s)
rr = DNSRR_DISPATCHER[type](b"\x00"+ret+s[p:p+rdlen], _orig_s=s, _orig_p=p)
else:
del(rr.rdlen)
@ -182,7 +183,7 @@ class DNSQRField(DNSRRField):
def decodeRR(self, name, s, p):
ret = s[p:p+4]
p += 4
rr = DNSQR(b"\x00"+ret, _orig_s=s)
rr = DNSQR(b"\x00"+ret, _orig_s=s, _orig_p=p)
rr.qname = plain_str(name)
return rr, p
@ -199,7 +200,10 @@ class RDataField(StrLenField):
p = ((l & ~0xc0) << 8) + orb(s[1]) - 12
s = DNSgetstr(pkt._orig_s, p)[0]
else: # No compression / Cannot decompress
s = DNSgetstr(s, 0)[0]
if hasattr(pkt, "_orig_s") and pkt._orig_s:
s = DNSgetstr(pkt._orig_s, pkt._orig_p)[0]
else:
s = DNSgetstr(s, 0)[0]
elif pkt.type == 16: # TXT
ret_s = b""
tmp_s = s

View File

@ -5800,6 +5800,15 @@ assert b.an[7].target == 'sCapys-fLuff.local.'
assert b.an[6].rrname == '_apple-mobdev2._tcp.local.'
assert b.an[6].rdata == '24:e3:14:4d:84:c0@fe80::26e3:14ff:fe4d:84c0._apple-mobdev2._tcp.local.'
= DNS frame with decompression hidden args
c = b'\x01\x00^\x00\x00\xfb\x14\x0cv\x8f\xfe(\x08\x00E\x00\x01C\xe3\x91@\x00\xff\x11\xf4u\xc0\xa8\x00\xfe\xe0\x00\x00\xfb\x14\xe9\x14\xe9\x01/L \x00\x00\x84\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05_raop\x04_tcp\x05local\x00\x00\x0c\x00\x01\x00\x00\x11\x94\x00\x1e\x1b140C768FFE28@Freebox Server\xc0\x0c\xc0(\x00\x10\x80\x01\x00\x00\x11\x94\x00\xa0\ttxtvers=1\x08vs=190.9\x04ch=2\x08sr=44100\x05ss=16\x08pw=false\x06et=0,1\x04ek=1\ntp=TCP,UDP\x13am=FreeboxServer1,2\ncn=0,1,2,3\x06md=0,2\x07sf=0x44\x0bft=0xBF0A00\x08sv=false\x07da=true\x08vn=65537\x04vv=2\xc0(\x00!\x80\x01\x00\x00\x00x\x00\x19\x00\x00\x00\x00\x13\x88\x10Freebox-Server-3\xc0\x17\xc1\x04\x00\x01\x80\x01\x00\x00\x00x\x00\x04\xc0\xa8\x00\xfe'
pkt = Ether(c)
assert DNS in pkt
assert pkt.an.rdata == '140C768FFE28@Freebox Server._raop._tcp.local.'
assert pkt.an.getlayer(DNSRR, type=1).rrname == 'Freebox-Server-3.local.'
assert pkt.an.getlayer(DNSRR, type=1).rdata == '192.168.0.254'
= Layer binding
* Test DestMACField & DestIPField