Skip to content

BishopFox/exchange-scanner

Microsoft Exchange Server Scanner

example scan

Description

This tool scans several common public-facing services on a target host in order to detect Microsoft Exchange Server and fingerprint its software version if possible.

To do this, it uses the following techniques:

  • Outlook Web Access (OWA) fingerprinting by response headers, login page contents, and favicon hashes
  • Exchange Control Panel (ECP) export tool fingerprinting by XML responses
  • Autodiscover endpoint fingerprinting by response headers
  • Service fingerprinting for SMTP, IMAP, and POP3 on common ports by service banners

Detected build numbers are matched against a version table scraped from Microsoft that covers every release from Exchange Server 5.5 through Exchange Server Subscription Edition (SE), including Service Pack (SP), Cumulative Update (CU), Security Update (SU), Hotfix Update (HU), and Update Rollup (RU) levels. Matches are reported with a product name, release date, and CPE strings in the NVD dictionary format.

Getting Started

Prerequisites

The recommended way to run the scanner is with Docker, which requires no local dependencies beyond Docker itself. To run the script directly instead, it was designed for use on 64-bit Debian Linux, but should work with any Linux variant supported by Python 3, dnsx, and fingerprintx (with minor modifications to the installation script).

Installation

Docker (recommended)

Build the image. It bundles Python, the pinned Python packages, and version-locked dnsx and fingerprintx binaries, and scrapes the Exchange Server version table from Microsoft at build time:

docker build -t exchange-scanner .

Then run the scanner, passing the same arguments you would pass to the script (described under Usage below):

# Scan a single target
docker run --rm exchange-scanner -q -t 192.168.5.3

# Scan a list of targets (mount the file into the container)
docker run --rm -v "$PWD/targets.txt:/app/targets.txt" exchange-scanner -l targets.txt

Rebuild the image to refresh the version table.

Manual installation

Run scripts/install-requirements.sh to install the required tools, packages, and other dependencies. Python packages are pinned to specific versions in scripts/requirements.txt.

Feel free to re-run scripts/get-exchange-versions.py separately at any time to update the software version table found in exchange-versions.json.

Usage

Run the exchange-scanner.py script with -h to view usage details:

❯ ./exchange-scanner.py -h
usage: exchange-scanner.py [-h] [-q] [-d] [-x TIMEOUT] [-o OUTFILE] (-t TARGET | -l LIST)

optional arguments:
  -h, --help            show this help message and exit
  -q, --quiet           Suppress log output (except errors)
  -d, --debug           Print debugging messages
  -x TIMEOUT, --timeout TIMEOUT
                        Set timeout for HTTP requests (defaults to 3 seconds)
  -o OUTFILE, --outfile OUTFILE
                        Save output to a file instead of writing to stdout
  -t TARGET, --target TARGET
                        A single hostname or IP address to scan
  -l LIST, --list LIST  File containing a list of hostnames and/or IP addresses to scan (one per line)

Required: -t or -l

  • To scan a single target, use -t with a single hostname or IP address. If the hostname resolves to multiple IPs, the script will scan each of them separately.
  • To scan multiple targets at once, create a file with one hostname or IP address per line, then use -l with the name of the file.

Logging: To suppress most log output, use -q. To view more log detail, use -d.

Timeout: To change the maximum response time per HTTP request, specify a timeout value in seconds (the default is 3). Keep in mind that a single IP address can generate over 200 requests under certain circumstances (though most scans don't reach this volume), so a shorter timeout is generally preferred.

Output: Scan results are printed in JSON format by default. To save output to a file instead of printing to stdout, use -o with a filename.

Example

$ ./exchange-scanner.py -q -t 192.168.5.3
[
    {
        "hostname": "192.168.5.3",
        "ip_address": "192.168.5.3",
        "build_number": "15.2.1118",
        "exchange_services": [
            "https://192.168.5.3:443",
            "imaps://192.168.5.3:993"
        ],
        "product_name": "Exchange Server 2019 CU12 (2022H1)",
        "major_version": "2019",
        "update": "Cumulative Update 12",
        "security_update": null,
        "release_date": "2022-04-20",
        "recalled": false,
        "cpes": [
            "cpe:2.3:a:microsoft:exchange_server:2019:cumulative_update_12:*:*:*:*:*:*",
            "cpe:2.3:a:microsoft:outlook_web_access:2019:cumulative_update_12:*:*:*:*:*:*"
        ]
    }
]

Miscellany

Legal disclaimer

Usage of this tool for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state, and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program.

License

This project is licensed under the GNU General Public License.

Capabilities and Limitations

  • The scanner currently only checks default ports for default services.
  • It assumes the target is being scanned from an external perspective.
  • It uses fuzzy matching to determine versions when partial build numbers are found.
  • It also flags updates that Microsoft has recalled via a recalled field in its output.
  • CPE strings follow the NVD CPE dictionary format. Because the NVD dictionary tracks updates only down to the CU/SP/RU level (not SU/HU), those CPEs are best-effort and may not match a dictionary entry exactly. The full detected detail (exact build number, SU/HU level) is preserved in the other result fields.

About

Identify public-facing Microsoft Exchange servers and determine their software versions

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors