add daily batch scanner + top50 target list + cron job
- targets/top50.txt — 50 most popular websites for daily scanning - scan-batch.sh — batch scanner that iterates through targets in quick mode, logs findings, tracks progress - cron job 'analyzer-daily-batch' runs at 2 AM daily - Uses perl-based timeout for macOS compat (no GNU timeout) - Shuffles targets each run for variety
This commit is contained in:
170
scan-batch.sh
Executable file
170
scan-batch.sh
Executable file
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
# The Analyzer — Daily Batch Scanner
|
||||
# Reads target list and scans each site in quick mode
|
||||
# Logs progress and generates reports
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ANALYZER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ANALYZER="$ANALYZER_DIR/analyzer"
|
||||
TARGETS="$ANALYZER_DIR/targets/top50.txt"
|
||||
REPORTS="$ANALYZER_DIR/reports"
|
||||
LOG="$ANALYZER_DIR/targets/batch.log"
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# Config
|
||||
OLLAMA_HOST="${OLLAMA_HOST:-http://10.30.20.110:11434}"
|
||||
OLLAMA_MODEL="${OLLAMA_MODEL:-granite4.1:8b}"
|
||||
MAX_SCAN_TIME=180 # 3 min max per target
|
||||
SUMMARY_ONLY=false
|
||||
|
||||
# Parse args
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--summary) SUMMARY_ONLY=true ;;
|
||||
--help)
|
||||
echo "Usage: $0 [--summary]"
|
||||
echo " --summary Show last scan results without running"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
mkdir -p "$ANALYZER_DIR/targets"
|
||||
|
||||
if [ "$SUMMARY_ONLY" = true ]; then
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════╗"
|
||||
echo "║ BATCH SCAN SUMMARY — Last Run ║"
|
||||
echo "╚═══════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
if [ -f "$LOG" ]; then
|
||||
tail -60 "$LOG"
|
||||
else
|
||||
echo "No batch runs yet."
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════╗"
|
||||
echo "║ THE ANALYZER — Daily Batch Scan ║"
|
||||
echo "║ $TIMESTAMP ║"
|
||||
echo "╚═══════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Check target file
|
||||
if [ ! -f "$TARGETS" ]; then
|
||||
echo "❌ Target list not found: $TARGETS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Count targets
|
||||
TOTAL=$(grep -cve '^\s*#' -e '^\s*$' "$TARGETS")
|
||||
echo " 🎯 Targets loaded: $TOTAL"
|
||||
echo " ⚡ Mode: Quick Scan"
|
||||
echo " 🧠 Ollama: $OLLAMA_HOST / $OLLAMA_MODEL"
|
||||
echo ""
|
||||
|
||||
# Read targets (shuffle with perl for macOS compat)
|
||||
SITES=()
|
||||
while IFS= read -r line; do
|
||||
SITES+=("$line")
|
||||
done < <(grep -ve '^\s*#' -e '^\s*$' "$TARGETS" | perl -MList::Util=shuffle -e 'print shuffle(<>);')
|
||||
|
||||
# Progress tracking
|
||||
COMPLETED=0
|
||||
FOUND=0
|
||||
FAILED=0
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# Log header
|
||||
{
|
||||
echo ""
|
||||
echo "═══ BATCH RUN: $TIMESTAMP ═══"
|
||||
echo "Total targets: $TOTAL"
|
||||
} >> "$LOG"
|
||||
|
||||
for SITE in "${SITES[@]}"; do
|
||||
SITE=$(echo "$SITE" | xargs) # trim
|
||||
[ -z "$SITE" ] && continue
|
||||
|
||||
# Add protocol if missing
|
||||
[[ "$SITE" != http* ]] && SITE="https://$SITE"
|
||||
|
||||
COMPLETED=$((COMPLETED + 1))
|
||||
DOMAIN=$(echo "$SITE" | sed 's|https\?://||' | cut -d/ -f1)
|
||||
|
||||
echo ""
|
||||
echo " ── [$COMPLETED/$TOTAL] $DOMAIN ──"
|
||||
|
||||
# Log start
|
||||
echo "[$(date '+%H:%M')] SCANNING $DOMAIN..." >> "$LOG"
|
||||
|
||||
# Run scan with timeout (portable: perl-based)
|
||||
SCAN_START=$(date +%s)
|
||||
SCAN_OUTPUT=$(perl -e 'alarm shift; exec @ARGV' $MAX_SCAN_TIME bash -c "
|
||||
cd '$ANALYZER_DIR'
|
||||
OLLAMA_HOST='$OLLAMA_HOST' OLLAMA_MODEL='$OLLAMA_MODEL' '$ANALYZER' '$SITE' quick 2>&1
|
||||
" 2>&1 || true)
|
||||
SCAN_END=$(date +%s)
|
||||
SCAN_TIME=$((SCAN_END - SCAN_START))
|
||||
|
||||
# Check for findings
|
||||
if echo "$SCAN_OUTPUT" | grep -q "💥\|vulnerabilities\|SQLi\|XSS\|LFI\|CRITICAL\|HIGH"; then
|
||||
FOUND=$((FOUND + 1))
|
||||
echo " 💥 FINDINGS on $DOMAIN"
|
||||
|
||||
# Extract finding lines for logging
|
||||
FINDINGS=$(echo "$SCAN_OUTPUT" | grep "💥\|🔴\|🟠\|findings\|vulnerabilit")
|
||||
|
||||
# Log findings
|
||||
echo "[$(date '+%H:%M')] FINDINGS on $DOMAIN" >> "$LOG"
|
||||
echo "$FINDINGS" >> "$LOG"
|
||||
|
||||
# Print findings
|
||||
echo "$FINDINGS" | while IFS= read -r line; do
|
||||
[ -n "$line" ] && echo " $line"
|
||||
done
|
||||
else
|
||||
echo " ✅ No findings (${SCAN_TIME}s)"
|
||||
echo "[$(date '+%H:%M')] CLEAN $DOMAIN (${SCAN_TIME}s)" >> "$LOG"
|
||||
fi
|
||||
|
||||
# Small delay between scans
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Summary
|
||||
END_TIME=$(date +%s)
|
||||
TOTAL_TIME=$((END_TIME - START_TIME))
|
||||
HOURS=$((TOTAL_TIME / 3600))
|
||||
MINS=$(((TOTAL_TIME % 3600) / 60))
|
||||
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════╗"
|
||||
echo "║ BATCH COMPLETE ║"
|
||||
echo "╚═══════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo " 📊 Stats:"
|
||||
echo " Total: $TOTAL"
|
||||
echo " Scanned: $COMPLETED"
|
||||
echo " Found: $FOUND sites with findings"
|
||||
echo " Time: ${HOURS}h ${MINS}m"
|
||||
echo ""
|
||||
|
||||
# Log summary
|
||||
{
|
||||
echo "═══ BATCH COMPLETE ═══"
|
||||
echo "Scanned: $COMPLETED | With findings: $FOUND | Time: ${HOURS}h ${MINS}m"
|
||||
echo ""
|
||||
} >> "$LOG"
|
||||
|
||||
# Print latest report
|
||||
echo " 📄 Latest reports:"
|
||||
ls -lt "$REPORTS"/*.md 2>/dev/null | head -5 | while IFS= read -r r; do
|
||||
echo " $r"
|
||||
done
|
||||
echo ""
|
||||
echo " View full log: $LOG"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user