New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add External Module: office365userenum.py #10607

Merged
merged 3 commits into from Nov 13, 2018

Conversation

Projects
None yet
6 participants
@GrimHacker
Contributor

GrimHacker commented Sep 7, 2018

External python module compatible with v2 and v3.

Enumerate valid usernames (email addresses) from Office 365 using ActiveSync.
Differences in the HTTP Response code and HTTP Headers can be used to differentiate between:

  • Valid Username (Response code 401)
  • Valid Username and Password without 2FA (Response Code 200)
  • Valid Username and Password with 2FA (Response Code 403)
  • Invalid Username (Response code 404 with Header X-CasErrorCode: UserNotFound)

Note this behaviour appears to be limited to Office365, MS Exchange does not appear to be affected.

Microsoft Security Response Center stated on 2017-06-28 that this issue does not "meet the bar for security servicing". As such it is not expected to be fixed any time soon.

This script is maintaing the ability to run independently of MSF.

Verification

  • Create a file with candidate usernames (aka email addresses) for an Office365 domain /home/msfdev/users
  • Start msfconsole
  • use auxiliary/gather/office365userenum
  • set users /home/msfdev/users
  • set rhosts 127.0.0.1
  • run
  • Verify valid username returns [+] 401 VALID_USER valid_username@example.com:Password1
  • Verify invalid username returns [-] 404 INVALID_USER invalid_username@example.com:Password1
  • Document documentation/modules/auxiliary/gather/office365userenum.py

Example

msf5 > use auxiliary/gather/office365userenum 
msf5 auxiliary(gather/office365userenum) > info

       Name: Office 365 User Enumeration
     Module: auxiliary/gather/office365userenum
    License: GNU Public License v2.0
       Rank: Normal
  Disclosed: 2018-09-05

Provided by:
  Oliver Morton (GrimHacker) <grimhacker@grimhacker.com>

Check supported:
  Yes

Basic options:
  Name      Current Setting                                            Required  Description
  ----      ---------------                                            --------  -----------
  LOGFILE                                                              no        Log file
  OUTPUT                                                               no        Output file (will be appended to)
  PASSWORD  Password1                                                  yes       Password to use during enumeration.
  RHOSTS                                                               yes       The target address range or CIDR identifier
  RPORT     443                                                        no        IGNORE ME!
  THREADS   10                                                         yes       Maximum threads
  TIMEOUT   30                                                         yes       HTTP Timeout
  URL       https://outlook.office365.com/Microsoft-Server-ActiveSync  yes       ActiveSync URL
  USERS                                                                yes       Potential usernames file, one username per line
  VERBOSE   false                                                      yes       Debug logging

Description:
  Enumerate valid usernames (email addresses) from Office 365 using 
  ActiveSync. Differences in the HTTP Response code and HTTP Headers 
  can be used to differentiate between: - Valid Username (Response 
  code 401) - Valid Username and Password without 2FA (Response Code 
  200) - Valid Username and Password with 2FA (Response Code 403) - 
  Invalid Username (Response code 404 with Header X-CasErrorCode: 
  UserNotFound) Note this behaviour appears to be limited to 
  Office365, MS Exchange does not appear to be affected. Microsoft 
  Security Response Center stated on 2017-06-28 that this issue does 
  not "meet the bar for security servicing". As such it is not 
  expected to be fixed any time soon.

References:
  CVE: Not available
  https://grimhacker.com/2017/07/24/office365-activesync-username-enumeration/

msf5 auxiliary(gather/office365userenum) > set users /home/msfdev/users
users => /home/msfdev/users
msf5 auxiliary(gather/office365userenum) > set rhosts 127.0.0.1
RHOSTS => 127.0.0.1
msf5 auxiliary(gather/office365userenum) > run

[*] Running for 127.0.0.1...
[*] 

.       .1111...          | Title: office365userenum.py
    .10000000000011.   .. | Author: Oliver Morton (Sec-1 Ltd)
 .00              000...  | Email: oliverm@sec-1.com
1                  01..   | Description:
                    ..    | Enumerate valid usernames from Office 365 using
                   ..     | ActiveSync.
