Oggi vedremo uno script bash che ci permette di analizzare i sottodomini di un webserver tramite diverse utility:
Struttura del codice:
- /path/to/script/
- subdomain_finder.sh # bash
- requirements.txt # requisiti Python
- install_tools.sh # servizi richiesti
- recon.log # log (creato dallo script)
- domains.txt # (opzionale) lista di domini
Il codice inizia definendo diversi colori per il terminale, subito dopo definiamo la funzione display_usage
che restituisce le istruzioni su come usare lo script compreso un esempio di comando (questa funzione viene richiamata tramite -h o --help).
Definiamo una funzione di log che ci permette di salvarlo tramite timestamp.
Viene installato figlet tramite apt-get, tool opzionale utilizzato per generare il banner dello script.
Quando richiamiamo il tool da terminale i comandi vengono riconosciuti tramite parsing degli argomenti quindi analizza gli argomenti: della riga di comando per determinare il dominio (-d o --domain), il file della lista di domini (-dL o --domain-list) e la directory di output (-o o --output).
Se il comando inserito non è corretto o il dominio non viene inserito in maniera corretta restituisce un errore e il messaggio di utilizzo (idem se non viene trovata nessuna lista di domini).
Poi viene scritta la logica per salvare la cartella di output, se viene specificata lo script la crea e cambia la directory corrente in quella directory.
Viene creata la funzione run_recon
che avvia l'enumerazione dei sottodomini tramite i servizi specificati in precedenza (Assetfinder, Subfinder, Sublist3r, Chaos, Crtsh, Crobat, Findomain, Knockpy, Amass). I risultati di ciascun tool vengono salvati in file separati e poi combinati in un unico file di sottodomini unici, questi file temporanei vengono poi rimossi.
Se abbiamo configurato correttamente il codice per Telegram e Discord, dopo aver completato l'enumerazione invia una notifica a un webhook Discord e a un bot Telegram (con timestamp).
#!/bin/bash
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
BLUE=$(tput setaf 4)
YELLOW=$(tput setaf 3)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
RESET=$(tput sgr0)
display_usage() {
echo "${YELLOW}Subdomain Finder di Samueleex${RESET}"
echo
echo "Uso: $0 [opzioni]"
echo
echo "Opzioni:"
echo " -h, --help Dove ti trovi ora"
echo " -d, --domain <nome> Specifica un dominio"
echo " -dL, --domain-list Specifica un file con una lista di domini"
echo " -o, --output <directory> Specifica la directory di output"
echo
echo "Esempio: $0 -d example.com -o /home/user/Desktop"
exit 1
}
log() {
local log_file="recon.log"
local timestamp=$(date +"%Y-%m-%d %T")
echo "[$timestamp] $1" >> "$log_file"
echo -e "$2$1${RESET}"
}
if ! command -v figlet &> /dev/null; then
echo "Figlet non presente. Installazione..."
sudo apt-get update
sudo apt-get install -y figlet
fi
color_code="\033[31m"
reset_color="\033[0m"
figlet_text=$(figlet "Sub finder")
colored_text="${color_code}${figlet_text}${reset_color}"
echo -e "$colored_text"
output_file=""
domain=""
domain_list=""
output_dir=""
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-h|--help)
display_usage
;;
-d|--domain)
domain="$2"
shift
;;
-dL|--domain-list)
domain_list="$2"
shift
;;
-o|--output)
output_dir="$2"
shift
;;
*)
echo -e "${RED}Opzione sconosciuta: $1${RESET}"
display_usage
;;
esac
shift
done
set -e
if [ -z "$domain" ] && [ -z "$domain_list" ]; then
log "For bash practice and fun!" "$RED"
display_usage
fi
if [ -n "$domain_list" ]; then
domain_list="$(realpath "$domain_list")"
if [ ! -f "$domain_list" ]; then
log "Errore: file della lista dei domini non trovato: $domain_list" "$RED"
exit 1
fi
fi
if [ -n "$output_dir" ]; then
mkdir -p "$output_dir" || { log "Errore: impossibile creare la directory di output: $output_dir" "$RED"; exit 1; }
cd "$output_dir" || { log "Errore: impossibile cambiare directory a: $output_dir" "$RED"; exit 1; }
fi
run_recon() {
local current_domain="$1"
log "Inizio enumerazione per: $current_domain" "$WHITE"
local domain_output_dir="$current_domain"
mkdir -p "$domain_output_dir"
cd "$domain_output_dir" || { log "Errore cambiando directory: $domain_output_dir" "$RED"; exit 1; }
tools=("Assetfinder" "Subfinder" "Sublist3r" "Chaos" "Crtsh" "Crobat" "Findomain" "Knockpy" "Amass")
for tool in "${tools[@]}"; do
echo "Esecuzione di $tool per $current_domain..."
log "Esecuzione di $tool per $current_domain" "$BLUE"
case $tool in
"Assetfinder")
assetfinder "$current_domain" > assetfinder_Tool.txt 2>/dev/null || true
;;
"Subfinder")
subfinder -d "$current_domain" > subfinder_Tool.txt 2>/dev/null || true
;;
"Sublist3r")
sublist3r -d "$current_domain" -o sublist3r_Tool.txt > /dev/null 2>&1 || true
;;
"Chaos")
chaos -d "$current_domain" -silent -key 3c8d87ff-efad-43a4-ab80-a4a3aa528e73 -o chaos_Tool.txt > /dev/null 2>&1 || true
;;
"Crtsh")
curl -s "https://crt.sh/?q=%.$current_domain" | sed 's/<[^>]*>//g' | grep -Eo "[a-zA-Z0-9._-]+\.$current_domain" | sed '/^$/d' > crtsh_Tool.txt
;;
"Crobat")
crobat -s "$current_domain" -o crobat_Tool.txt 2>/dev/null || true
;;
"Findomain")
findomain -t "$current_domain" -u findomain_Tool.txt > /dev/null 2>&1 || true
;;
"Knockpy")
knockpy.py -d "$current_domain" > knockpy_Tool.txt 2>/dev/null || true
;;
"Amass")
amass enum -passive -d "$current_domain" > amass_Tool.txt 2>/dev/null || true
;;
esac
done
cat *_Tool.txt | sort -u > $current_domain-subdomains.txt
rm *_Tool.txt
if ls *.json >/dev/null 2>&1; then
rm *.json
echo "Tutti i file .json sono stati rimossi dalla directory."
fi
if [ -z "$output_dir" ]; then
echo -e "${WHITE}Fatto! Risultati in: $current_domain${RESET}"
log "Fatto! Risultati in: $current_domain" "$BLUE"
else
echo -e "${WHITE}Fatto! Risultati in: $output_dir${RESET}"
log "Fatto! Risultati in: $output_dir" "$BLUE"
fi
cd .. || { log "Errore cambiando directory: $output_dir" "$RED"; exit 1; }
}
if [ -n "$domain" ]; then
run_recon "$domain"
fi
if [ -n "$domain_list" ]; then
while IFS= read -r line; do
run_recon "$line"
done < "$domain_list"
rm -f *_Tool.txt
if ls *.json >/dev/null 2>&1; then
rm *.json
echo "Tutti i file .json sono stati rimossi."
fi
fi
current_datetime=$(date +"%Y-%m-%d %H:%M:%S")
message="Azione per $current_domain completata il $current_datetime"
webhook_url="WEBHOOK_URL"
response=$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d "{\"content\":\"$message\"}" "$webhook_url" 2>/dev/null)
if [[ $response == "200" || $response == "204" ]]; then
echo "Notifica inviata a Discord per $current_domain."
else
echo "Notifica non inviata, errore $response"
fi
telegram_token="token"
chat_id="id"
telegram_response=$(curl -s -X POST "https://api.telegram.org/bot$telegram_token/sendMessage" -d "chat_id=$chat_id" -d "text=$message")
if [[ $telegram_response =~ "\"ok\":true" ]]; then
echo "Notifica Telegram inviata per $current_domain"
else
echo "Messaggio non inviato, errore $telegram_response"
fi

Requisiti
install_tools.sh
#!/bin/bash
command_exists() {
command -v "$1" &> /dev/null
}
if command_exists go; then
go install github.com/tomnomnom/assetfinder@latest
go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
go install github.com/projectdiscovery/chaos-client/cmd/chaos@latest
go install github.com/cgboal/sonarsearch/crobat@latest
else
echo "Go non installato. Installare Go prima di procedere."
exit 1
fi
if ! command_exists findomain; then
wget https://github.com/Findomain/Findomain/releases/latest/download/findomain-linux
chmod +x findomain-linux
sudo mv findomain-linux /usr/local/bin/findomain
else
echo "Findomain già installato."
fi
if ! command_exists amass; then
sudo apt-get update
sudo apt-get install -y amass
else
echo "Amass già installato."
fi
requirements.txt
sublist3r
knockpy