265 lines
12 KiB
Bash
Executable file
265 lines
12 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Script Name: web-recon.sh
|
|
# Description: Web application reconnaissance with tmux orchestration
|
|
# Usage: web-recon <url>
|
|
# Creates tmux window with parallel web scans (nuclei, feroxbuster, katana, arjun)
|
|
|
|
VERSION="2.0.0"
|
|
|
|
# Colors
|
|
readonly RED='\033[0;31m'
|
|
readonly GREEN='\033[0;32m'
|
|
readonly YELLOW='\033[1;33m'
|
|
readonly BLUE='\033[0;34m'
|
|
readonly CYAN='\033[0;36m'
|
|
readonly MAGENTA='\033[0;35m'
|
|
readonly BOLD='\033[1m'
|
|
readonly NC='\033[0m'
|
|
|
|
# Status indicators
|
|
readonly GREENPLUS="${GREEN}[+]${NC}"
|
|
readonly GREENSTAR="${YELLOW}[*]${NC}"
|
|
readonly REDMINUS="${RED}[-]${NC}"
|
|
readonly REDEXCLAIM="${RED}[!]${NC}"
|
|
|
|
show_help() {
|
|
echo -e "${BOLD}web-recon${NC} - Web Application Reconnaissance v${VERSION}"
|
|
echo
|
|
echo -e "${BOLD}USAGE:${NC}"
|
|
echo " web-recon <url>"
|
|
echo
|
|
echo -e "${BOLD}DESCRIPTION:${NC}"
|
|
echo " Creates tmux window with 4 panes running parallel/pipelined web reconnaissance:"
|
|
echo " - Pane 1 (top-left): nuclei (vulnerability scanner)"
|
|
echo " - Pane 2 (top-right): feroxbuster → arjun (pipeline)"
|
|
echo " - Pane 3 (bottom-left): katana (web crawler with JS parsing)"
|
|
echo " - Pane 4 (bottom-right): live results dashboard"
|
|
echo
|
|
echo -e "${BOLD}EXAMPLES:${NC}"
|
|
echo " web-recon http://target.htb"
|
|
echo " web-recon https://example.com"
|
|
echo " web-recon 10.10.10.5"
|
|
echo
|
|
echo -e "${BOLD}OUTPUT:${NC}"
|
|
echo " All results saved to: ./web-recon-<target>-<timestamp>/"
|
|
echo
|
|
echo -e "${BOLD}WORKFLOW:${NC}"
|
|
echo " - Nuclei & Katana: Run in parallel immediately"
|
|
echo " - Feroxbuster (5 min) → Arjun: Pipeline (arjun waits for feroxbuster)"
|
|
echo " - httpx: Live monitoring - probes URLs as they're discovered"
|
|
}
|
|
|
|
# Check required tools
|
|
check_tools() {
|
|
local missing=()
|
|
local optional_missing=()
|
|
|
|
# Core tools
|
|
command -v tmux &>/dev/null || missing+=("tmux")
|
|
|
|
# Web tools (all optional but warn)
|
|
command -v nuclei &>/dev/null || optional_missing+=("nuclei")
|
|
command -v feroxbuster &>/dev/null || optional_missing+=("feroxbuster")
|
|
command -v katana &>/dev/null || optional_missing+=("katana")
|
|
command -v arjun &>/dev/null || optional_missing+=("arjun")
|
|
|
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
echo -e "${RED}Error:${NC} Missing required tools: ${missing[*]}"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ${#optional_missing[@]} -gt 0 ]]; then
|
|
echo -e "${YELLOW}⚠${NC} Optional tools missing (scans will be skipped): ${optional_missing[*]}"
|
|
echo -e "${CYAN}Install with:${NC}"
|
|
for tool in "${optional_missing[@]}"; do
|
|
case "$tool" in
|
|
nuclei) echo " go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest" ;;
|
|
feroxbuster) echo " cargo install feroxbuster (or: sudo apt install feroxbuster)" ;;
|
|
katana) echo " go install github.com/projectdiscovery/katana/cmd/katana@latest" ;;
|
|
arjun) echo " pipx install arjun" ;;
|
|
esac
|
|
done
|
|
echo
|
|
fi
|
|
}
|
|
|
|
# Create output directory
|
|
setup_output_dir() {
|
|
local url="$1"
|
|
local timestamp=$(date +%Y%m%d-%H%M%S)
|
|
local clean_url=$(echo "$url" | tr '/:' '_' | tr -d 'http')
|
|
|
|
OUTPUT_DIR="web-recon-${clean_url}-${timestamp}"
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
echo -e "${GREEN}✓${NC} Output directory: ${BOLD}$OUTPUT_DIR${NC}"
|
|
}
|
|
|
|
# Main web-recon function
|
|
run_web_recon() {
|
|
local url="$1"
|
|
|
|
# Ensure URL has http:// or https://
|
|
if [[ ! "$url" =~ ^https?:// ]]; then
|
|
url="http://$url"
|
|
echo -e "${YELLOW}⚠${NC} No protocol specified, using: $url"
|
|
fi
|
|
|
|
echo -e "${CYAN}${BOLD}"
|
|
echo "╔════════════════════════════════════════════════════════════╗"
|
|
echo "║ Web Application Reconnaissance ║"
|
|
echo "║ Target: $url"
|
|
echo "╚════════════════════════════════════════════════════════════╝"
|
|
echo -e "${NC}"
|
|
|
|
# Create output directory
|
|
setup_output_dir "$url"
|
|
|
|
# Check if in tmux
|
|
if [[ -z "${TMUX:-}" ]]; then
|
|
echo -e "${YELLOW}⚠${NC} Not in tmux session - running sequentially"
|
|
run_scans_sequential "$url"
|
|
return
|
|
fi
|
|
|
|
# Create tmux window
|
|
WINDOW_NAME="--> Web: ${url:0:20}... <--"
|
|
tmux new-window -n "$WINDOW_NAME"
|
|
|
|
# Split into 4 panes with explicit targeting
|
|
# Layout: 2x2 grid with pipelines and live monitoring
|
|
# ACTUAL pane numbers after splits: 1, 2, 3, 4 (no pane 0!)
|
|
# [1: nuclei] [2: feroxbuster → arjun]
|
|
# [3: katana] [4: live dashboard]
|
|
|
|
# Create 2x2 grid layout
|
|
# CRITICAL: Tmux pane numbering behavior discovered through testing:
|
|
# Step 1: split-window -h creates [0:left] [1:right]
|
|
# Step 2: select pane 0, split-window -v creates [0:TL] [1:BL] [2:right]
|
|
# Step 3: select pane 2, split-window -v creates [1:TL] [2:TR] [3:BL] [4:BR]
|
|
#
|
|
# PANE 0 DISAPPEARS during this process! Final panes are numbered 1, 2, 3, 4
|
|
|
|
# Split horizontally first (left | right)
|
|
tmux split-window -h
|
|
|
|
# Split left column vertically
|
|
tmux select-pane -t 0
|
|
tmux split-window -v
|
|
|
|
# Split right column vertically (target pane 2 after left split)
|
|
tmux select-pane -t 2
|
|
tmux split-window -v
|
|
|
|
# Force tiled layout for perfect 2x2 grid (equal-sized panes)
|
|
tmux select-layout tiled
|
|
|
|
# Final verified pane layout after tmux renumbering and tiled layout:
|
|
# 1 (top-left) 2 (top-right)
|
|
# 3 (bottom-left) 4 (bottom-right)
|
|
|
|
# Send commands to each pane with ACTUAL pane numbers after splits
|
|
# After all splits complete, tmux renumbers panes as: 1 (TL), 2 (TR), 3 (BL), 4 (BR)
|
|
# (pane 0 disappears during the splitting process)
|
|
|
|
# Pane 1 (top-left): nuclei
|
|
tmux select-pane -t 1
|
|
if command -v nuclei &>/dev/null; then
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${GREENSTAR} Starting nuclei vulnerability scan...${NC}' && nuclei -u '$url' -o nuclei.txt && echo -e '${GREEN}✓ Nuclei complete${NC}'" C-m
|
|
else
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${YELLOW}⚠ nuclei not installed - skipping${NC}'" C-m
|
|
fi
|
|
|
|
# Pane 2 (top-right): feroxbuster THEN arjun (pipeline)
|
|
tmux select-pane -t 2
|
|
if command -v feroxbuster &>/dev/null; then
|
|
# Run feroxbuster, then arjun on discovered URLs
|
|
if command -v arjun &>/dev/null; then
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${GREENSTAR} Starting feroxbuster (5 min limit, default wordlist)...${NC}' && echo -e '${YELLOW}💡 Tip: Install SecLists for better wordlists: sudo apt install seclists${NC}' && timeout 300 feroxbuster -u '$url' -d 3 --force-recursion -C 404 -o feroxbuster.txt 2>&1 | tee feroxbuster-stderr.log || echo 'Feroxbuster exited' && echo -e '${GREEN}✓ Feroxbuster complete${NC}' && cat feroxbuster.txt 2>/dev/null | grep -oE 'http[s]?://[^[:space:]]+' >> urls.txt || true && echo -e '${GREENSTAR} Starting arjun parameter discovery...${NC}' && arjun -u '$url' -oT arjun_main.txt 2>&1 | tee arjun.log && if [ -f urls.txt ] && [ -s urls.txt ]; then echo -e '${GREENSTAR} Running arjun on discovered URLs...${NC}' && arjun -i urls.txt -oT arjun_urls.txt 2>&1 | tee -a arjun.log || true; fi && echo -e '${GREEN}✓ Arjun complete${NC}'" C-m
|
|
else
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${GREENSTAR} Starting feroxbuster (5 min limit, default wordlist)...${NC}' && echo -e '${YELLOW}💡 Tip: Install SecLists for better wordlists: sudo apt install seclists${NC}' && timeout 300 feroxbuster -u '$url' -d 3 --force-recursion -C 404 -o feroxbuster.txt 2>&1 | tee feroxbuster-stderr.log || echo 'Feroxbuster exited' && echo -e '${GREEN}✓ Feroxbuster complete${NC}' && cat feroxbuster.txt 2>/dev/null | grep -oE 'http[s]?://[^[:space:]]+' >> urls.txt || true" C-m
|
|
fi
|
|
else
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${YELLOW}⚠ feroxbuster not installed - skipping${NC}' && touch urls.txt" C-m
|
|
fi
|
|
|
|
# Pane 3 (bottom-left): katana (web crawler with all output formats)
|
|
tmux select-pane -t 3
|
|
if command -v katana &>/dev/null; then
|
|
# Full katana with all output formats as originally requested
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${GREENSTAR} Starting katana crawler (full output)...${NC}' && katana -u '$url' -jc -kf all -aff -d 10 -o katana.txt 2>&1 | tee katana.log && katana -u '$url' -jc -kf all -aff -d 10 -f path -o katana_paths.txt && katana -u '$url' -jc -kf all -aff -d 10 -f url -o katana_urls.txt && katana -u '$url' -jc -kf all -aff -d 10 -f udir -o katana_dirs.txt && cat katana_dirs.txt 2>/dev/null | sort -u >> urls.txt && cat katana_paths.txt 2>/dev/null | sed 's/^.//g' >> paths.txt && echo -e '${GREEN}✓ Katana complete (all formats)${NC}'" C-m
|
|
else
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${YELLOW}⚠ katana not installed - skipping${NC}'" C-m
|
|
fi
|
|
|
|
# Pane 4 (bottom-right): Live results dashboard
|
|
tmux select-pane -t 4
|
|
# Watch output files and show live statistics
|
|
tmux send-keys "cd '$PWD/$OUTPUT_DIR' && echo -e '${CYAN}╔══════════════════════════════════════════════╗${NC}' && echo -e '${CYAN}║ LIVE SCAN RESULTS DASHBOARD ║${NC}' && echo -e '${CYAN}╚══════════════════════════════════════════════╝${NC}' && echo -e '${YELLOW}[*] Monitoring output files...${NC}' && while true; do clear; echo -e '${CYAN}═══ Scan Progress ═══${NC}'; echo; echo -e '${GREEN}Nuclei:${NC}'; [ -f nuclei.txt ] && echo \" Found: \$(wc -l < nuclei.txt 2>/dev/null || echo 0) findings\" || echo ' Waiting...'; echo; echo -e '${GREEN}Feroxbuster:${NC}'; [ -f feroxbuster.txt ] && echo \" Found: \$(grep -c '200\\|301\\|302\\|403' feroxbuster.txt 2>/dev/null || echo 0) endpoints\" || echo ' Waiting...'; echo; echo -e '${GREEN}Katana:${NC}'; [ -f katana.txt ] && echo \" Crawled: \$(wc -l < katana.txt 2>/dev/null || echo 0) URLs\" || echo ' Waiting...'; echo; echo -e '${GREEN}URLs Discovered:${NC}'; [ -f urls.txt ] && echo \" Total: \$(sort -u urls.txt 2>/dev/null | wc -l) unique URLs\" && echo && echo -e '${CYAN}Latest URLs:${NC}' && tail -5 urls.txt 2>/dev/null || echo ' None yet'; echo; echo -e '${YELLOW}[Press Ctrl+C to stop monitoring]${NC}'; sleep 3; done" C-m
|
|
|
|
# Focus back on top-left pane (nuclei)
|
|
tmux select-pane -t 1
|
|
|
|
echo
|
|
echo -e "${GREEN}✓${NC} Tmux web-recon window created"
|
|
echo -e "${CYAN}[*]${NC} Switch to window: ${BOLD}--> Web: ${url:0:20}... <--${NC}"
|
|
echo -e "${CYAN}[*]${NC} Results will be in: ${BOLD}$OUTPUT_DIR${NC}"
|
|
echo
|
|
echo -e "${YELLOW}Note:${NC} Feroxbuster will auto-stop after 5 minutes"
|
|
echo -e "${YELLOW}Note:${NC} Arjun waits 10 seconds before starting"
|
|
}
|
|
|
|
# Sequential execution (when not in tmux)
|
|
run_scans_sequential() {
|
|
local url="$1"
|
|
|
|
cd "$OUTPUT_DIR"
|
|
|
|
echo -e "\n${GREENSTAR} Running nuclei...${NC}"
|
|
command -v nuclei &>/dev/null && nuclei -u "$url" -o nuclei.txt || echo "nuclei not installed"
|
|
|
|
echo -e "\n${GREENSTAR} Running feroxbuster (5 min timeout)...${NC}"
|
|
if command -v feroxbuster &>/dev/null; then
|
|
timeout 300 feroxbuster -u "$url" -d 3 --smart --silent --force-recursion -o feroxbuster.txt 2>/dev/null || true
|
|
cat feroxbuster.txt 2>/dev/null | awk '{print $1}' >> urls.txt
|
|
fi
|
|
|
|
echo -e "\n${GREENSTAR} Running katana...${NC}"
|
|
if command -v katana &>/dev/null; then
|
|
katana -u "$url" -jc -kf all -aff -d 10 -o katana.txt
|
|
cat katana.txt 2>/dev/null | sort -u >> urls.txt
|
|
fi
|
|
|
|
echo -e "\n${GREENSTAR} Running arjun...${NC}"
|
|
if command -v arjun &>/dev/null; then
|
|
arjun -u "$url" -oT arjun_main.txt 2>&1 | tee arjun.log
|
|
[ -f urls.txt ] && [ -s urls.txt ] && arjun -i urls.txt -oT arjun_urls.txt 2>&1 | tee -a arjun.log || true
|
|
fi
|
|
|
|
cd ..
|
|
|
|
echo -e "\n${GREEN}✓${NC} Web recon complete! Results in: ${BOLD}$OUTPUT_DIR${NC}"
|
|
}
|
|
|
|
# Parse arguments
|
|
if [[ $# -eq 0 ]] || [[ "$1" =~ ^(-h|--help|help)$ ]]; then
|
|
show_help
|
|
exit 0
|
|
fi
|
|
|
|
url="$1"
|
|
|
|
# Validate URL
|
|
if [[ -z "$url" ]]; then
|
|
echo -e "${RED}Error:${NC} URL required"
|
|
echo "Usage: web-recon <url>"
|
|
exit 1
|
|
fi
|
|
|
|
# Check tools
|
|
check_tools
|
|
|
|
# Run web reconnaissance
|
|
run_web_recon "$url"
|