mdaxfr

- Mass DNS AXFR
git clone git://git.acid.vegas/mdaxfr.git
Log | Files | Refs | Archive | README | LICENSE

commit ecbd8139f4d290d780ec30e6567e6ac59cabd049
parent 4c8ac71c62619d3d7ab276f82b859d5b737a64ea
Author: acidvegas <acid.vegas@acid.vegas>
Date: Sun, 10 Mar 2024 18:04:01 -0400

POSIX version drastically improved, allows parsing AXFR output files now, improved verbosity, daxfr merged into mdaxfr script.

Diffstat:
A.screens/preview_ripe.png | 0
A.screens/preview_root.png | 0
MREADME.md | 41++++++++++++++++++++++++++++++++---------
Dextras/daxfr | 70----------------------------------------------------------------------
Mmdaxfr | 203++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------

5 files changed, 177 insertions(+), 137 deletions(-)

diff --git a/.screens/preview_ripe.png b/.screens/preview_ripe.png
Binary files differ.
diff --git a/.screens/preview_root.png b/.screens/preview_root.png
Binary files differ.
diff --git a/README.md b/README.md
@@ -1,27 +1,50 @@
 # Mass DNS AXFR (Zone Transfer)
 
-###### [Zone Transfer](https://en.wikipedia.org/wiki/DNS_zone_transfer) on all of the [Root Nameservers](https://en.wikipedia.org/wiki/Root_name_server) and [Top-level Domains](https://en.wikipedia.org/wiki/Top-level_domain) *(TLDs)*.
+## Information
+MDAXFR allows you to perform a DNS [Zone Transfer](https://en.wikipedia.org/wiki/DNS_zone_transfer) against a target domain by resolving all of the domains nameservers to their respective A/AAAA records and making an AXFR attempt against each of the IP addresses.
+
+You can also use this tool against the [Root Nameservers](https://en.wikipedia.org/wiki/Root_name_server) and [Top-level Domains](https://en.wikipedia.org/wiki/Top-level_domain) *(TLD)*, including those in the [Public Suffix List](https://en.wikipedia.org/wiki/Public_Suffix_List) *(PSL)* aswell.
+
+![](.screens/preview_ripe.png)
+![](.screens/preview_root.png)
 
 ## Expectations & Legalities
 It is expected to set *realistic* expectations when using this tool. In contemporary network configurations, AXFR requests are typically restricted, reflecting best practices in DNS security. While many nameservers now disallow AXFR requests, there may still be occasional instances where configurations permit them. Always exercise due diligence and ensure ethical use.
 
-## Requirements
+## Usage
+### POSIX Version
+
+```shell
+./mdaxfr <option>
+```
+
+###### Options
+| Argument      | Description                                                                                 |
+| ------------- | ------------------------------------------------------------------------------------------- |
+| `-tld`,       | Perform AXFR on all TLDs                                                                    |
+| `-psl`,       | Perform AXFR on all PSL TLDs                                                                |
+| `<axfr_file>` | Perform AXFR on all domains found in `<axfr_file>` *(must be an AXFR output file from dig)* |
+| `<domain>`    | Perform AXFR on `<domain>`                                                                  |
+
+### Python Version
+```shell
+python mdaxfr.py <option>
+```
+
+###### Requirements
 - [dnspython](https://pypi.org/project/dnspython/) *(`pip install dnspython`)*
 
-## Usage
+###### Options
 | Argument              | Description                                          |
 | --------------------- | ---------------------------------------------------- |
 | `-c`, `--concurrency` | Maximum concurrent tasks.                            |
 | `-o`, `--output`      | Specify the output directory *(default is axfrout)*. |
 | `-t`, `--timeout`     | DNS timeout *(default: 30)*                          |
 
-## Information
+## Statistics, laughs, & further thinking...
 I only wrote this to shit on **[this bozo](https://github.com/flotwig/TLDR-2/)** who took a dead project & brought it back to life by making it even worse. Rather than making a pull request to give this bloke more credit in his "tenure" as a developer, I decided to just rewrite it all from scratch so people can fork off of *clean* code instead.
 
-This repostiory also contains a [pure POSIX version](./mdaxfr) for portability, aswell as a [script](./extras/opennic) to do zone transfers on [OpenNIC TLDs](https://wiki.opennic.org/opennic/dot), a special [ozones](./extras/ozones) script for fetching a few obscure additional zones, and a [domain axfr script](./extras/daxfr) to target a specific website.
-
-## Statistics, laughs, & further thinking...
-As of my last scan in 2023, I was only able to AXFR the zones for **8** out of **1,456** root TLDs, with a few of them being zones that were already retrieved by [acidvegas/czds](https://github.com/acidvegas/czds/), & **114** out of **7,977** TLDs in the [Public suffix list](https://publicsuffix.org/). The addition scripts in this repository provide an additional **37** zone files.
+As of my last scan in 2023, I was only able to AXFR the zones for **8** out of **1,456** root TLDs, with a few of them being zones that were already retrieved by [acidvegas/czds](https://github.com/acidvegas/czds/), & **114** out of **7,977** TLDs in the [Public suffix list](https://publicsuffix.org/). The [addition scripts](./extras/) in this repository provide an additional **37** zone files.
 
 For laughs, here is a one-liner mass zone axfr:
 ```bash
@@ -29,7 +52,7 @@ curl -s https://www.internic.net/domain/root.zone | awk '$4=="A" || $4=="AAAA" {
 ```
 **Note:** Don't actually use this lol...
 
-It is interesting to have seen this has worked on some "darknet" DNS servers...would maybe look into exploring collecting more zones for alterntive DNS routing. Some of that goes beyond an "AXFR" though...
+It is interesting to have seen this has worked on some "darknet" DNS servers...would maybe look into exploring collecting more zones for alterntive DNS routing. I am also intruiged at how much you can explore [ARPANET](https://en.wikipedia.org/wiki/ARPANET) with AXFRs...more ARPAgheddon coming soon...
 
 ___
 
diff --git a/extras/daxfr b/extras/daxfr
@@ -1,69 +0,0 @@
-#!/bin/sh
-# Domain AXFR - developed by acidvegas (https://git.acid.vegas/mdaxfr)
-# This one will take a domain as an argument and attempt to perform an AXFR against all of the nameservers for that domain.
-# You can also pass an AXFR output file as an argument to attempt AXFR against all of the unique domains found in the file.
-
-# Colors
-BLUE="\033[1;34m"
-CYAN="\033[1;36m"
-GREEN="\033[1;32m"
-GREY="\033[1;90m"
-PURPLE='\033[0;35m'
-RED="\033[1;31m"
-YELLOW="\033[1;33m"
-RESET="\033[0m"
-
-# Globals
-output_dir="daxfrout"
-
-perform_axfr() {
-    domain=$1
-    ns=$2
-    ip=$3
-
-    echo "${YELLOW}Attempting AXFR for ${CYAN}${domain}${YELLOW} from ${PURPLE}${ns} ${GREY}(${ip})${RESET}"
-
-    axfr_output=$(dig +retry=3 +time=10 @$ip AXFR $domain)
-    axfr_status=$?
-
-    if [ $axfr_status -eq 0 ] && echo "$axfr_output" | grep -q "XFR size: "; then
-        echo "$axfr_output" > "${output+dir}/axfr-${domain}_${ns}_${ip}.txt"
-        size=$(echo "$axfr_output" | awk '/XFR size:/ {print $4}')
-        echo "${GREEN}Successful AXFR for ${CYAN}${domain}${GREEN} from ${PURPLE}${ns} ${GREY}(${ip}) ${BLUE}[${size} records]${RESET}"
-    else
-        echo "${RED}    Failed AXFR for ${CYAN}${domain}${RED} from ${PURPLE}${ns} ${GREY}(${ip})${RESET}"
-    fi
-}
-
-process_domain() {
-    domain=$1
-    nameservers=$(dig +short +retry=3 +time=10 $domain NS)
-
-    [ -z "$nameservers" ] && echo "${GREY}No nameservers found for ${CYAN}${domain}{$RESET}" && return
-
-    for ns in $nameservers; do
-        ns=$(echo "$ns" | sed 's/\.$//')
-        ns_ip=$(host $ns | awk '/has (IPv6 )?address/ { print $NF }')
-
-        [ -z "$ns_ip" ] && echo "${GREY}No IP addresses found for nameserver ${PURPLE}${ns}${GREY} under ${CYAN}${domain}{RESET}" && continue
-
-        for ip in $ns_ip; do
-            perform_axfr "$domain" "$ns" "$ip"
-        done
-    done
-}
-
-[ $# -eq 0 ] && echo "Usage: $0 <domain> or <path_to_axfr_output>" && exit 1
-
-mkdir -p $output_dir
-
-if [ -f "$1" ]; then
-    root=$(grep -m1 '^; <<>> DiG' $1 | awk '{print $(NF-1)}') # Get the root domain from the dig output
-    domains=$(grep -a $'\t'IN$'\t'NS$'\t' "$1" | awk '{print $1}' | sort -u | sed 's/\.$//' | grep -v "^$root\.$") # Get the unique domains from the dig output (excluding the root domain)
-    
-    for domain in $domains; do
-        process_domain $domain
-    done
-else
-    process_domain $1
-fi
-\ No newline at end of file
diff --git a/mdaxfr b/mdaxfr
@@ -1,70 +1,156 @@
 #!/bin/sh
 # Mass DNS AXFR (POSIX version) - developed by acidvegas (https://git.acid.vegas/mdaxfr)
 
-# Define the current date for data organization
-now=$(date +"%Y-%m-%d")
+# Colors
+BLUE="\033[1;34m"
+CYAN="\033[1;36m"
+GREEN="\033[1;32m"
+GREY="\033[1;90m"
+PINK="\033[1;95m"
+PURPLE="\033[0;35m"
+RED="\033[1;31m"
+YELLOW="\033[1;33m"
+RESET="\033[0m"
 
-# Define the output directory
-output="axfrout/$now"
+# Set output directory
+output_dir="axfrout"
+mkdir -p $output_dir
 
-# Function to attempt an AXFR request on all possible IP addresses for a nameserver
-attempt_axfr() {
-    tld=$1
-    nameserver=$2
-    filename="$3"
 
-    temp_file="${filename}.temp"
-    nameserver_ips=$(dig +short A +retry=3 +time=10 $nameserver && dig +short AAAA +retry=3 +time=10 $nameserver)
+axfr() {
+    domain=$1
+    ns=$2
+    ip=$3
 
-    if [ -z "$nameserver_ips" ]; then
-        echo -e "\e[31m[FAIL]\e[0m AXFR for \e[36m$tld\e[0m on \e[33m$nameserver\e[0m \e[90m(failed to resolve nameserver)\e[0m"
-        return
+    echo "                ${YELLOW}Attempting AXFR for ${CYAN}${domain}${YELLOW} from ${PURPLE}${ns} ${GREY}(${ip})${RESET}"
+
+    axfr_output=$(dig +retry=3 +time=10 @$ip AXFR $domain)
+    axfr_status=$?
+
+    if [ $axfr_status -eq 0 ] && echo "$axfr_output" | grep -q "XFR size: "; then
+        echo "$axfr_output" > "${output_dir}/axfr-${domain}_${ns}_${ip}.txt"
+        size=$(echo "$axfr_output" | awk '/XFR size:/ {print $4}')
+        echo "                ${GREEN}Successful AXFR for ${CYAN}${domain}${GREEN} from ${PURPLE}${ns} ${GREY}(${ip}) ${GREEN}found ${size} records${RESET}"
+    else
+        echo "                ${RED}    Failed AXFR for ${CYAN}${domain}${RED} from ${PURPLE}${ns} ${GREY}(${ip})${RESET}"
     fi
+}
+
+
+process_domain() {
+    domain=$1
+
+    domain=$(echo "$domain" | sed -e 's|^\(https\?://\)\?||' -e 's|^www\.||' -e 's|/.*||')
+
+    echo "${PINK}Looking up nameservers for ${CYAN}${domain}${RESET}"
+
+    nameservers=$(dig +short +retry=3 +time=10 $domain NS | sed 's/\.$//')
+
+    [ -z "$nameservers" ] && echo "    ${GREY}No nameservers found for ${CYAN}${domain}${RESET}" && return
+
+    total_nameservers=$(echo "$nameservers" | wc -l)
+    echo "    ${BLUE}Found ${total_nameservers} nameservers for ${CYAN}${domain}${RESET}"
+
+    for ns in $nameservers; do
+        echo "        ${PINK}Looking up IP addresses for ${PURPLE}${ns}${RESET}"
+
+        ns_ip=$(dig +short +retry=3 +time=10 $ns A && dig +short +retry=3 +time=10 $ns AAAA)
+
+        [ -z "$ns_ip" ] && echo "            ${GREY}No IP addresses found on ${PURPLE}${ns}${GREY} for ${CYAN}${domain}${RESET}" && continue
+
+        total_ip=$(echo "$ns_ip" | wc -l)
+        echo "            ${BLUE}Found ${total_ip} IP addresses on ${PURPLE}${ns}${BLUE} for ${CYAN}${domain}${RESET}"
+
+        for ip in $ns_ip; do
+            axfr "$domain" "$ns" "$ip"
+        done
+
+        
+    done
+}
+
+
+read_axfr_out() {
+    axfr_output_file=$1
+
+    root=$(grep -m1 '^; <<>> DiG' $axfr_output_file | awk '{print $NF}')
+    domains=$(grep -aE "\s+IN\s+NS\s+" "$axfr_output_file" | grep -avE "^${root}\.\s+" | awk '{print $1}' | sort -u | sed 's/\.$//')
+
+    [ -z "$domains" ] && echo "${GREY}No domains found for ${root}${RESET}" && return
+ 
+    total_domains=$(echo "$domains" | wc -l)
+    echo "${BLUE}Found ${total_domains} domains for ${CYAN}${root}${BLUE} zone"
 
-    for nameserver_ip in $nameserver_ips; do
-        dig AXFR "$tld" "@$nameserver_ip" > "$temp_file"
-        if ! grep -q 'IN.*NS' "$temp_file"; then
-			echo -e "[\e[31mFAIL\e[0m] AXFR for \e[36m$tld\e[0m on \e[33m$nameserver\e[0m \e[90m($nameserver_ip)\e[0m"
-            rm -f "$temp_file"
-        else
-            mv "$temp_file" "$filename"
-            echo -e "[\e[32mSUCCESS\e[0m] AXFR for \e[36m$tld\e[0m on \e[33m$nameserver\e[0m \e[90m($nameserver_ip)\e[0m"
-            return
-        fi
+    for domain in $domains; do
+        process_domain $domain
     done
 }
 
-# Create the output directories (if they don't exist)
-mkdir -p "$output/root"
-mkdir -p "$output/psl"
-
-# Give a warning about the current state of AXFR requests
-echo "[\e[31mWARNING\e[0m] Most nameservers will block AXFR requests \e[90m(It is normal for most of these to fail)\e[0m" && sleep 3
-
-# For root nameservers
-for root in $(dig +short . NS | sed 's/\.$//'); do
-	attempt_axfr "." "$root" "$output/root/$root.txt"
-done
-
-# Parse the tld list from a root nameserver
-rndroot=$(find $output/root/*.root-servers.net.txt -type f | shuf -n 1)
-if [ -z $rndroot ]; then
-	echo "Failed to AXFR a root nameserver (using IANA list instead)"
-	tlds=$(curl -s 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt' | tail -n +2 | tr '[:upper:]' '[:lower:]')
-else 
-	tlds=$(cat $rndroot | grep -E 'IN\s+NS' | awk '{print $1}' | sed 's/\.$//' | sort -u)
-fi
-
-# For TLD nameservers
-for tld in $tlds; do
-	for ns in $(dig +short "$tld" NS | sed 's/\.$//'); do
-		attempt_axfr "$tld" "$ns" "$output/$tld.txt"
-	done
-done
-
-# For Public Suffix List TLD nameservers
-for tld in $(curl -s https://publicsuffix.org/list/public_suffix_list.dat | grep -vE '^(//|.*[*!])' | grep '\.' | awk '{print $1}'); do
-	for ns in $(dig +short "$tld" NS | sed 's/\.$//'); do
-		attempt_axfr "$tld" "$ns" "$output/psl/$tld.txt"
-	done
-done
+
+psl_crawl() {
+    psl=$(curl -s https://publicsuffix.org/list/public_suffix_list.dat | grep -vE '^(//|.*[*!])' | grep '\.' | awk '{print $1}')
+
+    [ -z "$psl" ] && echo "${RED}No PSL TLDs found${RESET}" && exit 1
+
+    total_psl=$(echo "$psl" | wc -l)
+    echo "${BLUE}Found ${total_psl} PSL TLDs${RESET}"
+
+    # Process the PSL TLDs
+    for tld in $psl; do
+        process_domain $tld
+    done
+}
+
+
+tld_crawl() {
+    process_domain "."
+
+    rndroot=$(find $output_dir/*.root-servers.net.txt -type f | shuf -n 1)
+
+    if [ -z $rndroot ]; then
+        echo "${GREY}No root nameserver found, using IANA TLD list${RESET}"
+        tlds=$(curl -s 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt' | tail -n +2 | tr '[:upper:]' '[:lower:]')
+    else 
+        tlds=$(cat $rndroot | grep -aE '\s+IN\s+NS\s+' | grep -avE "^\.\s+" | awk '{print $1}' | sed 's/\.$//' | sort -u)
+    fi
+
+    [ -z "$tlds" ] && echo "${RED}No TLDs found${RESET}" && exit 1
+
+    total_tld=$(echo "$tlds" | wc -l)
+    echo "${BLUE}Found ${total_tld} TLDs${RESET}"
+
+    # Process the TLDs
+    for tld in $tlds; do
+        process_domain $tld
+    done
+}
+
+
+
+if [ -t 0 ]; then
+    if [ $# -ne 1 0 ]; then
+        echo "Usage: $0 <option>"
+        echo ""
+        echo "Options:"
+        echo "      -tld : Perform AXFR on all TLDs"
+        echo "      -psl : Perform AXFR on all PSL TLDs"
+        echo "    <file> : Process AXFR output file (must be an AXFR output file from dig)"
+        echo "  <domain> : Perform AXFR on a single domain"
+        echo ""
+        echo "Standard Input:"
+        echo "  cat domain_list.txt | $0"
+        exit 1
+    elif [ $1 = '-tld' ]; then
+        tld_crawl
+    elif [ $1 = '-psl' ]; then
+        psl_crawl
+    elif [ -f $1 ]; then
+        read_axfr_out $1
+    else
+        process_domain $1
+    fi
+else
+    while IFS= read -r line; do
+        process_domain $line
+    done
+fi
+\ No newline at end of file