# Attacking MS Exchange Web Interfaces
**[swarm.ptsecurity.com/attacking-ms-exchange-web-interfaces/](https://swarm.ptsecurity.com/attacking-ms-exchange-web-interfaces/)**
Arseniy Sharoglazov July 23, 2020
## Author
[Arseniy Sharoglazov](https://swarm.ptsecurity.com/author/arseniy-sharoglazov/)
Penetration Testing Expert
[_mohemiv](https://twitter.com/_mohemiv)
During External Penetration Testing, I often see MS Exchange on the perimeter:
Examples of MS Exchange web interfaces
Exchange is basically a mail server that supports a bunch of Microsoft protocols. It’s usually
located on subdomains named autodiscover, mx, owa or mail, and it can also be detected by
existing `/owa/,` `/ews/,` `/ecp/,` `/oab/,` `/autodiscover/,` `/Microsoft-Server-`
```
ActiveSync/, /rpc/, /powershell/ endpoints on the web server.
```
-----
The knowledge about how to attack Exchange is crucial for every penetration testing team. If
you found yourself choosing between a non-used website on a shared hosting and a MS
Exchange, only the latter could guide you inside.
In this article, I’ll cover all the available techniques for attacking MS Exchange web interfaces
and introduce a new technique and a new tool to connect to MS Exchange from the Internet
and extract arbitrary Active Directory records, which are also known as LDAP records.
## Techniques for Attacking Exchange in Q2 2020
Let’s assume you’ve already brute-forced or somehow accessed a low-privilege domain
account.
If you had been a Black Hat, you would try to sign into the Exchange and access the user’s
mailbox. However, for Red Teams, it’s never possible since keeping the client data private is
the main goal during penetration testing engagements.
I know of only 5 ways to attack fully updated MS Exchange via a web interface and not
disclose any mailbox content:
**Getting Exchange User List and Other Information**
Exchange servers have a url /autodiscover/autodiscover.xml that implements Autodiscover
Publishing and Lookup Protocol (MS-OXDSCLI). It accepts special requests that return a
configuration of the mailbox to which an email belongs.
If Exchange is covered by Microsoft TMG, you must specify a non-browser User-Agent in the
request or you will be redirected to an HTML page to authenticate.
[Microsoft TMG’s Default User-Agent Mapping](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ff826797(v=vs.85))
An example of a request to the Autodiscover service:
-----
```
POST /autodiscover/autodiscover.xml HTTP/1.1
Host: exch01.contoso.com
User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.10730;
Pro)
Authorization: Basic Q09OVE9TT1x1c2VyMDE6UEBzc3cwcmQ=
Content-Length: 341
Content-Type: text/xml
kmia@contoso.com
http://schemas.microsoft.com/exchange/autodiscover/outlook/r
```
The specified in the tag email needs to be a primary email of an existing
user, but it does not necessarily need to correspond to the account used for the
authentication. Any domain account will be accepted since the authentication and the
authorization are fully done on IIS and Windows levels and Exchange is only processing the
XML.
If the specified email has been accepted, you will get a big response containing a
dynamically constructed XML. Examine the response, but don’t miss the four following items:
-----
An example of the Autodiscover service’s output
In the X-BackEndCookie cookie you will find a SID. It’s the SID of the used account, and not
the SID of the mailbox owner. This SID can be useful when you don’t know the domain of the
bruteforced user.
In the and tags you will find one of Domain Controllers FQDNs, and the
Exchange RPC identity. The DC FQDN will refer to the domain of the mailbox owner. Both
_ and values can vary for each request. As you go along, you’ll see how you_
may apply this data
-----
In the tag you will find a path to a directory with Offline Address Book (OAB) files.
Using the path, you can get an Address List of all Exchange users. To do so,
request the /oab.xml page from the server and list OAB files:
Getting access to Offline Address Books
The Global Address List (GAL) is an Address Book that includes every mail-enabled object in
the organization. Download its OAB file from the same directory, unpack it via the oabextract
tool from libmspack library, and run one of the OAB extraction tools or just a strings
command to get access to user data:
-----
An example of extracting data via Offline Address Books
There could be multiple organizations on the server and multiple GALs, but this function is
almost never used. If it’s enabled, the Autodiscover service will return different OABUrl
values for users from different organizations.
There are ways to get Address Lists without touching OABs (e.g., via MAPI over HTTP in
Ruler or [via OWA or EWS in MailSniper), but these techniques require your account to have](https://github.com/dafthack/MailSniper)
a mailbox associated with it.
After getting a user list, you can perform a Password Spraying attack via the same
Autodiscover service or via any other domain authentication on the perimeter. I advise you
check out [ntlmscan utility, as it contains a quite good wordlist of NTLM endpoints.](https://github.com/nyxgeek/ntlmscan)
**Pros and Cons**
Any domain account can be used
The obtained information is very limited
You can only get a list of users who have a mailbox
You have to specify an existent user’s primary email address
-----
The attacks are well-known for Blue Teams, and you can expect blocking or monitoring
of the needed endpoints
Available extraction tools do not support the full OAB format and often crash
Don’t confuse Exchange Autodiscover with Lync Autodiscover; they are two completely
different services.
**Usage of Ruler**
Ruler is a tool for connecting to Exchange via MAPI over HTTP or RPC over HTTP v2
protocols and insert special-crafted records to a user mailbox to abuse the user’s Microsoft
Outlook functions and make it execute arbitrary commands or code.
An example of Ruler usage
There are currently only three known techniques to get an RCE in such a way: via rules, via
forms, and via folder home pages. All three are fixed, but organizations which have no
WSUS, or have a WSUS configured to process only Critical Security Updates, can still be
attacked.
[Microsoft Update Severity Ratings](https://www.microsoft.com/en-us/msrc/security-update-severity-rating-system)
You must install both Critical and Important updates to protect your domain from Ruler’s
attacks
**Pros and Cons**
A successful attack leads to RCE
The used account must have a mailbox
The user must regularly connect to Exchange and have a vulnerable MS Outlook
The tool provides no way to know if the user uses MS Outlook and what its version is
The tool requires you to specify the user’s primary email address
The tool requires /autodiscover/ endpoint to be available
The tool has no Unicode support
The tool has a limited protocol support and may fail with mystery errors
Blue Teams can reveal the tool by its hardcoded strings and BLOBs, including the
“Ruler” string in its go-ntlm external library
Link to a tool: [https://github.com/sensepost/ruler](https://github.com/sensepost/ruler)
**Usage of PEAS**
-----
PEAS is a lesser-known alternative to Ruler. It s a tool for connecting to Exchange via
ActiveSync protocol and get access to any SMB server in the internal network:
An example of PEAS usage
To use PEAS, you need to know any internal domain name that has no dots. This can be a
NetBIOS name of a server, a subdomain of a root domain, or a special name like localhost. A
domain controller NetBIOS name can be obtained from the FQDN from the tag of the
Autodiscover XML, but other names are tricky to get.
The PEAS attacks work via the Search and ItemOperations commands in ActiveSync.
Note #1
It’s a good idea to modify PEAS hard-coded identifiers. Exchange stores identifiers of all
ActiveSync clients, and Blue Teams can easily request them via an LDAP request. These
records can be accessible via any user with at least Organization Management privileges:
-----
Getting a list of accounts that have used PEAS via LDAP using (msExchDeviceID=123456)
filter
These identifiers are also used to wipe lost devices or to filter or quarantine new devices by
their models or model families. If the quarantine policy is enforced, Exchange sends emails
to administrators when a new device has been connected. Once the device is allowed, a
device with the same model or model family can be used to access any mailbox.
An example of widely used identifiers:
```
msExchDeviceID: 302dcfc5920919d72c5372ce24a13cd3
msExchDeviceModel: Outlook for iOS and Android
msExchDeviceOS: OutlookBasicAuth
msExchDeviceType: Outlook
msExchDeviceUserAgent: Outlook-iOS-Android/1.0
```
If you have been quarantined, PEAS will show an empty output, and there will be no signs of
quarantine even in the decrypted TLS traffic.
Note #2
-----
The ActiveSync service supports http/https URLs for connecting to Windows SharePoint
Services (WSS). This feature can be abused by performing a blind SSRF attack, and you will
have an option to authenticate to the target with any credentials via NTLM:
Forcing Exchange to make a WSS connection to http://SHP01/test/test/test with
CONTOSO\sharepoint-setup account
[An example of a WSS connection: activesync_wss_sample.pcap](https://swarm.ptsecurity.com/wp-content/uploads/2020/07/activesync_wss_sample.pcap)
The shown requests will be sent even if the target is not a SharePoint. For HTTPS
connections, the certificate will require a validation. As it is ActiveSync, the target hostname
should have no dots.
**Pros and Cons**
The tool has no bugs on the protocol level
The tool supports usage of different credentials for each Exchange and SMB/HTTP
The tool attacks are unique and cannot be currently done via other techniques or
software
The used account must have a mailbox
The ActiveSync protocol must be enabled on the server and for the used account
The support of UNC/WSS paths must not be disabled in the ActiveSync configuration
-----
The list of allowed SMB/WSS servers must not be set in the ActiveSync configuration
You need to know hostnames to connect
ActiveSync accepts only plaintext credentials, so there is no way to perform the NTLM
Relay or Pass-The-Hash attack
The tool has some bugs related to Unicode paths, but they can be easily fixed.
Link to a tool: [https://github.com/FSecureLABS/PEAS](https://github.com/FSecureLABS/PEAS)
**Abusing EWS Subscribe Operation**
Exchange Web Services (EWS) is an Exchange API designed to provide access to mailbox
items. It has a Subscribe operation, which allows a user to set a URL to get callbacks from
Exchange via HTTP protocol to receive push notifications.
In 2018, the ZDI Research Team discovered that Exchange authenticates to the specified
URL via NTLM or Kerberos, and this can be used in NTLM Relay attacks to the Exchange
itself.
[Impersonating Users on Microsoft Exchange](https://www.thezdi.com/blog/2018/12/19/an-insincere-form-of-flattery-impersonating-users-on-microsoft-exchange)
Forcing Exchange to make a connection to http://attacker.com/test/test/test
After the original publication, the researcher Dirk-jan Mollema demonstrated that HTTP
requests in Windows can be relayed to LDAP and released the PrivExchange tool and a new
version of NTLMRelayX to get a write access to Active Directory on behalf of the Exchange
account.
[Abusing Exchange: One API call away from Domain Admin](https://dirkjanm.io/abusing-exchange-one-api-call-away-from-domain-admin/)
Currently, Subscribe HTTP callbacks do not support any interaction with a receiving side, but
it’s still possible to specify any URL to get an incoming connection, so they can be used for
blind SSRF attacks.
**Pros and Cons**
The used account must have a mailbox
-----
You must have an extensive knowledge of the customer s internal network
Link to a tool: [https://github.com/dirkjanm/PrivExchange](https://github.com/dirkjanm/PrivExchange)
**Abusing Office Web Add-ins**
This technique is only for persistence, so just read the information by the link if needed.
Link to a technique: https://www.mdsec.co.uk/2019/01/abusing-office-web-add-ins-for-funand-limited-profit/
## The New Tool We Want
Based on the available attacks and software, it’s easy to imagine the tool that will be great to
have:
The tool must work with any domain account
The tool must not rely on /autodiscover/ and /oab/ URLs
The knowledge of any email addresses must not be required
All used protocols must be fully and qualitatively implemented
The tool must be able to get Address Lists on all versions of Exchange in any encoding
The tool must not rely on endpoints which can be protected by ADFS, as ADFS may
require Multi-Factor Authentication
The tool must be able to get other useful data from Active Directory: service account
names, hostnames, subnets, etc
These requirements led me to choose RPC over HTTP v2 protocol for this research. It’s the
oldest protocol for communication with Exchange, it’s enabled by default in Exchange
2003/2007/2010/2013/2016/2019, and it can pass through Microsoft Forefront TMG servers.
## How RPC over HTTP v2 works
Let’s run Ruler and see how it communicates via RPC over HTTP v2:
**Connection #1**
-----
Traffic dump of
-----
**Parallel Connection #2**
-----
Traffic dump of
-----
Ruler #2 connection
RPC over HTTP v2 works in two parallel connections: IN and OUT channels. It’s a patented
Microsoft technology for high-speed traffic passing via two fully compliant HTTP/1.1
connections.
[The structure of RPC over HTTP v2 data is described in the MS-RPCH Specification, and it](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpch/c0f4c9c5-1a61-4d10-b8e2-005378d1d212)
just consists of ordinary MSRPC packets and special RTS RPC packets, where RTS stands
for Request to Send.
RPC over HTTP v2 carries MSRPC
The endpoint /rpc/rpcproxy.dll actually is not a part of Exchange. It’s a part of a service called
**RPC Proxy. It’s an intermediate forwarding server between RPC Clients and RPC Servers.**
The Exchange RPC Server is on port 6001 in our case:
An example of
a pure ncacn_http endpoint
We will refer to such ports as ncacn_http services/endpoints. According to the specification,
each client must use RPC Proxies to connect to ncacn_http services, but surely you can
emulate RPC Proxy and connect to ncacn_http endpoints directly, if you need to.
RPC IN and OUT channels operate independently, and they can potentially pass through
different RPC Proxies, and the RPC Server can be on a different host as well:
-----
The RPC Server, i.e., the ncacn_http endpoint orchestrates IN and OUT channels, and
packs or unpacks MSRPC packets into or from them.
Both RPC Proxies and RPC Servers control the amount of traffic passing through the chain
to protect from Denial-of-Service attacks. This protection is one of the reasons for the
existence of RTS RPC packets.
## Determining target RPC Server name
In the RPC over HTTP v2 traffic dump, you can see that Ruler obtained the RPC Server
name from the Autodiscover service and put it into the URL:
Traffic dump of Ruler’s RPC over HTTP v2 connection
Interestingly, according to the MS-RPCH specification, this URL should contain a hostname
or an IP; and such “GUID hostnames” cannot be used:
-----
[An excerpt from the MS-RPCH specification: 2.2.2 URI Encoding](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpch/0b7aecea-cd35-436d-9b4b-ae1e1fd5174f)
[The article by Microsoft RPC over HTTP Security also mentions nothing about this format,](https://docs.microsoft.com/en-us/windows/win32/rpc/rpc-over-http-security)
but it shows the registry key where RPC Proxies contain allowed values for this URL:
```
HKLM\Software\Microsoft\Rpc\RpcProxy .
```
-----
An example of a content of HKLM\Software\Microsoft\Rpc\RpcProxy key
It was discovered that each RPC Proxy has a default ACL that accepts connections to the
RPC Proxy itself via 593 and 49152-65535 ports using its NetBIOS name, and all Exchange
servers have a similar ACL containing every Exchange NetBIOS name with corresponding
ncacn_http ports.
Since RPC Proxies support NTLM authentication, we can always get theirs NetBIOS names
via NTLMSSP:
-----
An
example of getting target NetBIOS name via NTLMSSP using nmap
So now we likely have a technique for connecting to RPC Proxies without usage of the
Autodiscover service and knowing the Exchange GUID identity.
Based on the code available in Impacket, I’ve developed RPC over HTTP v2 protocol
implementation, rpcmap.py utility, and slightly modified rpcdump.py to verify our ideas and
pave the way for future steps:
-----
Running rpcmap.py for Exchange 2019. The previous version of this tool was contributed to
Impacket in May 2020.
-----
Traffic dump of RPC IN Channel of rpcmap.py
Although rpcmap.py successfully used our technique to connect to the latest Exchange,
internally the request was processed in a different way: Exchange 2003/2007/2010 used to
get connections via rpcproxy.dll, but Exchange 2013/2016/2019 have RpcProxyShim.dll.
**RpcProxyShim.dll hooks RpcProxy.dll callbacks and processes Exchange GUID identities.**
NetBIOS names are also supported for backwards compatibility. RpcProxyShim.dll allows to
skip authentication on the RPC level and can forward traffic directly to the Exchange process
to get a faster connection.
For more information about RpcProxyShim.dll and RPC Proxy ACLs, read comments in our
MS-RPCH implimentation code.
## Exploring RPC over HTTP v2 endpoints
Let’s run rpcmap.py with -brute-opnums option for MS Exchange 2019 to get information
about which endpoints are accessible via RPC over HTTP v2:
-----
```
$ rpcmap.py debug auth transport CONTOSO/mia:P@ssw0rd auth rpc
'CONTOSO/mia:P@ssw0rd' -auth-level 6 -brute-opnums 'ncacn_http:
[6001,RpcProxy=exch01.contoso.com:443]'
[+] StringBinding has been changed to
ncacn_http:EXCH01[6001,RpcProxy=exch01.contoso.com:443]
Protocol: [MS-DCOM]: Distributed Component Object Model (DCOM) Remote
Provider: N/A
UUID: 00000131-0000-0000-C000-000000000046 v0.0
Opnums 0-64: rpc_s_access_denied
Protocol: [MS-DCOM]: Distributed Component Object Model (DCOM)
Provider: N/A
UUID: 00000134-0000-0000-C000-000000000046 v0.0
Opnums 0-64: rpc_s_access_denied
Protocol: [MS-DCOM]: Distributed Component Object Model (DCOM) Remote
Provider: N/A
UUID: 00000143-0000-0000-C000-000000000046 v0.0
Opnums 0-64: rpc_s_access_denied
Protocol: [MS-OXABREF]: Address Book Name Service Provider Interface (NSPI) Referral
Protocol
Provider: N/A
UUID: 1544F5E0-613C-11D1-93DF-00C04FD7BD09 v1.0
Opnum 0: rpc_x_bad_stub_data
Opnum 1: rpc_x_bad_stub_data
Opnums 2-64: nca_s_op_rng_error (opnum not found)
Protocol: [MS-DCOM]: Distributed Component Object Model (DCOM)
Provider: ole32.dll
UUID: 18F70770-8E64-11CF-9AF1-0020AF6E72F4 v0.0
Opnums 0-64: rpc_s_access_denied
Protocol: [MS-OXCRPC]: Wire Format Protocol
Provider: N/A
UUID: 5261574A-4572-206E-B268-6B199213B4E4 v0.1
Opnum 0: rpc_x_bad_stub_data
Opnums 1-64: nca_s_op_rng_error (opnum not found)
Procotol: N/A
Provider: N/A
UUID: 5DF3C257-334B-4E96-9EFB-A0619255BE09 v1.0
Opnums 0-64: rpc_s_access_denied
Protocol: [MS-OXCRPC]: Wire Format Protocol
Provider: N/A
UUID: A4F1DB00-CA47-1067-B31F-00DD010662DA v0.81
Opnum 0: rpc_x_bad_stub_data
Opnum 1: rpc_x_bad_stub_data
Opnum 2: rpc_x_bad_stub_data
Opnum 3: rpc_x_bad_stub_data
Opnum 4: rpc_x_bad_stub_data
Opnum 5: rpc_x_bad_stub_data
Opnum 6: success
Opnum 7: rpc_x_bad_stub_data
```
-----
```
Opnum 8: rpc_x_bad_stub_data
Opnum 9: rpc_x_bad_stub_data
Opnum 10: rpc_x_bad_stub_data
Opnum 11: rpc_x_bad_stub_data
Opnum 12: rpc_x_bad_stub_data
Opnum 13: rpc_x_bad_stub_data
Opnum 14: rpc_x_bad_stub_data
Opnums 15-64: nca_s_op_rng_error (opnum not found)
Protocol: [MS-RPCE]: Remote Management Interface
Provider: rpcrt4.dll
UUID: AFA8BD80-7D8A-11C9-BEF4-08002B102989 v1.0
Opnum 0: success
Opnum 1: rpc_x_bad_stub_data
Opnum 2: success
Opnum 3: success
Opnum 4: rpc_x_bad_stub_data
Opnums 5-64: nca_s_op_rng_error (opnum not found)
Procotol: N/A
Provider: N/A
UUID: BA3FA067-8D56-4B56-BA1F-9CBAE8DB3478 v1.0
Opnums 0-64: rpc_s_access_denied
Protocol: [MS-NSPI]: Name Service Provider Interface (NSPI) Protocol
Provider: ntdsai.dll
UUID: F5CC5A18-4264-101A-8C59-08002B2F8426 v56.0
Opnum 0: rpc_x_bad_stub_data
Opnum 1: rpc_x_bad_stub_data
Opnum 2: rpc_x_bad_stub_data
Opnum 3: rpc_x_bad_stub_data
Opnum 4: rpc_x_bad_stub_data
Opnum 5: rpc_x_bad_stub_data
Opnum 6: rpc_x_bad_stub_data
Opnum 7: rpc_x_bad_stub_data
Opnum 8: rpc_x_bad_stub_data
Opnum 9: rpc_x_bad_stub_data
Opnum 10: rpc_x_bad_stub_data
Opnum 11: rpc_x_bad_stub_data
Opnum 12: rpc_x_bad_stub_data
Opnum 13: rpc_x_bad_stub_data
Opnum 14: rpc_x_bad_stub_data
Opnum 15: rpc_x_bad_stub_data
Opnum 16: rpc_x_bad_stub_data
Opnum 17: rpc_x_bad_stub_data
Opnum 18: rpc_x_bad_stub_data
Opnum 19: rpc_x_bad_stub_data
Opnum 20: rpc_x_bad_stub_data
Opnums 21-64: nca_s_op_rng_error (opnum not found)
```
[The rpcmap.py works via the Remote Management Interface described in MS-RPCE 2.2.1.3.](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/3165f378-ede3-48a8-b871-be1183e1b7fb)
If it’s available, it can show all interfaces offered by the RPC Server. Note that the tool may
show non-available endpoints, and provider and protocol lines are taken from the Impacket
database, and they can be wrong.
-----
Correlating the rpcmap.py output with the Exchange documentation, the next table with a
complete list of protocols available via RPC over HTTP v2 in MS Exchange was formed:
**Protocol** **UUID** **Description**
[MS‑OXCRPC](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcrpc/137f0ce2-31fd-4952-8a7d-6c0b242e4b6a) A4F1DB00-CA47-1067B31F-00DD010662DA v0.81
[MS‑OXCRPC](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcrpc/137f0ce2-31fd-4952-8a7d-6c0b242e4b6a) 5261574A-4572-206E-B2686B199213B4E4 v0.1
[MS‑OXABREF](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxabref/88c2b896-fe4f-4e28-8a87-e83a73d9c90e) 1544F5E0-613C-11D1-93DF00C04FD7BD09 v1.0
[MS‑OXNSPI](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxnspi/63662a26-c8fc-4493-a41a-fbcbb7e43136) F5CC5A18-4264-101A8C59-08002B2F8426 v56.0
Wire Format Protocol EMSMDB Interface
Wire Format Protocol AsyncEMSMDB
Interface
Address Book Name Service Provider
Interface (NSPI) Referral Protocol
Exchange Server Name Service Provider
Interface (NSPI) Protocol
MS-OXCRPC is the protocol that Ruler uses to send MAPI messages to Exchange, and MSOXABREF and MS-OXNSPI are two completely new protocols for the penetration testing
field.
## Exploring MS-OXABREF and MS-OXNSPI
MS-OXNSPI is one of the protocols that Outlook uses to access Address Books. MSOXABREF is its auxiliary protocol to obtain the specific RPC Server name to connect to it via
RPC Proxy to use the main protocol.
MS-OXNSPI contains 21 operations to access Address Books. It appears to be an OAB with
search and dynamic queries:
-----
Contents of [the MS-OXNSPI specification](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxnspi/63662a26-c8fc-4493-a41a-fbcbb7e43136)
The important thing for working with MS-OXNSPI is understanding what Legacy DN is. In the
specification you will see terms “DN” and “DNs” that seem to refer to Active Directory:
-----
[An excerpt from the MS-OXNSPI specification: 3.1.4.1.13 NspiDNToMId](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxnspi/a4e056f0-7d05-4e6d-8acb-65751e83a071)
The truth is, these DNs are not Active Directory DNs. They are Legacy DNs.
In 1997, Exchange was not based on Active Directory and used its predecessor, X.500
Directory Service. In 2000, the migration to Active Directory happened, and for each
X.500 attribute a corresponding attribute in Active Directory was assigned:
**X.500 Attribute** **Active Directory Attribute**
DXA‑Flags none
DXA‑Task none
distinguishedName legacyExchangeDN
objectGUID objectGUID
mail mail
none distinguishedName
… …
X.500 distinguishedName was moved to legacyExchangeDN, and Active Directory was given
its own distinguishedName. But, from Exchange protocols point of view, not that much has
changed. The protocols were modified to access Active Directory instead of X.500 Directory
Service, but a lot of the terminology and internal features remained the same.
-----
I would say X.500 space on top of Active Directory was formed, and all elements with
legacyExchangeDN attribute represent it.
Let’s see how it’s done in practice.
I’ve developed the implementation of MS-OXNSPI protocol, but before we use it, let’s
request our sample object via LDAP:
Connecting to Active Directory via LDAP and getting information about a sample user
As expected, the distinguishedName field contains the object’s Active Directory
Distinguished Name, and the legacyExchangeDN field contains a different thing we call
Legacy DN.
To request information about this user via MS-OXNSPI, we will use its Legacy DN as a DN,
as it represents a DN in our imaginary X.500 space:
Connecting to Exchange via MS-OXNSPI and performing the NspiDNToMId operation
-----
The NspiDNToMId operation we called returned a temporary object identifier that works only
during this session. We will talk about it in the next section, but for now, just observe that we
passed Legacy DN as a DN and it worked.
Also note we have used “Administrator” account and it worked despite the fact that this
account doesn’t have a mailbox. Even a machine account would work fine.
Let’s request all the object properties via the obtained temporary identifier:
Requesting the sample object information via MS-OXNSPI
You can see we were able to get a lot of properties which do not show up via other
techniques (e.g., OAB extracting). Sadly, not all Active Directory properties are here.
Exchange returns only fields of our imaginary X.500 space.
As the documentation describes operations to get all members of any Address Book, we are
able to develop a tool to extract all available fields of all mailbox accounts. I will present this
tool at the end, but now let’s move on since we wanted to get access to whole Active
Directory information.
## Revealing Formats of MIDs and Legacy DNs
-----
One of the key terms in MS-OXNSPI is Minimal Entry ID (MId). MIDs are 4-byte integers that
act like temporary identifiers during a single MS-OXNSPI session:
[An excerpt from the MS-OXNSPI specification: 2.2.9.1 MinimalEntryID](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxnspi/902ede0d-bb0a-46f0-bf68-03a6ed08d4e8)
The documentation does not disclose the algorithm used for MIDs creation.
To explore how MIDs are formed, we will call NspiGetSpecialTable operation and obtain a list
of existing Address Books:
-----
The demonstration of usage of NspiGetSpecialTable operation
In the output, the PidTagAddressBookContainerId field contains an assigned MId for each
Address Book. It’s easy to spot that they are simply integers that are decrementing from
0xFFFFFFF0:
**MID HEX Format** **MID Unsigned Int Format** **MID Signed Int Format**
0xFFFFFFF0 4294967280 -16
0xFFFFFFEF 4294967279 -17
0xFFFFFFEE 4294967278 -18
… … …
The 4294967280 number also appeared in the previous section where we requested sample
user information. It’s here again because I used a blank session to take this screenshot. If it
was the same session, we would get MIDs assigned from 4294967279.
-----
Take a look into the PidTagEntryId field in the shown output. It contains new for us Legacy
DN format:
```
/guid=B2D6307C8376CA4DA4CE20E29BB1F2DF
```
If you will try to request objects using this format, you will discover you can get any Active
Directory object by its objectGUID:
Getting access to a service account’s data by its objectGUID
This output shows the other similar Legacy DN format:
```
/o=NT5/ou=00000000000000000000000000000000/cn=F24B833B62919948B1D1D2D888CDB10B
```
So, we need very little to obtain whole Active Directory data: we must either get a list of all
Active Directory GUIDs, or somehow make the server assign a MId to each Active Directory
object.
## Revealing Hidden Format of MIDs
-----
I redrawn the previously used schematic to show how MS-OXNSPI works from the server
perspective:
Exchange does not match or sort the data itself; it’s acting like a proxy. Most of the work
happens on Domain Controllers. Exchange uses LDAP and MS-NSPI protocols to connect to
DCs to access the Active Directory database.
MS-NSPI is the MSRPC protocol that is almost fully compliant with MS-OXNSPI:
Contents of the MS-OXNSPI
specification
-----
Contents of [the MS-NSPI specification](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nspi/6dd0a3ea-b4d4-4a73-a857-add03a89a543)
The main difference is that the MS-NSPI protocol is offered by the ntdsai.dll library in the
lsass.exe memory on DCs when Exchange is set up.
The MS-NSPI and MS-OXNSPI protocols are even sharing UUIDs:
**Protocol** **UUID**
MS‑NSPI F5CC5A18-4264-101A-8C59-08002B2F8426 v56.0
MS‑OXNSPI F5CC5A18-4264-101A-8C59-08002B2F8426 v56.0
So, MS-NSPI is the third network protocol after LDAP and MS-DRSR (MS-DRSR is also
known as DcSync and DRSUAPI) to access the Active Directory database.
Let’s connect to a Domain Controller via MS-NSPI using our code developed for MSOXNSPI:
-----
Determining MS-NSPI endpoint on a DC and connecting to it
And let’s call NspiGetSpecialTable, the operation we previously used for obtaining a list of
existing Address Books, directly on a DC:
Calling NspiGetSpecialTable on a Domain Controller
The returning Address Books remain the same, but the MIDs are different. A MId on a
Domain Controller represents an object DNT.
-----
**Distinguished Name Tags (DNTs) are 4-byte integer indexes of objects inside a Domain**
Controller NTDS.dit database. DNTs are different on every DC: they are never replicated, but
can be copied during an initial DC synchronization.
DNTs usually start between 1700 and 2200, end before 100,000 in medium-sized domains,
and end before 5,000,000 in large-sized domains. New DNTs are created by incrementing
previous ones. According to the Microsoft website, the maximum possible DNT is
231 (2,147,483,648).
**MIDs on Domain Controllers are DNTs**
The fact that DCs use DNTs as MIDs is convenient since, in this way, DCs don’t need to
maintain an in-memory correspondence table between MIDs and GUIDs for each object. The
downside is that an NSPI client can request any DNT skipping the MID-assigning process.
## Requesting DNTs via Exchange
Let’s construct a table with approximate MID ranges we have discovered:
**MID Range** **Used to**
0x00000000 .. 0x0000000F Trigger specific behaviors in specific methods
(e.g., indicating the end of a table)
0x00000010 .. 0x7FFFFFFF Used by Domain Controllers as MIDs and DNTs
0xFFFFFFF0 .. 0x80000000 Used by Exchange as dynamically assigned MIDs
It’s clear Domain Controllers MIDs and Exchange MIDs are not intersecting. It’s done on
purpose:
**Exchange allows proxying DC MIDs to and from the end-user**
This is one of the ways how Exchange devolves data matching operations to Domain
Controllers. An example of an operation that clearly shows this can be NspiUpdateStat:
-----
Calling the NspiUpdateStat operation via MS Exchange
In fact, in Exchange 2003, MS-OXNSPI didn’t exist and the future protocol named MSOXABREF returned a Domain Controller address to the client. Next, the client contacted the
MS-NSPI interface on a DC via RPC Proxy without passing traffic through Exchange.
After 2003, NSPI implementation started to move from DCs to Exchange, and you will find
the NSPI Proxy Interface term in books of that time. In 2011, the initial MS-OXNSPI
specification was published, but internally it’s still based on Domain Controller NSPI
endpoints.
This story also explains why we see the 593/tcp port with ncacn_http endpoint mapper on
every DC nowadays. This is the port for Outlook 2003 to locate MS-NSPI interface via RPC
Proxies.
If you are wondering if we can look up all DNTs from zero to a large number as MIDs via
Exchange, this is exactly how our tool will get all Active Directory records.
## The Tool’s Overview
The exchanger.py utility was developed to conduct all described movements:
-----
Displaying supported attacks in exchanger.py
The list-tables attack lists Address Books and can count entities in every one of them:
Example usage of the list-tables attack
-----
The dump-tables attack can dump any specified Address Book by its name or GUID. It
supports requesting all the properties, or one of the predefined set of fields. It’s capable of
getting any number of rows via one request:
The help of the dump-tables attack
-----
Example usage of the dump-tables attack
The guid-known attack returns Active Directory objects by their GUIDs. It’s capable of looking
up GUIDs from a specified file.
Example usage of the guid-known attack
-----
The dnt-lookup option dumps all Active Directory records via requesting DNTs. It requests
multiple DNTs at one time to speed up the attack and reduce traffic:
Example usage of the dnt-lookup attack
The dnt-lookup attack supports the -output-file flag to write the output to a file, as the output
could be larger than 1 GB. The output file will include, but will not be limited to: user
thumbnails, all description and info fields, user certificates, machine certificates (including
machine NetBIOS names), subnets, and printer URLs.
## The Tool’s Internal Features
The internal exchanger.py features:
Python2/Python3 compatibility
NTLM and Basic authentication, including Pass-The-Hash attack
TLS SNI support; HTTP Chunked Transfer Encoding support
Full Unicode compliance
RPC over HTTP v2 implementation tested on 20+ targets
RPC Fragmentation and RPC over HTTP v2 Flow control
MS-OXABREF implementation
MS-NSPI/MS-OXNSPI implementation
-----
Complete OXNSPI/NSPI/MAPI fields database
Optimized NDR parser to work with large-sized RPC results
The tool doesn’t support usage of the Autodiscover service, since during many penetration
tests, this service was blocked or it was almost impossible to guess an email to get its
output.
When Basic is forced or Microsoft TMG is covering the Exchange, the tool will not be able to
get the RPC Server name from NTLMSSP, or this name will not work. If this happens,
manually request the RPC Server name via Autodiscover or find it in HTTP headers, in
sources of OWA login form, or in mail headers of emails from the server and set it in -rpc_hostname flag:_
Examples of setting -rpc-hostname flag
If you are not sure in what hostname the tool is getting from NTLMSSP, use -debug flag to
show this information and other useful debugging output.
## The Tool’s Limitations
-----
The tool was developed with support for any Exchange configuration and was tested in all
such cases. However, there are two issues that can occur:
**Issue with Multi-Tenant Configurations**
When Exchange uses multiple Active Directory domains, the dnt-lookup attack may crash a
Domain Controller.
Probably no one has ever used all the features of MS-NSPI, especially on Global Catalog
Domain Controllers, and the ntdsai.dll library may throw some unhandled exceptions which
result in lsass.exe termination and a reboot. We were unable to consistently reproduce this
behavior.
The list-tables, dump-tables and guid-known attacks are safe and work fine with Exchange
Multi-Tenant Configurations.
**Issue with Nginx**
If MS Exchange is running behind an nginx server that was not specially configured for
Exchange, the nginx will buffer data in RPC IN/OUT Channels and release them by 4k/8k
size blocks. This will break our tool and MS Outlook as well.
We’d probably can develop a workaround for this by expanding RPC traffic with unnecessary
data.
## Getting The Tool
The exchanger.py tool, and rpcmap.py and rpcdump.py utilities are now avaliable in the
[official Impacket repository: https://github.com/SecureAuthCorp/impacket](https://github.com/SecureAuthCorp/impacket)
Thanks [@agsolino for merging!](https://twitter.com/agsolino)
I hope we’ll see an offline OAB unpacker and MS-OXCRPC and MAPI implementation with
at least Ruler functions in exchanger.py in the future.
## Mitigations
We recommend that all our clients use client certificates or a VPN to provide remote access
to employees. No Exchange, or other domain services should be available directly from the
Internet.
-----