Skip to content

Instantly share code, notes, and snippets.

@oskar456
Created May 8, 2019 00:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oskar456/abd3502e5ee1affbbac868c43209a75b to your computer and use it in GitHub Desktop.
Save oskar456/abd3502e5ee1affbbac868c43209a75b to your computer and use it in GitHub Desktop.
Walk NSEC3 chain of .SK TLD in order to discover zones with secure delegation
#!/usr/bin/env python3
from hashlib import sha1
from base64 import b32encode
import csv
from collections import OrderedDict
from itertools import zip_longest
import dns.name
from dns.rdtypes.ANY.NSEC3 import b32_normal_to_hex
import dns.message
import dns.query
def digest_to_ascii(digest):
return b32encode(digest).translate(b32_normal_to_hex).decode("ascii")
def get_nsec3_hash(name, iterations=1, salt=None):
wirename = dns.name.from_text(name).to_wire()
if salt:
salt = bytes.fromhex(salt)
wirename += salt
digest = sha1(wirename).digest()
while iterations > 0:
if salt:
digest += salt
digest = sha1(digest).digest()
iterations -= 1
return digest_to_ascii(digest)
def read_domains_txt(domainstxt):
yield from csv.DictReader(
(r for r in domainstxt if not r.startswith("--")),
delimiter=";",
)
def walk_nsec3(raindict, origin="sk"):
secdomains = iter(raindict.values())
firstdomain = next(secdomains)
nextdomain = dict((k, v)
for k, v
in zip_longest(raindict.values(),
secdomains,
fillvalue=firstdomain)
)
secureddomains = list()
originhash = get_nsec3_hash(origin)
d = origin
h = originhash
while True:
q = dns.message.make_query(d + ".", "DS", want_dnssec=True)
res = dns.query.tcp(q, "c.tld.sk")
h = digest_to_ascii(
[rrset[0].next for rrset in res.authority
if rrset.rdtype == 50 and
rrset.name.labels[0].decode("ascii") == h.lower()
][0]
)
d = raindict[h]
print(h, d)
secureddomains.append((h, d))
if h == originhash:
break
d = nextdomain[d]
with open("domains-secured.tsv", "w") as outf:
writer = csv.writer(outf, dialect="excel-tab")
writer.writerow(["hash", "domena"])
for i in secureddomains:
writer.writerow(i)
def main():
raindict = {get_nsec3_hash("sk"): "sk", }
with open("domains.txt", newline="") as inf:
for r in read_domains_txt(inf):
d = r["domena"]
h = get_nsec3_hash(d)
raindict[h] = d
print(h, d)
raindict = OrderedDict(sorted(raindict.items()))
walk_nsec3(raindict)
with open("domains-rainbow.tsv", "w") as outf:
writer = csv.writer(outf, dialect="excel-tab")
writer.writerow(["hash", "domena"])
for i in raindict.items():
writer.writerow(i)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment