Skip to content
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

Port msmailprobe(Nick Powers) + Cleanup for GO bridge #10964

Merged
merged 7 commits into from Dec 4, 2018

Conversation

clee-r7
Copy link
Contributor

@clee-r7 clee-r7 commented Nov 14, 2018

OWA (Outlook Webapp) is vulnerable to time-based user enumeration attacks.
This module leverages all known, and even some lesser-known services exposed by default
Exchange installations to enumerate email.
Error-based user enumeration for Office 365 integrated email addresses

Verification

  • Start msfconsole
  • use auxiliary/scanner/msmail/exchange_enum
  • set (EMAILorEMAIL_FILE)
  • run
  • creds
    Results should look something like below if valid users were found:
host      origin    service        public  private  realm  private_type
----      ------    -------        ------  -------  -----  ------------
<ip>      <ip>      443/tcp (owa)  chris@somecompany.com

OWA (Outlook Webapp) is vulnerable to time-based user enumeration attacks.
This module leverages all known, and even some lesser-known services exposed by default
Exchange installations to enumerate users. It also targets Office 365 for error-based user enumeration.
Identify Command

  • Used for gathering information about a host that may be pointed towards an Exchange or o365 tied domain
  • Queries for specific DNS records related to Office 365 integration
  • Attempts to extract internal domain name for onprem instance of Exchange
  • Identifies services vulnerable to time-based user enumeration for onprem Exchange
  • Lists password-sprayable services exposed for onprem Exchange host
    Note: Currently uses RHOSTS which resolves to an IP which is NOT desired, this is currently being fixed

Verification

  • Start msfconsole
  • use auxiliary/scanner/msmail/host_id
  • set RHOSTS <target>
  • run
    Results should look like below:
msf5 > use auxiliary/scanner/msmail/host_id
msf5 auxiliary(scanner/msmail/host_id) > set RHOSTS <host>
RHOSTS => <host>
msf5 auxiliary(scanner/msmail/host_id) > run
[*] Running for <ip>...
[*] Attempting to harvest internal domain:
[*] Internal Domain:
[*] <domain>
[*] [-] Domain is not using o365 resources.
[*] Identifying endpoints vulnerable to time-based enumeration:
[*] [+] https://<host>/Microsoft-Server-ActiveSync
[*] [+] https://<host>/autodiscover/autodiscover.xml
[*] [+] https://<host>/owa
[*] Identifying exposed Exchange endpoints for potential spraying:
[*] [+] https://<host>/oab
[*] [+] https://<host>/ews

OWA (Outlook Webapp) is vulnerable to time-based user enumeration attacks.
This module leverages all known, and even some lesser-known services exposed by default
Exchange installations to enumerate users. It also targets Office 365 for error-based user enumeration.

  • Error-based user enumeration for on premise Exchange services
    Note: Currently uses RHOSTS which resolves to an IP which is NOT desired, this is currently being fixed

