The Analyzer v1.0 — autonomous bug bounty engine with 20 attack vectors and Ollama brain

This commit is contained in:
drjones
2026-06-19 06:11:40 -07:00
commit eb1fad4ecc
28 changed files with 2501 additions and 0 deletions

135
engine/ollama-brain.sh Executable file
View File

@@ -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. <vector_number>: <reason>
2. <vector_number>: <reason>
## SUMMARY
<brief strategy 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"
}

121
engine/recon.sh Executable file
View File

@@ -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 '<form\|<input.*type="\(text\|password\|email\|search\)"\|method="\(get\|post\)"'; then
RECON_DATA+="Has Forms: true\n"
print_info "Forms detected on page"
fi
# Detect login
if echo "$page_content" | grep -qi 'login\|signin\|password\|type="password"'; then
RECON_DATA+="Has Login: true\n"
print_info "Login form detected"
fi
# Detect search
if echo "$page_content" | grep -qi 'search\|type="search"\|name="q"\|\bapi\b'; then
RECON_DATA+="Has Search: true\n"
print_info "Search functionality detected"
fi
# Detect file upload
if echo "$page_content" | grep -qi 'type="file"\|multipart/form-data\|upload'; then
RECON_DATA+="Has File Upload: true\n"
print_info "File upload detected"
fi
# Detect JS frameworks / SPAs
if echo "$page_content" | grep -qi 'react\|vue\|angular\|next.js\|nuxt'; then
RECON_DATA+="SPA Framework: true\n"
print_info "SPA framework detected"
fi
# Detect API endpoints
if echo "$page_content" | grep -qi 'api\.\|/v1/\|/v2/\|/api/\|graphql\|rest\|endpoint'; then
RECON_DATA+="Has API References: true\n"
print_info "API references found in page"
fi
# Detect JWT
if echo "$page_content" | grep -qi 'eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*'; then
RECON_DATA+="JWT Tokens Found: true\n"
print_find "JWT tokens detected in page!"
fi
# Save recon data for the brain
echo "$RECON_DATA" > "$REPORTS_DIR/.${domain}_recon.txt"
print_ok "Recon complete for $domain"
return 0
}

242
engine/reporter.sh Executable file
View File

@@ -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+="<div class=\"finding\" style=\"background:#1e293b;border-radius:8px;padding:16px;margin-bottom:12px;${border_color}\">"
findings_html+="<div class=\"finding-header\" style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;\">"
findings_html+="<h3 style=\"margin:0;color:#f1f5f9;font-size:16px;\">${finding_num}. ${finding_title}</h3>"
findings_html+="<span class=\"badge\" style=\"background:${badge_bg};color:#fff;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:bold;\">${finding_sev//\*/}</span>"
findings_html+="</div>"
[ -n "$finding_detail" ] && findings_html+="<p style=\"color:#94a3b8;font-size:14px;margin:4px 0;\">${finding_detail}</p>"
[ -n "$finding_evidence" ] && findings_html+="<div style=\"background:#0f172a;padding:8px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#22d3ee;margin:8px 0;word-break:break-all;\">${finding_evidence}</div>"
[ -n "$finding_exploit" ] && findings_html+="<div style=\"background:#0f172a;padding:8px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#fbbf24;margin:8px 0;\"><strong style=\"color:#f59e0b;\">Exploit:</strong> ${finding_exploit}</div>"
findings_html+="</div>"
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+="<div class=\"finding\" style=\"background:#1e293b;border-radius:8px;padding:16px;margin-bottom:12px;${border_color}\">"
findings_html+="<div class=\"finding-header\" style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;\">"
findings_html+="<h3 style=\"margin:0;color:#f1f5f9;font-size:16px;\">${finding_num}. ${finding_title}</h3>"
findings_html+="<span class=\"badge\" style=\"background:${badge_bg};color:#fff;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:bold;\">${finding_sev//\*/}</span>"
findings_html+="</div>"
[ -n "$finding_detail" ] && findings_html+="<p style=\"color:#94a3b8;font-size:14px;margin:4px 0;\">${finding_detail}</p>"
[ -n "$finding_evidence" ] && findings_html+="<div style=\"background:#0f172a;padding:8px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#22d3ee;margin:8px 0;word-break:break-all;\">${finding_evidence}</div>"
[ -n "$finding_exploit" ] && findings_html+="<div style=\"background:#0f172a;padding:8px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#fbbf24;margin:8px 0;\"><strong style=\"color:#f59e0b;\">Exploit:</strong> ${finding_exploit}</div>"
findings_html+="</div>"
fi
local total_findings=$((crit + high + med + low))
cat > "$html_report" << HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Analyzer Report - ${domain}</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; line-height: 1.6; }
.container { max-width: 800px; margin: 0 auto; padding: 20px; }
.header { background: linear-gradient(135deg, #0f172a, #1e293b); padding: 32px; border-radius: 12px; margin-bottom: 24px; text-align: center; border: 1px solid #334155; }
.header h1 { font-size: 24px; margin-bottom: 8px; background: linear-gradient(90deg, #f97316, #ef4444); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.header p { color: #94a3b8; font-size: 14px; }
.header .domain { color: #f97316; font-size: 18px; font-weight: bold; -webkit-text-fill-color: #f97316; margin: 8px 0; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 24px; }
.stat-card { background: #1e293b; padding: 16px; border-radius: 8px; text-align: center; border: 1px solid #334155; }
.stat-card .number { font-size: 28px; font-weight: bold; }
.stat-card .label { font-size: 12px; color: #94a3b8; margin-top: 4px; }
.critical .number { color: #ef4444; }
.high .number { color: #f97316; }
.medium .number { color: #eab308; }
.low .number { color: #3b82f6; }
.section-title { font-size: 18px; font-weight: bold; margin: 24px 0 12px; color: #f1f5f9; border-bottom: 1px solid #334155; padding-bottom: 8px; }
.finding { transition: transform 0.1s; }
.finding:hover { transform: translateX(4px); }
.footer { text-align: center; padding: 20px; color: #475569; font-size: 12px; margin-top: 32px; border-top: 1px solid #1e293b; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🔍 Analyzer Security Report</h1>
<div class="domain">${domain}</div>
<p>${date}</p>
</div>
<div class="stats">
<div class="stat-card critical">
<div class="number">${crit}</div>
<div class="label">Critical</div>
</div>
<div class="stat-card high">
<div class="number">${high}</div>
<div class="label">High</div>
</div>
<div class="stat-card medium">
<div class="number">${med}</div>
<div class="label">Medium</div>
</div>
<div class="stat-card low">
<div class="number">${low}</div>
<div class="label">Low</div>
</div>
</div>
<div class="section-title">Findings</div>
${findings_html}
<div class="footer">
Generated by The Analyzer v1.0 — Authorized Bug Bounty Use Only<br>
Analyst: Drjonesxxx / Indianaholmes
</div>
</div>
</body>
</html>
HTML
echo "$html_report"
}