Files
th-analyzer/engine/discovery.sh
drjones e832ef3b46 v2: real exploitation — discovery phase, nuclei CVE scanning, SQLi/XSS/LFI rebuild
- New discovery engine (engine/discovery.sh): crawls target for real
  URLs, forms, parameters, and API endpoints before attacking
- New nuclei vector (21): runs nuclei templates for real CVE detection
  (critical/high/medium severity)
- Rebuilt SQLi vector: tests discovered forms and URL params with
  error-based and time-based blind payloads, sqlmap injection
- Rebuilt XSS vector: multi-context payloads against discovered
  forms/params, confirms payload reflection
- Rebuilt LFI vector: tests all discovered and common file parameters
  with traversal payloads, confirms by reading /etc/passwd
- Updated main analyzer with 5-step pipeline: connectivity →
  discovery → recon → Ollama brain → exploitation
2026-06-19 06:27:33 -07:00

200 lines
6.5 KiB
Bash

#!/usr/bin/env bash
# The Analyzer v2 — Discovery Engine
# Finds actual URLs, forms, parameters, and endpoints on the target
# This feeds the exploit vectors with real attack surface
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/utils.sh"
discover_target() {
local target="$1"
local domain=$(get_domain "$target")
local base=$(get_base "$target")
local outfile="$REPORTS_DIR/.${domain}_discovery.txt"
print_info "Discovering attack surface on $target..."
separator
local DISCOVERED_URLS=""
local DISCOVERED_FORMS=""
local DISCOVERED_PARAMS=""
local DISCOVERED_ENDPOINTS=""
# 1. Crawl the homepage for links and forms
print_sub "Crawling homepage for links..."
local page=$(curl -s --connect-timeout 10 --max-time 20 -L "$target" 2>/dev/null)
if [ -z "$page" ]; then
print_error "Cannot fetch target page"
return 1
fi
# Extract all internal links
local links=$(echo "$page" | perl -nle 'while (/href="([^"]+)"/g) { print $1 }' | sort -u)
local internal_links=""
while IFS= read -r link; do
[ -z "$link" ] && continue
# Make absolute
if [[ "$link" == /* ]]; then
link="${base}${link}"
elif [[ "$link" == http* ]]; then
# External link — skip unless same domain
local link_domain=$(echo "$link" | sed 's|https\?://||' | cut -d/ -f1)
[[ "$link_domain" != "$domain" ]] && continue
else
link="${base}/${link}"
fi
internal_links+="$link\n"
DISCOVERED_URLS+="$link\n"
done <<< "$links"
local url_count=$(echo -e "$DISCOVERED_URLS" | grep -c .)
print_ok "Found $url_count internal URLs"
# 2. Extract forms
print_sub "Extracting forms..."
local forms=$(echo "$page" | perl -0 -nle 'while (/<form[^>]*>.*?<\/form>/gs) { print $& }')
local form_count=0
while IFS= read -r form; do
[ -z "$form" ] && continue
form_count=$((form_count + 1))
local form_action=$(echo "$form" | perl -nle 'print $1 if /action="([^"]*)"/')
local form_method=$(echo "$form" | perl -nle 'print $1 if /method="([^"]*)"/' | tr '[:upper:]' '[:lower:]')
local form_inputs=$(echo "$form" | perl -nle 'print $1 while /name="([^"]*)"/g')
# Make action URL absolute
if [[ "$form_action" == / ]]; then
form_action="$base/"
elif [[ "$form_action" == /* ]]; then
form_action="${base}${form_action}"
elif [[ "$form_action" == http* ]] && ! echo "$form_action" | grep -qi "$domain"; then
continue # skip external forms
elif [ -z "$form_action" ]; then
form_action="$target" # submits to current page
fi
DISCOVERED_FORMS+="$form_count|$form_method|$form_action|$form_inputs\n"
DISCOVERED_URLS+="$form_action\n"
DISCOVERED_PARAMS+="$form_inputs\n"
print_info "Form #$form_count: [$form_method] $form_action -> params: $form_inputs"
done <<< "$forms"
print_ok "Found $form_count form(s)"
# 3. Extract URL parameters from existing links
print_sub "Finding URL parameters..."
local url_params=$(echo -e "$DISCOVERED_URLS" | perl -nle 'while (/[?&]([^=]+)=/g) { print $1 }' | sort -u)
while IFS= read -r p; do
[ -z "$p" ] && continue
DISCOVERED_PARAMS+="$p\n"
done <<< "$url_params"
local param_count=$(echo -e "$DISCOVERED_PARAMS" | grep -c .)
print_ok "Found $param_count parameter(s): $(echo -e "$DISCOVERED_PARAMS" | tr '\n' ' ')"
# 4. Check common API paths
print_sub "Probing API endpoints..."
local api_paths=(
"/api" "/api/v1" "/api/v2" "/v1" "/v2"
"/graphql" "/graph" "/gql"
"/rest" "/swagger" "/openapi" "/docs"
"/api/docs" "/api/swagger" "/api/openapi"
)
for path in "${api_paths[@]}"; do
local code=$(http_check "${base}${path}")
if [[ "$code" =~ ^[23] ]]; then
DISCOVERED_ENDPOINTS+="${base}${path} (HTTP $code)\n"
print_info "API: ${base}${path} (HTTP $code)"
fi
done
# 5. Check for JS files that might leak endpoints
print_sub "Scanning JS for endpoint leaks..."
local js_urls=$(echo "$page" | perl -nle 'print $1 while /src="([^"]*\.js[^"]*)"/g' | head -10)
while IFS= read -r js; do
[ -z "$js" ] && continue
[[ "$js" == /* ]] && js="${base}${js}"
[[ "$js" != http* ]] && continue
local js_content=$(curl -s --connect-timeout 5 --max-time 10 "$js" 2>/dev/null)
local leaked_endpoints=$(echo "$js_content" | perl -nle 'print $1 while m|["\x27](/api/[^"\x27]+)["\x27]|g' | sort -u | head -10)
if [ -n "$leaked_endpoints" ]; then
print_info "JS leak: $js"
while IFS= read -r ep; do
[ -z "$ep" ] && continue
DISCOVERED_ENDPOINTS+="${base}${ep} (JS leak)\n"
print_find " Leaked endpoint: ${ep}"
done <<< "$leaked_endpoints"
fi
done <<< "$js_urls"
# 6. Save everything to a discovery file
cat > "$outfile" << EOF
TARGET=$target
DOMAIN=$domain
BASE=$base
URLS:
$(echo -e "$DISCOVERED_URLS" | sort -u | grep -v '^$')
FORMS:
$(echo -e "$DISCOVERED_FORMS" | sort -u | grep -v '^$')
PARAMS:
$(echo -e "$DISCOVERED_PARAMS" | sort -u | grep -v '^$')
ENDPOINTS:
$(echo -e "$DISCOVERED_ENDPOINTS" | sort -u | grep -v '^$')
EOF
print_ok "Discovery complete. Saved to $(basename $outfile)"
separator
# Summary
local total_urls=$(echo -e "$DISCOVERED_URLS" | grep -c .)
local total_forms=$(echo -e "$DISCOVERED_FORMS" | grep -c .)
local total_params=$(echo -e "$DISCOVERED_PARAMS" | grep -c .)
local total_eps=$(echo -e "$DISCOVERED_ENDPOINTS" | grep -c .)
echo ""
echo -e " ${BOLD}Discovery Summary:${NC}"
echo -e " ${CYAN}URLs:${NC} $total_urls"
echo -e " ${CYAN}Forms:${NC} $total_forms"
echo -e " ${CYAN}Params:${NC} $total_params"
echo -e " ${CYAN}Endpoints:${NC} $total_eps"
return 0
}
# Get discovered data for a target
get_discovered_urls() {
local domain="$1"
local file="$REPORTS_DIR/.${domain}_discovery.txt"
if [ -f "$file" ]; then
sed -n '/^URLS:/,/^FORMS:/p' "$file" | grep -v "^URLS:\|^FORMS:\|^\$"
fi
}
get_discovered_forms() {
local domain="$1"
local file="$REPORTS_DIR/.${domain}_discovery.txt"
if [ -f "$file" ]; then
sed -n '/^FORMS:/,/^PARAMS:/p' "$file" | grep -v "^FORMS:\|^PARAMS:\|^\$"
fi
}
get_discovered_params() {
local domain="$1"
local file="$REPORTS_DIR/.${domain}_discovery.txt"
if [ -f "$file" ]; then
sed -n '/^PARAMS:/,/^ENDPOINTS:/p' "$file" | grep -v "^PARAMS:\|^ENDPOINTS:\|^\$"
fi
}
get_discovered_endpoints() {
local domain="$1"
local file="$REPORTS_DIR/.${domain}_discovery.txt"
if [ -f "$file" ]; then
sed -n '/^ENDPOINTS:/,$p' "$file" | grep -v "^ENDPOINTS:\|^\$"
fi
}