Verification

  • Start msfconsole
  • use auxiliary/scanner/msmail/onprem_enum
  • set RHOSTS <target>
  • set (USERorUSER_FILE`)
  • run
  • creds
    Results should look something like below if valid users were found:
host      origin    service        public  private  realm  private_type
----      ------    -------        ------  -------  -----  ------------
10.1.1.1  10.1.1.1  443/tcp (owa)
10.1.1.1  10.1.1.1  443/tcp (owa)  chris

@clee-r7 clee-r7 added the external modules PRs dealing with modules run as their own process label Nov 14, 2018
@busterb
Copy link
Member

busterb commented Nov 20, 2018

The .md file is in a path where not only does it not actually work in Metasploit, but the module actually fails to load. Please move it to the path with all other documentation files are (2 other PRs have landed in the same way; people need to please start using the info -d command to test documentation).

@busterb
Copy link
Member

busterb commented Nov 20, 2018

The side-effect of putting the .md file where it is is this in the log:

[11/20/2018 10:09:41] [e(0)] core: /Users/bcook/projects/metasploit-framework/modules/auxiliary/scanner/msmail/exchange_enumerator.md failed to load due to the following error:
Errno::ENOENT

@jmartin-tech
Copy link
Contributor

Jenkins test this please.

@@ -142,7 +142,7 @@ def harvest_process
elsif Process.kill('TERM', self.wait_thread.pid) && self.wait_thread.join(10)
self.exit_status = self.wait_thread.value
else
Procoess.kill('KILL', self.wait_thread.pid)
Process.kill('KILL', self.wait_thread.pid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops!

Transport: tr,
}
req, err := http.NewRequest("GET", URI, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a MSF configured parameter

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's sorta a WIP thing: #9228

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah right!

"time"
)

func WebRequestCodeResponse(URI string) int {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try and loop back on a patch on this, but realistically this should probably return an http.Response and error instead of an integer.

Transport: tr,
}
req, err := http.NewRequest("GET", urlToHarvest, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also seems like it should be MSF defined, but it does switch to a "desktop" UA. I talked to Nick and he says that this was to simulate the "real devices" for the devices that normally hit then endpoints (ie a phone generally only accesses the ActiveSync)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have an old PR of mine that's supposed to cleanup UA handling and make it work properly for external modules. I should go back and finish it up. Don't think it blocks this though.


**Note:** Currently uses RHOSTS which resolves to an IP which is NOT desired, this is currently being fixed

## Verification
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace these with some redacted test runs, so someone looking at the docs later would see what the output of this module should look like

"protocol": protocol,
"fullname": "auxiliary/scanner/msmail/msmail_enum",
}
module.ReportCredentialLogin(user,"", opts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't gofmt pick up spacing things like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why yes - I'm not sure why IDE doesn't auto run this

}.merge(service_data)

if data.has_key?(:password)
print_warning "In pass"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a debug statement from development?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bwhaha - thanks

gopath = ENV['GOPATH'] || ''
self.env = self.env.merge({ 'GOPATH' => File.expand_path('../go', __FILE__) + File::PATH_SEPARATOR + gopath})
default_go_path = ENV['GOPATH'] || ''
shared_module_lib_path = File.dirname(module_path) + "/shared"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using File.join for this:

shared_module_lib_path = File.join(File.dirname(module_path), 'shared')

go_path = go_path + File::PATH_SEPARATOR + shared_module_lib_path
end

self.env = self.env.merge({ 'GOPATH' => go_path})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: space after {, however, no space before }.

"service_name": service,
"address": ip,
"protocol": protocol,
"fullname": "auxiliary/scanner/msmail/msmail_enum",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to determine the fullname programmatically?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you figure it out let me know :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The report method should not need this. The Msf::Module::External mixin has access to this info and should be the one using it

"protocol": protocol,
"fullname": "auxiliary/scanner/msmail/msmail_enum",
}
module.ReportCredentialLogin(user,"", opts)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type of interface makes it impossible to report just a username vs a valid login with an empty password.

msfLog(message, "error")
}

func msfLog(message string, level string) {
Copy link
Contributor

@mkienow-r7 mkienow-r7 Dec 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should behave more like the log method in lib/msf/core/modules/external/python/metasploit/cli.py, otherwise, all callers become responsible for adding the leading log status indicators ([*], [!], [+], etc) to the actual messages themselves. This could result in many inconsistencies in the log.

Copy link
Member

@busterb busterb Dec 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the 'level' string makes metasploit display the correct character at the beginning of the message already. So this should be fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cli.py is something that interprets the output of the message that comes from a module like this, so it's a different thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unsure of that since there are plenty of locations in this PR where module.LogInfo is being called with a leading indicator in the message string.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, you are right.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, all of the 'mux.Lock/Unlock' code needs to be fixed

@busterb
Copy link
Member

busterb commented Dec 3, 2018

I think this is good to go, we can continue improving in the tree. Thanks all!

Also, oops, hit the wrong button!

@busterb busterb closed this Dec 3, 2018
@busterb busterb reopened this Dec 3, 2018
@busterb
Copy link
Member

busterb commented Dec 3, 2018

Shouldn't auxiliary/scanner/msmail/exchange_enum just have an 'RHOSTS' with a default value of the normal target? Seems silly to force the user to set a value since there actually is one it uses. Also, unregistering or even never registering datastore values is possible. You might just have to declare a new template type though.

@busterb busterb self-assigned this Dec 4, 2018
@busterb
Copy link
Member

busterb commented Dec 4, 2018

sorted out above comment offline, going to land and iterate from there

@acammack-r7
Copy link
Contributor

@busterb, there was still a lot that needs to be fixed. Are we keeping track of that anywhere besides this PR?

@busterb
Copy link
Member

busterb commented Dec 4, 2018

@clee-r7 are you going to do that? @mkienow-r7 has some valid points that I missed in time.
The mux code here should all be moved into the library as well.

@busterb
Copy link
Member

busterb commented Dec 4, 2018

Chatted with @clee-r7 , he'll take care of the additional issues. Thanks!

@busterb
Copy link
Member

busterb commented Dec 19, 2018

Release Notes

This adds additional support for modules written in Go, specifically adding auxiliary scanner and reporting functionality. It also adds three modules for enumerating users with Microsoft Exchange and Office 365.

@gdavidson-r7 gdavidson-r7 added the rn-enhancement release notes enhancement label Dec 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external modules PRs dealing with modules run as their own process rn-enhancement release notes enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants