- 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
171 lines
5.0 KiB
Bash
Executable File
171 lines
5.0 KiB
Bash
Executable File
#!/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 ""
|