Skip to content

Instantly share code, notes, and snippets.

@ResistanceIsUseless
Forked from nullenc0de/365doms.py
Created November 4, 2023 00:41
Show Gist options
  • Save ResistanceIsUseless/617d28bf4aeb1d5da9b3d686b081ffd9 to your computer and use it in GitHub Desktop.
Save ResistanceIsUseless/617d28bf4aeb1d5da9b3d686b081ffd9 to your computer and use it in GitHub Desktop.

Revisions

  1. @nullenc0de nullenc0de created this gist Feb 23, 2023.
    79 changes: 79 additions & 0 deletions 365doms.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    #!/usr/bin/env python3

    """
    Python script to enumerate valid Microsoft 365 domains, retrieve tenant name, and check for an MDI instance.
    Based on: https://github.com/thalpius/Microsoft-Defender-for-Identity-Check-Instance.
    Usage: ./check_mdi.py -d <domain>
    """

    import argparse
    import dns.resolver
    import xml.etree.ElementTree as ET
    from urllib.request import urlopen, Request


    # Get domains
    def get_domains(args):
    domain = args.domain

    # Create a valid HTTP request
    # Example from: https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxwsadisc/18fe58cd-3761-49da-9e47-84e7b4db36c2
    body = f"""<?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:exm="http://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:ext="http://schemas.microsoft.com/exchange/services/2006/types"
    xmlns:a="http://www.w3.org/2005/08/addressing"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Header>
    <a:RequestedServerVersion>Exchange2010</a:RequestedServerVersion>
    <a:MessageID>urn:uuid:6389558d-9e05-465e-ade9-aae14c4bcd10</a:MessageID>
    <a:Action soap:mustUnderstand="1">http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation</a:Action>
    <a:To soap:mustUnderstand="1">https://autodiscover.byfcxu-dom.extest.microsoft.com/autodiscover/autodiscover.svc</a:To>
    <a:ReplyTo>
    <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    </soap:Header>
    <soap:Body>
    <GetFederationInformationRequestMessage xmlns="http://schemas.microsoft.com/exchange/2010/Autodiscover">
    <Request>
    <Domain>{domain}</Domain>
    </Request>
    </GetFederationInformationRequestMessage>
    </soap:Body>
    </soap:Envelope>"""

    # Including HTTP headers
    headers = {
    "Content-type": "text/xml; charset=utf-8",
    "User-agent": "AutodiscoverClient"
    }

    # Perform HTTP request
    try:
    httprequest = Request(
    "https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc", headers=headers, data=body.encode())

    with urlopen(httprequest) as response:
    response = response.read().decode()
    except Exception:
    print("[-] Unable to execute request. Wrong domain?")
    exit()

    # Parse XML response
    domains = []

    tree = ET.fromstring(response)
    for elem in tree.iter():
    if elem.tag == "{http://schemas.microsoft.com/exchange/2010/Autodiscover}Domain":
    domains.append(elem.text)

    print(*domains, sep="\n")


    if __name__ == "__main__":
    parser = argparse.ArgumentParser(
    description="Enumerates valid Microsoft 365 domains, retrieves tenant name, and checks for MDI instance")
    parser.add_argument(
    "-d", "--domain", help="input domain name, example format: example.com", required=True)
    args = parser.parse_args()
    get_domains(args)