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

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

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

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

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

Категории

Все категории
Loading categories
cve-2023-41564-research — Детальный анализ и доказательство концепции для CVE-2023-41564, уязвимости хранимого XSS в Cockpit CMS <=2.6.3, с описанием первопричины на уровне кода и рекомендациями по устранению. | Kitploit
Инструменты/GitHubGitHub/sota70/cve-2023-41564-research
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на ПроникновениеОбучение и Образование
GitHubsota70/cve-2023-41564-research

cve-2023-41564-research

Детальный анализ и доказательство концепции для CVE-2023-41564, уязвимости хранимого XSS в Cockpit CMS <=2.6.3, с описанием первопричины на уровне кода и рекомендациями по устранению.

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
Репозиторий
1 год назадЕщё не проверено

Обзор уязвимости CVE-2023-41564

CVE-2023-415641 — это уязвимость типа Stored XSS в CMS Cockpit (<= v2.6.3).
Если при загрузке файла загрузить HTML-файл с расширением .shtml, то в момент открытия загруженного файла выполнится JavaScript.

1: https://nvd.nist.gov/vuln/detail/CVE-2023-41564

Порядок проведения атаки

Сначала рассмотрим метод атаки на основе PoC2, опубликованного, предположительно, автором отчета об уязвимости.
Сначала войдите на сайт под учетной записью, имеющей права на загрузку файлов.
cms login
cms assets
Затем загрузите shtml-файл следующего содержания:
```html

root@kitploit:~
Скопируйте URL загруженного файла (Asset).<br />![cms link](https://assets.kitploit.com/production/public/readmes/32770/6a1d6857f6a6b20d1feb81a1f0237f189b016c4bcfb9700c41b3cbcf05093c43.png)<br />При переходе по скопированной ссылке выполнится скрипт, описанный в HTML выше.<br />![cms xss](https://assets.kitploit.com/production/public/readmes/32770/92fdb22909f8f16219b555fa9d1145818576b4c8232e5c7785d7ac5fcd408d36.png)<br /><br />2: https://github.com/LongHair00/Mitre_opensource_report/blob/main/CockpitCMS-StoredXSS.md

# Конкретная причина возникновения

Теперь я объясню результаты моего более глубокого исследования.<br />Обработка загрузки Assets начинается с POST-запроса к пути /assets/upload.<br />Обработка запроса на загрузку определена в строке 51 файла modules/Assets/bootstrap.php<sup>3</sup>.<br />Ниже приведен код.
```php
// assets api
$this->module('assets')->extend([

    // 省略
    'upload' => function(string|array $param = 'files', array $meta = [], bool $isUpload = true) {

        $files = [];

        if (is_string($param) && isset($this->app->request->files[$param])) {
            $files = $this->app->request->files[$param];
        } elseif (is_array($param) && isset($param['name'], $param['error'], $param['tmp_name'])) {
            $files = $param;
        }

        $finfo      = finfo_open(FILEINFO_MIME_TYPE);
        $uploaded  = [];
        $failed    = [];
        $_files     = [];
        $assets    = [];

        $allowed   = $this->app->retrieve('assets/allowed_uploads', '*');
        $allowed   = $allowed == '*' ? true : str_replace([' ', ','], ['', '|'], preg_quote(is_array($allowed) ? implode(',', $allowed) : $allowed));
        $max_size  = $this->app->retrieve('assets/max_upload_size', 0);

        $forbiddenExtension = ['bat', 'exe', 'sh', 'php', 'phar', 'phtml', 'phps', 'htm', 'html', 'xhtml', 'htaccess'];
        $forbiddenMime = [
            'application/x-httpd-php', 'application/x-php', 'text/x-php',
            'text/html', 'application/xhtml+xml'
        ];

        if (isset($files['name']) && is_array($files['name'])) {

            $cnt = count($files['name']);

            for ($i = 0; $i < $cnt; $i++) {

                $_file  = $this->app->path('#tmp:').'/'.$files['name'][$i];
                $_mime = $finfo->file($files['tmp_name'][$i]);
                $_isAllowed = $allowed === true ? true : preg_match("/\.({$allowed})$/i", $_file);
                $_sizeAllowed = $max_size ? filesize($files['tmp_name'][$i]) < $max_size : true;

                $extension = strtolower(pathinfo(parse_url($_file, PHP_URL_PATH), PATHINFO_EXTENSION));

                if (!$extension) {
                    $_isAllowed = false;
                }

                // prevent uploading php / html files
                if ($_isAllowed && (
                    in_array($extension, $forbiddenExtension) ||
                    in_array(strtolower($_mime), $forbiddenMime)
                )) {
                    $_isAllowed = false;
                }

                if (!$files['error'][$i] && $_isAllowed && $_sizeAllowed && ($isUpload ? move_uploaded_file($files['tmp_name'][$i], $_file) : rename($files['tmp_name'][$i], $_file))) {

                    $_files[]   = $_file;
                    $uploaded[] = $files['name'][$i];

                    if (\preg_match('/\.(svg|xml)$/i', $_file)) {
                        file_put_contents($_file, \SVGSanitizer::clean(\file_get_contents($_file)));
                    }

                } else {
                    $failed[] = $files['name'][$i];
                }
            }
        }

        if (count($_files)) {

            $assets = $this->add($_files, $meta, isset($meta['_id']));

            foreach ($_files as $file) {
                unlink($file);
            }
        }

        return ['uploaded' => $uploaded, 'failed' => $failed, 'assets' => $assets];
    },
    // 省略
]);

Функция upload сохраняется в переменной-члене registry['modules']['assets'] класса App, которая хранит функции модуля Assets.
Поэтому при вызове функции upload используется вызов $this->module('assets')->upload('file', $file);.
Зарегистрированная здесь функция upload вызывается классом Assets4.

root@kitploit:~
public function upload() {
    this->helper('session')->close();
    this->hasValidCsrfToken(true);
    if (!this->isAllowed('assets/upload')) {
        return $this->stop(['error' => 'Upload not allowed'], 401);
    }
    $meta = ['folder' => $this->param('folder', '')];
    return $this->module('assets')->upload('files', $meta);
}

Видно, что вызывается функция upload, зарегистрированная в registry['modules']['assets'].
Теперь посмотрим на функцию upload, описанную в bootstrap.php.
В ней переменная $forbiddenExtension определяет запрещённые расширения.
Однако расширение shtml отсутствует.
Это и является дефектом, который позволяет загружать shtml-файлы.

3: https://github.com/Cockpit-HQ/Cockpit/blob/2.6.3/modules/Assets/bootstrap.php#L51
4: https://github.com/Cockpit-HQ/Cockpit/blob/2.6.3/modules/Assets/Controller/Assets.php#L140

Меры противодействия

Поскольку причина в том, что shtml не запрещён, мерой противодействия является добавление shtml в $forbiddenExtension.

root@kitploit:~
$forbiddenExtension = ['bat', 'exe', 'sh', 'php', 'phar', 'phtml', 'phps', 'htm', 'html', 'xhtml', 'htaccess', 'shtml'];
Скачать инструмент