├── requirements.txt ├── subnuke.PNG ├── subnuke1.PNG ├── rebuild.sh ├── LICENSE ├── README.md ├── install.sh ├── subauto.sh ├── Dockerfile ├── single.sh ├── app.py └── templates ├── base.html ├── scan.html ├── home.html └── results.html /requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | itsdangerous==2.0.1 3 | -------------------------------------------------------------------------------- /subnuke.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethicalhackingplayground/SubNuke/HEAD/subnuke.PNG -------------------------------------------------------------------------------- /subnuke1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethicalhackingplayground/SubNuke/HEAD/subnuke1.PNG -------------------------------------------------------------------------------- /rebuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git pull ; docker build -t subnuke . ; docker stop subnuke ; docker run -d --rm -p 8080:5444 --name subnuke subnuke -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Krypt0mux 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SubNuke 2 | Subdomain Takeover tool with web UI 3 |
4 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 5 | 6 | # Install 7 | 8 | ```bash 9 | chmod +x install.sh ; ./install.sh 10 | ``` 11 | 12 | ```bash 13 | python3 app.py 14 | ``` 15 | 16 | # Tools used 17 | 18 | * Chaos 19 | * Subfinder 20 | * Crobat 21 | * dnsgen 22 | * metabigor 23 | * masscan 24 | * subtake 25 | 26 | # Features 27 | 28 | * File upload option to run scans against multiple. 29 | 30 | * Run scans against a single domain. 31 | 32 | # Contributors 33 | 34 | 35 | 36 | 37 | 38 | **Feel free to change the bash scripts to implement more recon techniques** 39 | 40 | ### Menu 41 | ![Img](subnuke.PNG) 42 | 43 | ### Scan 44 | ![Img](subnuke1.PNG) 45 | 46 | 47 | # Video 48 | [![(Watch Video)](https://i.imgur.com/8ya5vAs.png)](https://www.youtube.com/watch?v=pYewle2HcTw&ab_channel=krypt0muxbugbounty) 49 | 50 |
51 | Buy Me A Coffee 52 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #################################### 3 | # 4 | # Subdomain takeover tool installer 5 | # 6 | #################################### 7 | 8 | function install () { 9 | 10 | mkdir -p app 11 | cd app 12 | 13 | # Install some requirements 14 | sudo apt-get update && \ 15 | sudo apt-get install -y python3-pip && \ 16 | sudo apt-get install -y python3-dev && \ 17 | sudo apt-get install -y git && \ 18 | sudo apt-get install -y jq && \ 19 | sudo apt-get install -y wget && \ 20 | sudo apt-get install -y curl && \ 21 | sudo apt-get install -y unzip && \ 22 | sudo apt-get install -y git gcc make libpcap-dev && \ 23 | sudo apt-get install -y mariadb-server 24 | 25 | 26 | # Install all the tools 27 | git clone https://github.com/robertdavidgraham/masscan 28 | cd masscan; make -j ; cd .. 29 | git clone https://github.com/blechschmidt/massdns.git 30 | cd massdns ; make all ; cd .. 31 | 32 | wget https://github.com/tomnomnom/assetfinder/releases/download/v0.1.1/assetfinder-linux-amd64-0.1.1.tgz 33 | tar -xvf assetfinder-linux-amd64-0.1.1.tgz 34 | mv assetfinder /bin ; chmod +x /bin/assetfinder 35 | 36 | curl -LO https://github.com/findomain/findomain/releases/latest/download/findomain-linux-i386.zip 37 | unzip findomain-linux-i386.zip 38 | chmod +x findomain 39 | sudo mv findomain /usr/bin/findomain 40 | 41 | go install -v github.com/tomnomnom/anew@latest 42 | go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest 43 | go install -v github.com/cgboal/sonarsearch/crobat@latest 44 | git clone https://github.com/jakejarvis/subtake.git 45 | go install -v github.com/jakejarvis/subtake@latest 46 | go install -v github.com/OWASP/Amass/v3/...@master 47 | go install -v github.com/j3ssie/metabigor@maste 48 | 49 | 50 | # Install the requirments 51 | pip3 install -r $(pwd)/requirements.txt 52 | } 53 | 54 | install 55 | -------------------------------------------------------------------------------- /subauto.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | ######################### 4 | # 5 | # Subdomain takeover tool 6 | # 7 | ######################### 8 | 9 | # Clean up 10 | rm hosts.txt; 11 | rm domains.txt; 12 | rm tests.txt 13 | rm done.txt 14 | rm takeovers 15 | rm links 16 | rm asn_list 17 | rm ranges.txt 18 | rm masscan.txt 19 | rm orgs.txt 20 | 21 | # Get all chaos domains 22 | curl https://raw.githubusercontent.com/projectdiscovery/public-bugbounty-programs/master/chaos-bugbounty-list.json |jq -r '.programs[] | .domains' |sort -u |cut -d '"' -f2 |while read chaos ; do echo $chaos | tee -a hosts.txt ; done 23 | 24 | # Get all chaos domains 25 | curl https://raw.githubusercontent.com/projectdiscovery/public-bugbounty-programs/master/chaos-bugbounty-list.json |jq -r '.programs[] | .domains' |sort -u |cut -d '"' -f2 |while read chaos; do subfinder -d $chaos -silent | tee -a domains.txt ; done 26 | 27 | # Get all chaos files 28 | org=$(cat hosts.txt | rev | cut -d '.' -f 2 | rev | tee -a orgs.txt) 29 | cat orgs.txt | wget https://chaos-data.projectdiscovery.io/$org.zip -O chaos_domains/$org.zip 30 | find "chaos_domains" -name "*.zip" | xargs -I@ bash -c '{ cat @ | tee -a domains.txt ; }' 31 | 32 | # Get the subdomains from the Rapid7 DNS DB 33 | cat hosts.txt | xargs -I @ -P 10 bash -c '{ crobat -s "@" | tee -a domains.txt ; }' 34 | 35 | # Use amass to find subdomains 36 | amass enum -passive -df hosts.txt | anew domains.txt 37 | 38 | # Use amass to do an active subdomain enumeration 39 | amass enum -active -df hosts.tx | anew domains.txt 40 | 41 | # DNS GEN Scan 42 | cat domains.txt | dnsgen - | tee -a domains.txt 43 | 44 | # Get ASN's 45 | cat hosts.txt | rev | cut -d '.' -f 2 | rev | tee -a orgs.txt 46 | for org in `cat orgs.txt`; do amass intel -org $org | awk '{print $1}' | sed 's/\,$//' | tee -a asn_list ; done 47 | cat asn_list | metabigor net --asn -o ranges.txt 48 | 49 | # Use masscan to get IP's 50 | masscan -iL ranges.txt --max-rate 100000 -p80,443 -oL masscan.txt 51 | cat masscan.txt | awk '{print $4}' | tee -a domains.txt 52 | 53 | 54 | # Run the subdomain takeovers all across the subdomains 55 | cat domains.txt | sort -u | tee -a tests.txt 56 | subtake -c subtake/fingerprints.json -f tests.txt -ssl -o takeovers 57 | cat takeovers | awk '{print $3}' | tee -a links 58 | 59 | touch done.txt 60 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | # Install some requirements 4 | RUN apt-get update && \ 5 | apt-get install -y python3-pip && \ 6 | apt-get install -y python3-dev && \ 7 | apt-get install -y git && \ 8 | apt-get install -y jq && \ 9 | apt-get install -y wget && \ 10 | apt-get install -y snapd && \ 11 | apt-get install -y curl && \ 12 | apt-get install -y unzip && \ 13 | apt-get install -y git gcc make libpcap-dev sudo 14 | 15 | # The working directory where the app will live. 16 | WORKDIR /app 17 | 18 | # Copy contents into the app working directory 19 | COPY . /app 20 | 21 | # Install all the tools 22 | RUN wget https://dl.google.com/go/go1.19.6.linux-amd64.tar.gz 23 | RUN tar -xvf go1.19.6.linux-amd64.tar.gz 24 | RUN sudo mv go /usr/local 25 | ENV GOROOT=/usr/local/go 26 | ENV GOPATH=$HOME/go 27 | ENV PATH=$GOPATH/bin:$GOROOT/bin:$PATH 28 | 29 | # Install all the tools 30 | RUN git clone https://github.com/robertdavidgraham/masscan 31 | RUN cd masscan; make -j ; cd .. 32 | RUN git clone https://github.com/blechschmidt/massdns.git 33 | RUN cd massdns ; make all ; cd .. 34 | 35 | RUN wget https://github.com/tomnomnom/assetfinder/releases/download/v0.1.1/assetfinder-linux-amd64-0.1.1.tgz 36 | RUN tar -xvf assetfinder-linux-amd64-0.1.1.tgz 37 | RUN mv assetfinder /bin ; chmod +x /bin/assetfinder 38 | 39 | RUN curl -LO https://github.com/findomain/findomain/releases/latest/download/findomain-linux-i386.zip 40 | RUN unzip findomain-linux-i386.zip 41 | RUN chmod +x findomain 42 | RUN sudo mv findomain /usr/bin/findomain 43 | 44 | RUN go install -v github.com/tomnomnom/anew@latest 45 | RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest 46 | RUN git clone https://github.com/jakejarvis/subtake.git 47 | RUN go install -v github.com/jakejarvis/subtake@latest 48 | RUN go install -v github.com/OWASP/Amass/v3/...@master 49 | RUN go install -v github.com/j3ssie/metabigor@maste 50 | 51 | 52 | # Install the requirments 53 | RUN pip3 install -r $(pwd)/requirements.txt 54 | 55 | # Declare environment variables 56 | ENV FLASK_APP="app.py" 57 | ENV FLASK_ENV=production 58 | 59 | # Run Web app 60 | CMD ["python3", "app.py"] 61 | 62 | # Expose the port that Flask is running on 63 | EXPOSE 5444/tcp -------------------------------------------------------------------------------- /single.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | ######################### 4 | # 5 | # Subdomain takeover tool 6 | # 7 | ######################### 8 | 9 | # Clean up 10 | rm hosts.txt; 11 | rm domains.txt; 12 | rm tests.txt 13 | rm takeovers 14 | rm done.txt 15 | rm links 16 | rm asn_list 17 | rm ranges.txt 18 | rm masscan.txt 19 | 20 | mkdir -p chaos_domains 21 | 22 | # The single domain 23 | DOMAIN=$1 24 | if [[ -z "$DOMAIN" ]] ; then 25 | echo "Usage: $0 " 26 | exit 1; 27 | fi 28 | 29 | 30 | # Get all chaos domains 31 | curl https://raw.githubusercontent.com/projectdiscovery/public-bugbounty-programs/master/chaos-bugbounty-list.json |jq -r '.programs[] | .domains' |sort -u |cut -d '"' -f2 |while read chaos; do echo $chaos | grep -i "$DOMAIN" | tee -a domains.txt ; done 32 | 33 | # Get all chaos files 34 | org=$(echo $DOMAIN | rev | cut -d '.' -f 2 | rev) 35 | wget https://chaos-data.projectdiscovery.io/$org.zip -O chaos_domains/$org.zip 36 | cd chaos_domains; unzip $org.zip ; cd ../ 37 | find "chaos_domains" -name "*.txt" | xargs -I@ bash -c '{ cat @ | tee -a domains.txt ; }' 38 | 39 | # Use Subfinder to find subdomains 40 | subfinder -d $DOMAIN -silent -all | anew domains.txt 41 | 42 | # Use amass to find subdomains 43 | amass enum -passive -d $DOMAIN | anew domains.txt 44 | 45 | # Use amass to do an active subdomain enumeration 46 | amass enum -active -d $DOMAIN | anew domains.txt 47 | 48 | # findomain 49 | findomain --output --quiet --target $DOMAIN 50 | cat $DOMAIN.txt | anew domains.txt 51 | 52 | # DNS GEN Scan 53 | cat domains.txt | dnsgen - | anew domains.txt 54 | 55 | # Use crobat to get subdomains from rapid7 56 | #crobat -s $DOMAIN | tee -a domains.txt 57 | #cat domains.txt | xargs -I@ bash -c '{ crobat -s "@" | anew domains.txt ; }' 58 | 59 | # Get ASN's 60 | 61 | amass intel -org $org | awk '{print $1}' | sed 's/\,$//' | anew asn_list 62 | cat asn_list | metabigor net --asn -o ranges.txt 63 | 64 | # Use masscan to get IP's 65 | masscan -iL ranges.txt --max-rate 100000 -p80,443 -oL masscan.txt 66 | cat masscan.txt | awk '{print $4}' | tee -a domains.txt 67 | 68 | 69 | # Run the subdomain takeovers all across the subdomains 70 | cat domains.txt | sort -u | tee -a tests.txt 71 | subtake -c subtake/fingerprints.json -f tests.txt -ssl -o takeovers 72 | cat takeovers | awk '{print $3}' | tee -a links 73 | 74 | touch done.txt 75 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # encoding: utf-8 3 | from flask import Flask 4 | from flask import render_template, redirect, url_for, request 5 | from threading import Thread 6 | import subprocess,os 7 | 8 | 9 | 10 | # Initialise the flask application 11 | app = Flask(__name__) 12 | 13 | 14 | # Index route 15 | @app.route("/", methods=['GET','POST']) 16 | def index(): 17 | if request.method == 'POST': 18 | if "scan" in request.form: 19 | # Threaded mass scan 20 | run_mass_scan() 21 | return redirect(url_for('massscan')) 22 | 23 | if "domain" in request.form: 24 | # Threaded single scan 25 | domain = request.form.get('domain') 26 | run_single_scan(domain) 27 | return redirect(url_for('singlescan', domain=domain)) 28 | return render_template('home.html') 29 | 30 | # Do a mass scan on all subdomain 31 | def run_mass_scan(): 32 | thr = Thread(target=run_async_mass_scan, args=[]) 33 | thr.start() 34 | return thr 35 | 36 | # Run a mass async scan 37 | def run_async_mass_scan(): 38 | process = subprocess.Popen(['bash', 'subauto.sh', '&>/dev/null', '&']) 39 | process.communicate() 40 | 41 | 42 | # Do a single scan 43 | def run_single_scan(domain): 44 | thr = Thread(target=run_async_single_scan, args=[domain]) 45 | thr.start() 46 | return thr 47 | 48 | 49 | # Run a single async scan 50 | def run_async_single_scan(domain): 51 | process = subprocess.Popen(['bash', 'single.sh', domain, '&>/dev/null', '&']) 52 | process.communicate() 53 | 54 | 55 | 56 | # Start the scan. 57 | @app.route('/mass-scan') 58 | def massscan(): 59 | try: 60 | if os.path.isfile('domains.txt'): 61 | if os.path.isfile("done.txt"): 62 | return redirect(url_for('results')) 63 | if os.path.isfile("takeovers"): 64 | return redirect(url_for('results')) 65 | else: 66 | f=open('domains.txt','r+', encoding="utf-8") 67 | content=f.readlines() 68 | return render_template('scan.html', len = len(content), domain="") 69 | else: 70 | return render_template('scan.html', len = 0, domain="") 71 | except TypeError: 72 | return render_template('scan.html', len = 0, domain="") 73 | 74 | # Start the single scan. 75 | @app.route('/single-scan/') 76 | def singlescan(domain): 77 | try: 78 | if os.path.isfile('domains.txt'): 79 | if os.path.isfile("done.txt"): 80 | return redirect(url_for('results')) 81 | if os.path.isfile("takeovers"): 82 | return redirect(url_for('results')) 83 | else: 84 | f=open('domains.txt','r+', encoding="utf-8") 85 | content=f.readlines() 86 | return render_template('scan.html', len = len(content), domain=domain) 87 | else: 88 | return render_template('scan.html', len = 0, domain=domain) 89 | except TypeError: 90 | return render_template('scan.html', len = 0, domain=domain) 91 | 92 | # Display the results 93 | @app.route('/results') 94 | def results (): 95 | # Check to see if the session is mine 96 | if os.path.isfile("takeovers"): 97 | if os.path.isfile("links"): 98 | f1=open('takeovers', 'r') 99 | content=f1.readlines() 100 | f3=open('links', 'r') 101 | links=f3.readlines() 102 | return render_template('results.html', len = len(content), domains=len(content), content=content, links=links) 103 | else: 104 | return render_template('results.html', len = 0, domains=0, content="Still Proccessing...", links="") 105 | else: 106 | return render_template('results.html', len = 0, domains=0, content="No Subdomain Takeovers Found", links="") 107 | # Run the application 108 | if __name__ == '__main__': 109 | app.run(host='0.0.0.0', debug=False, port=5444) 110 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 14 | 15 | SubNuke 16 | 17 | 18 | 19 | 20 | 21 | 151 | 152 | 153 | 154 |
155 |
156 |
157 | 175 |
176 | 177 | 178 | 179 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /templates/scan.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 15 | 16 | SubNuke 17 | 18 | 19 | 20 | 21 | 22 | 177 | 178 | 179 | 180 |
181 |
182 |
183 | 210 |
211 | 212 | 213 | 214 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 14 | 15 | 18 | 19 | 20 | SubNuke 21 | 22 | 23 | 24 | 25 | 26 | 27 | 163 | 164 | 165 | 166 |
167 |
168 |
169 | 214 |
215 | 216 | 217 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /templates/results.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | SubNuke 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 190 | 191 | 192 | 193 |
194 |
195 |
196 | 226 |
227 | 228 | 229 | 232 | 233 | 234 | --------------------------------------------------------------------------------