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

This commit is contained in:
Dionysus 2024-03-10 18:04:01 -04:00
parent 4c8ac71c62
commit ecbd8139f4
Signed by: acidvegas
GPG Key ID: EF4B922DB85DC9DE
5 changed files with 171 additions and 131 deletions

BIN
.screens/preview_ripe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
.screens/preview_root.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -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...
___

View File

@ -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

192
mdaxfr
View File

@ -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
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
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
read_axfr_out() {
axfr_output_file=$1
# For root nameservers
for root in $(dig +short . NS | sed 's/\.$//'); do
attempt_axfr "." "$root" "$output/root/$root.txt"
done
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/\.$//')
# 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:]')
[ -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 domain in $domains; do
process_domain $domain
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
tlds=$(cat $rndroot | grep -E 'IN\s+NS' | awk '{print $1}' | sed 's/\.$//' | sort -u)
while IFS= read -r line; do
process_domain $line
done
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