GrimHacker        ..      | Requires: Python 2.7 or 3.6, python-requests
                 ..       |
grimhacker.com  ..        |
@grimhacker    ..         |
----------------------------------------------------------------------------
    This program comes with ABSOLUTELY NO WARRANTY.
    This is free software, and you are welcome to redistribute it
    under certain conditions. See GPLv2 License.
----------------------------------------------------------------------------

[+] 401 VALID_USER valid_username@example.com:Password1
[-] 404 INVALID_USER invalid_username@example.com:Password1
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Help Requested

  • Metasploit is automatically adding RHOSTS as a mandatory option despite it not being required by the module. Renaming URL to RHOSTS prevents the module from working - outputs [*] Auxiliary module execution completed without running the module.
  • Metasploit requires RPORT when reporting credentials, the module does not require the port to be specified separately as this would be supplied in the URL if required.
  • There are reportedly some edge cases where 503 is returned.

GrimHacker added some commits Sep 6, 2018

Add office365userenum.py as external module
External python module compatible with v2 and v3.

Enumerate valid usernames (email addresses) from Office 365 using
ActiveSync.
Differences in the HTTP Response code and HTTP Headers can be used to
differentiate between:

 - Valid Username (Response code 401)

 - Valid Username and Password without 2FA (Response Code 200)

 - Valid Username and Password with 2FA (Response Code 403)

 - Invalid Username (Response code 404 with Header X-CasErrorCode: UserNotFound)

Note this behaviour appears to be limited to Office365, MS Exchange
does not appear to be affected.

Microsoft Security Response Center stated on 2017-06-28 that this issue
does not "meet the bar for security servicing". As such it is not
expected to be fixed any time soon.

This script is maintaing the ability to run independently of MSF.
Make Output and Log Files Optional
Change the 'required' attribute of the output and logfile options to
False.
Open output file for appending immediately before use and only if output
file name is configured.
@GrimHacker

This comment has been minimized.

Contributor

GrimHacker commented Sep 15, 2018

RHOSTS is automatically created as a required option despite my module not needing it and it not being specified in the metadata.
Even if I rewrite the module to assemble the url i need from rhosts, the value of rhosts is replaced with a list containing the results of a DNS lookup, which is useless in context.
If I have tried setting the type of RHOSTS in my metadata to address, string, raw, it doesn't seem to have any affect.
I tried setting an RHOST option, but RHOSTS is still automatically created.

@busterb

This comment has been minimized.

Contributor

busterb commented Sep 25, 2018

I think we need a different kind of module type to support what you want, which is non-automatic host resolution, and just plain URI-based targets. I think there are lots of other modules that also would prefer this method of operations rather than RHOSTS / RPORT, etc.

The RHOSTS argument comes from the underlying module template that gets instantiated automatically by Metasploit, as you noticed.

@0x41414141

This comment has been minimized.

Contributor

0x41414141 commented Oct 10, 2018

Is the different module type something in the pipeline you know of buster? I can either look into writing a different module template for external py modules or help Oliver port this to pure ruby (former option probably preferred)

@busterb

This comment has been minimized.

Contributor

busterb commented Nov 9, 2018

Sorry for the delay @GrimHacker - @clee-r7 is doing some research into this. Maybe we can sync up on the Slack team at some point to work out the details.

@busterb

This comment has been minimized.

Contributor

busterb commented Nov 13, 2018

I'm going to land this now and we can improve it in the tree. Just spoke with @clee-r7 about a path forward to make raw unresolved hosts available to modules in a backward compatible way, but that shouldn't block this.

@busterb busterb self-assigned this Nov 13, 2018

@bcook-r7 bcook-r7 merged commit 7604712 into rapid7:master Nov 13, 2018

3 checks passed

Metasploit Automation - Sanity Test Execution Successfully completed all tests.
Details
Metasploit Automation - Test Execution Successfully completed all tests.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

bcook-r7 pushed a commit that referenced this pull request Nov 13, 2018

msjenkins-r7 added a commit that referenced this pull request Nov 13, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment