networkfreehard

insider-info

umdctf

Task: a wrapper forwards exactly two TCP-supplied DNS packets to a local UDP DNS server, where TXT queries leak one character of an 819-byte secret and the full secret subdomain returns the flag. Solution: craft compressed multi-question DNS packets to dump all secret characters in one request, then build a chained-pointer qname that expands past the usual DNS length limit and triggers the flag response.

$ ls tags/ techniques/
dns_pointer_compressionoversized_multi_question_queryqname_length_bypass

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

insider-info — UMDCTF

Description

No organizer description was included in the provided workspace files.

English summary: the service accepts exactly two length-prefixed DNS packets over TCP and forwards them to a local UDP resolver. TXT requests for <index>.inside.info reveal one character of a hidden 819-character secret, and querying the full secret as a subdomain of inside.info returns the flag.

Analysis

Reading dns_server.py reveals the core behavior:

  • the wrapper reads exactly two packets from stdin/TCP,
  • each packet is forwarded to a local UDP DNS server,
  • a random secret of length 819 is generated,
  • the secret is split into 13 labels of length 63,
  • N.inside.info TXT returns secret[N],
  • full_secret.inside.info TXT returns the flag.

The intended blocker is DNS name length. A normal domain name is limited to 253 bytes, so the final 819-character subdomain cannot be encoded directly. However, the bundled dnslib parser only checks per-label length during decoding; decode_name() follows compression pointers without enforcing the total expanded qname length.

That gives two useful ideas:

  1. Leak the whole secret in one request by placing 819 TXT questions into a single DNS packet.
  2. Use a second packet whose qnames are chained with compression pointers so the final expanded name becomes the full 13-label secret plus .inside.info.

The first packet also needs compression. A naive request with 819 full qnames is too large for the UDP receive path (recv(8192)). Reusing the repeated .inside.info suffix with DNS pointers shrinks the request to about 8103 bytes, which fits.

Solution

...

$ grep --similar

Similar writeups