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

    Samueleex interessante, di fatto si tratta di web-scraping analogo al software Screaming Frog, quasi indispensabile in ambito SEO, diciamo questo:

    • questo script permette di trovare i sottodomini partendo da un dominio
    • Screaming Frog può analizzare tutti i sottodomini e/o directory (a seconda delle impostazioni) partendo da un dominio (limite di 500 URL per la versione free), mostrando poi varie info (i vari meta tag, status code ecc, tutte informazioni utili in ambito SEO, per una panoramica generale del sito web); per come è strutturato, si presta meglio a studiare un singolo sottodominio, quindi le directory all'interno del sottodominio (il crawler poi si muove attraverso i link in modo abbastanza "random" e ricordiamo il limite di 500 URL per la versione free)

    Per un'analisi approfondita, può essere interessante anche combinare i due tool, dato che presentano vantaggi differenti. Ad esempio Screaming Frog viene bloccato da freeflarum.com (status code 403).

    Powered by: FreeFlarum.
    (remove this footer)