bashRecon & Automation#webinfo
257 linhas03_webinfo.sh

03_webinfo.sh — Web Fingerprint & Security Headers

Análise de cabeçalhos de resposta HTTP, identificação de WAF, tecnologias subjacentes (whatweb) e mapeamento de arquivos sensíveis como robots.txt e sitemap.

Destaques Operacionais

  • Auditoria de cabeçalhos de segurança (CSP, HSTS, X-Frame-Options, Cookie flags)
  • Detecção de Web Application Firewall (WAF) com wafw00f
  • Verificação de arquivos estáticos e rotas administrativas comuns

Como Executar

./03_webinfo.sh 10.10.10.1:80 ./output/10.10.10.1

* Ajuste as permissões de execução com chmod +x 03_webinfo.sh se necessário.

Código Fonte — 03_webinfo.sh
bash
#!/bin/bash
# ═══════════════════════════════════════════════════════
#  MÓDULO 03 — Web Fingerprint (Tech, WAF, Headers)
#  Uso standalone: ./03_webinfo.sh <alvo> <output_dir>
# ═══════════════════════════════════════════════════════

set -uo pipefail

RED='\033[0;31m'; GRN='\033[0;32m'; YLW='\033[1;33m'
BLU='\033[0;34m'; CYN='\033[0;36m'; RST='\033[0m'; BOLD='\033[1m'

info()  { echo -e "${BLU}[*]${RST} $1"; }
ok()    { echo -e "${GRN}[+]${RST} $1"; }
warn()  { echo -e "${YLW}[!]${RST} $1"; }
has()   { command -v "$1" &>/dev/null; }

TARGET="${1:?Uso: $0 <alvo> <output_dir>}"
OUTDIR="${2:?Uso: $0 <alvo> <output_dir>}/webinfo"
mkdir -p "$OUTDIR"
CLEAN=$(echo "$TARGET" | sed 's|https\?://||;s|/.*||;s|:.*||')

# Detectar URL base
if curl -sk --connect-timeout 3 "https://${CLEAN}" -o /dev/null 2>/dev/null; then
    BASE_URL="https://${CLEAN}"
elif curl -sk --connect-timeout 3 "http://${CLEAN}" -o /dev/null 2>/dev/null; then
    BASE_URL="http://${CLEAN}"
else
    BASE_URL="http://${CLEAN}"
fi

echo -e "\n${CYN}━━━ 🌐 MÓDULO 03 — Web Fingerprint ━━━${RST}"
echo -e "${BLU}    URL: ${BASE_URL}${RST}\n"

# ── Headers HTTP ──
info "Headers HTTP..."
{
    echo "═══ Response Headers ═══"
    curl -skI --connect-timeout 5 "$BASE_URL" 2>/dev/null
    echo ""
    echo "═══ Security Headers Check ═══"
    headers=$(curl -skI --connect-timeout 5 "$BASE_URL" 2>/dev/null)
    for h in "Strict-Transport-Security" "Content-Security-Policy" "X-Frame-Options" \
             "X-Content-Type-Options" "X-XSS-Protection" "Referrer-Policy" \
             "Permissions-Policy" "Access-Control-Allow-Origin"; do
        if echo "$headers" | grep -qi "$h"; then
            echo "  ✔ $h: $(echo "$headers" | grep -i "$h" | head -1 | cut -d: -f2-)"
        else
            echo "  ✘ $h: AUSENTE"
        fi
    done
} > "${OUTDIR}/headers.txt" 2>/dev/null
ok "→ headers.txt"

# Mostrar headers de segurança faltando
echo -e "\n${BOLD}  Security Headers:${RST}"
grep '✘' "${OUTDIR}/headers.txt" 2>/dev/null | while read -r line; do
    echo -e "    ${RED}${line}${RST}"
done
grep '✔' "${OUTDIR}/headers.txt" 2>/dev/null | while read -r line; do
    echo -e "    ${GRN}${line}${RST}"
done

# ── Cookies ──
info "Cookies..."
curl -sk --connect-timeout 5 -c - "$BASE_URL" 2>/dev/null > "${OUTDIR}/cookies.txt"
ok "→ cookies.txt"

# ── WhatWeb ──
if has whatweb; then
    info "whatweb (tecnologias)..."
    whatweb -a 3 "$BASE_URL" > "${OUTDIR}/whatweb.txt" 2>/dev/null
    ok "→ whatweb.txt"
    echo -e "\n${BOLD}  Tecnologias:${RST}"
    cat "${OUTDIR}/whatweb.txt" | tr ',' '\n' | head -20 | while read -r line; do
        echo -e "    ${GRN}→${RST} $line"
    done
else
    # Fallback: extrair do HTML
    info "whatweb indisponível, extraindo do HTML..."
    {
        echo "═══ Meta tags ═══"
        curl -sk "$BASE_URL" 2>/dev/null | grep -ioP '<meta[^>]+>' | head -20
        echo ""
        echo "═══ Scripts ═══"
        curl -sk "$BASE_URL" 2>/dev/null | grep -ioP 'src="[^"]+"' | head -20
        echo ""
        echo "═══ Server header ═══"
        curl -skI "$BASE_URL" 2>/dev/null | grep -i "^server:" | head -1
        echo ""
        echo "═══ X-Powered-By ═══"
        curl -skI "$BASE_URL" 2>/dev/null | grep -i "^x-powered-by:" | head -1
    } > "${OUTDIR}/tech_manual.txt"
    ok "→ tech_manual.txt"
fi

# ── WAF Detection ──
if has wafw00f; then
    info "wafw00f (WAF detection)..."
    wafw00f "$BASE_URL" > "${OUTDIR}/waf.txt" 2>/dev/null
    ok "→ waf.txt"
    # Mostrar resultado
    waf_result=$(grep -i "is behind" "${OUTDIR}/waf.txt" 2>/dev/null || grep -i "no waf" "${OUTDIR}/waf.txt" 2>/dev/null || echo "Inconclusivo")
    echo -e "    ${YLW}🛡️  ${waf_result}${RST}"
else
    warn "wafw00f não instalado."
fi

# ── Robots.txt ──
info "robots.txt..."
robots=$(curl -sk --connect-timeout 5 "${BASE_URL}/robots.txt" 2>/dev/null)
if [[ -n "$robots" ]] && ! echo "$robots" | grep -qi "404\|not found"; then
    echo "$robots" > "${OUTDIR}/robots.txt"
    ok "→ robots.txt"
    disallow=$(echo "$robots" | grep -i "disallow" | head -10)
    if [[ -n "$disallow" ]]; then
        echo -e "\n${BOLD}  Disallow entries:${RST}"
        echo "$disallow" | while read -r line; do echo -e "    ${YLW}→${RST} $line"; done
    fi
else
    warn "robots.txt não encontrado."
fi

# ── Sitemap ──
info "sitemap.xml..."
sitemap=$(curl -sk --connect-timeout 5 "${BASE_URL}/sitemap.xml" 2>/dev/null)
if [[ -n "$sitemap" ]] && echo "$sitemap" | grep -qi "urlset\|sitemapindex"; then
    echo "$sitemap" > "${OUTDIR}/sitemap.xml"
    urls_count=$(echo "$sitemap" | grep -coP '<loc>' 2>/dev/null || echo 0)
    ok "→ sitemap.xml (${urls_count} URLs)"
else
    warn "sitemap.xml não encontrado."
fi

# ── .well-known paths ──
info "Caminhos comuns..."
{
    for path in "/.well-known/security.txt" "/.env" "/wp-login.php" "/admin" \
                "/login" "/.git/HEAD" "/.svn/entries" "/phpinfo.php" \
                "/server-status" "/server-info" "/.htaccess" "/crossdomain.xml"; do
        code=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 3 "${BASE_URL}${path}" 2>/dev/null || echo "000")
        if [[ "$code" =~ ^(200|301|302|403)$ ]]; then
            echo "[${code}] ${path}"
        fi
    done
} > "${OUTDIR}/interesting_paths.txt"
ok "→ interesting_paths.txt"

if [[ -s "${OUTDIR}/interesting_paths.txt" ]]; then
    echo -e "\n${BOLD}  Paths interessantes:${RST}"
    cat "${OUTDIR}/interesting_paths.txt" | while read -r line; do
        echo -e "    ${YLW}→${RST} $line"
    done
fi

# ── HTML Report ──
HELPERS="$(dirname "$0")/_html_helpers.sh"
if [[ -f "$HELPERS" ]]; then
    source "$HELPERS"
    HTML="${OUTDIR}/report.html"

    html_head "🌐 Web Fingerprint — ${CLEAN}" > "$HTML"

    # Stats
    local sec_ok=0 sec_fail=0 paths_count=0
    [[ -f "${OUTDIR}/headers.txt" ]] && sec_ok=$(grep -c '✔' "${OUTDIR}/headers.txt" 2>/dev/null || echo 0)
    [[ -f "${OUTDIR}/headers.txt" ]] && sec_fail=$(grep -c '✘' "${OUTDIR}/headers.txt" 2>/dev/null || echo 0)
    [[ -f "${OUTDIR}/interesting_paths.txt" ]] && paths_count=$(wc -l < "${OUTDIR}/interesting_paths.txt" 2>/dev/null || echo 0)

    cat >> "$HTML" <<EOF
<h1>🌐 Web Fingerprint</h1>
<p class="meta">URL: <strong>${BASE_URL}</strong> — $(date '+%Y-%m-%d %H:%M:%S')</p>

<div class="stats">
$(html_stat "$sec_ok" "Headers OK" "green")
$(html_stat "$sec_fail" "Headers faltando" "red")
$(html_stat "$paths_count" "Paths sensíveis" "yellow")
</div>
EOF

    # Security Headers
    html_section_start "🛡️ Security Headers" >> "$HTML"
    echo '<table><tr><th>Header</th><th>Status</th><th>Valor</th></tr>' >> "$HTML"
    if [[ -f "${OUTDIR}/headers.txt" ]]; then
        grep -E '^\s*(✔|✘)' "${OUTDIR}/headers.txt" 2>/dev/null | while IFS= read -r line; do
            local hname hval
            if echo "$line" | grep -q '✔'; then
                hname=$(echo "$line" | sed 's/.*✔ //;s/:.*//') 
                hval=$(echo "$line" | sed 's/[^:]*://' | _esc)
                echo "<tr><td>${hname}</td><td>$(html_badge "✔ OK" "green")</td><td>${hval}</td></tr>" >> "$HTML"
            else
                hname=$(echo "$line" | sed 's/.*✘ //;s/:.*//') 
                echo "<tr><td>${hname}</td><td>$(html_badge "✘ AUSENTE" "red")</td><td>—</td></tr>" >> "$HTML"
            fi
        done
    fi
    echo '</table>' >> "$HTML"
    html_section_end >> "$HTML"

    # Response headers
    html_section_start "📋 Response Headers" >> "$HTML"
    html_file_pre "${OUTDIR}/headers.txt" 50 >> "$HTML"
    html_section_end >> "$HTML"

    # Tecnologias
    if [[ -f "${OUTDIR}/whatweb.txt" ]]; then
        html_section_start "🔧 Tecnologias (whatweb)" >> "$HTML"
        echo '<div style="padding:10px">' >> "$HTML"
        cat "${OUTDIR}/whatweb.txt" 2>/dev/null | tr ',' '\n' | while IFS= read -r tech; do
            tech=$(echo "$tech" | sed 's/^ *//' | _esc)
            [[ -n "$tech" ]] && echo "<span class=\"tag\">${tech}</span>" >> "$HTML"
        done
        echo '</div>' >> "$HTML"
        html_section_end >> "$HTML"
    fi

    # WAF
    if [[ -f "${OUTDIR}/waf.txt" ]]; then
        html_section_start "🛡️ WAF Detection" >> "$HTML"
        html_file_pre "${OUTDIR}/waf.txt" 20 >> "$HTML"
        html_section_end >> "$HTML"
    fi

    # Paths sensíveis
    if [[ -s "${OUTDIR}/interesting_paths.txt" ]]; then
        html_section_start "🔍 Paths Sensíveis (${paths_count})" >> "$HTML"
        echo '<table><tr><th>Status</th><th>Path</th></tr>' >> "$HTML"
        while IFS= read -r line; do
            local code path
            code=$(echo "$line" | grep -oP '^\[\K\d+')
            path=$(echo "$line" | grep -oP '\] \K.*')
            echo "<tr><td>$(html_status_badge "${code:-?}")</td><td><a href=\"${BASE_URL}${path}\" target=\"_blank\">${path}</a></td></tr>" >> "$HTML"
        done < "${OUTDIR}/interesting_paths.txt"
        echo '</table>' >> "$HTML"
        html_section_end >> "$HTML"
    fi

    # Robots.txt
    if [[ -f "${OUTDIR}/robots.txt" ]]; then
        html_section_start "🤖 robots.txt" >> "$HTML"
        html_file_pre "${OUTDIR}/robots.txt" 50 >> "$HTML"
        html_section_end >> "$HTML"
    fi

    # Cookies
    if [[ -s "${OUTDIR}/cookies.txt" ]]; then
        html_section_start "🍪 Cookies" >> "$HTML"
        html_file_pre "${OUTDIR}/cookies.txt" 30 >> "$HTML"
        html_section_end >> "$HTML"
    fi

    html_foot >> "$HTML"
    ok "→ report.html"
fi

echo -e "\n${GRN}━━━ Módulo 03 concluído ━━━${RST}"