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

Improve regex parsing in lotus_domino_hashes #16505

Merged
merged 3 commits into from May 19, 2022

Conversation

AdrianVollmer
Copy link
Contributor

  • The closing quotes after the VALUE attribute were not escaped. This
    commit adds them.
  • The regex assumed that the short name does not contain whitespace.
    I am looking at a Domino instance where the short name DOES contain
    whitespace. This commit changes the regex such that the value is
    assumed to not contain a quote before the closing quote. Of course,
    there could be an escaped quote inside quotes in the HTML source, but
    if we want to do it properly, we'd need an HTML parser which exceeds
    my modest ruby skills.
  • The fields $dspHTTPPassword and dspHTTPPassword (without the
    dollar sign) can both contain the hash. The code assumed that only up
    to one of those fields contain a hash. This leads to the hash being
    printed twice in the output in my case. This commit fixes this.

Note that I did not replace the deprecated report_auth_info function.

Verification

  1. Locate a vulnerable instance of Lotus Domino where at least one account uses a whitespace
  2. run msfconsole
  3. use auxillary/scanner/lotus/lotus_domino_hashes
  4. Provide RHOST and credentials
  5. Run
  6. Observe that reported user name is NULL
  7. Repeat after applying this patch and observe correct user name

Unfortunately I can't provide a PCAP (it's TLS encrypted anyway) or screen recordings because it would contain data protected by an NDA. I do not have a test instance. All I can offer is this:

Before:

14:43:44>192.168.137.16[0] auxiliary(scanner/lotus/lotus_domino_hashes) > run

[*] [2022.04.26-14:43:44] XX.XX.XX.XX:443       - Lotus Domino - Trying dump password hashes with given credentials
[+] [2022.04.26-14:43:44] XX.XX.XX.XX:443       - Lotus Domino - SUCCESSFUL authentication for 'XXXXXXXX'
[*] [2022.04.26-14:43:44] XX.XX.XX.XX:443       - Lotus Domino - Getting password hashes
[+] [2022.04.26-14:43:45] XX.XX.XX.XX:443       - Lotus Domino - Account Found: NULL, NULL, (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)(FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

After:

14:51:13>192.168.137.16[0] auxiliary(scanner/lotus/lotus_domino_hashes) > run

[*] [2022.04.26-14:51:13] XX.XX.XX.XX:443       - Lotus Domino - Trying dump password hashes with given credentials
[+] [2022.04.26-14:51:13] XX.XX.XX.XX:443       - Lotus Domino - SUCCESSFUL authentication for 'XXXXXXXX'
[*] [2022.04.26-14:51:13] XX.XX.XX.XX:443       - Lotus Domino - Getting password hashes
[+] [2022.04.26-14:51:14] XX.XX.XX.XX:443       - Lotus Domino - Account Found: <Firstname> <Lastname>, NULL, (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

* The closing quotes after the `VALUE` attribute were not escaped. This
  commit adds them
* The regex assumed that the short name does not contain whitespace.
  I am looking at a Domino instance where the short name DOES contain
  whitespace. This commit changes the regex such that the value is
  assumed to not contain a quote before the closing quote. Of course,
  there could be an escaped quote inside quotes in the HTML source, but
  if we want to do it properly, we'd need an HTML parser which exceeds
  my modest ruby skills.
* The fields `$dspHTTPPassword` and `dspHTTPPassword` (without the
  dollar sign) can both contain the hash. The code assumed that only up
  to one of those fields contain a hash. This leads to the hash being
  printed twice in the output in my case.
@jheysel-r7 jheysel-r7 self-assigned this Apr 27, 2022
Copy link
Contributor

@jheysel-r7 jheysel-r7 left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution @AdrianVollmer, looks great, just one suggestion. Wrote a quick unit test as I wasn't able to find a target:

Test script and output

  test_strings = ['<INPUT NAME="ShortName" TYPE=TESTTYPE VALUE="test name"  
<INPUT NAME="InternetAddress" TYPE=TESTTYPE VALUE="test_IP"  
<INPUT NAME="$?dspHTTPPassword" TYPE=TESTTYPE VALUE="test_hash_dollar_sign"  
<INPUT NAME="?dspHTTPPassword" TYPE=TESTTYPE VALUE="test_hash"',  
  
'<INPUT NAME="ShortName" TYPE=TESTTYPE VALUE="test name"  
<INPUT NAME="InternetAddress" TYPE=TESTTYPE VALUE="test_IP"  
<INPUT NAME="$?dspHTTPPassword" TYPE=TESTTYPE VALUE=""  
<INPUT NAME="?dspHTTPPassword" TYPE=TESTTYPE VALUE="test_hash"',  
  
'<INPUT NAME="ShortName" TYPE=TESTTYPE VALUE="test name"  
<INPUT NAME="InternetAddress" TYPE=TESTTYPE VALUE="test_IP"  
<INPUT NAME="$?dspHTTPPassword" TYPE=TESTTYPE VALUE="   "  
<INPUT NAME="?dspHTTPPassword" TYPE=TESTTYPE VALUE="test_hash"']  
  
  
test_strings.each do |test_string|  
  
  short_name = test_string.scan(/<INPUT NAME=\"ShortName\" TYPE=(?:.*) VALUE=\"([^"]+)\"/i).join  
  user_mail = test_string.scan(/<INPUT NAME=\"InternetAddress\" TYPE=(?:.*) VALUE=\"([^"]+)\"/i).join  
  pass_hash_candidates = test_string.scan(/<INPUT NAME=\"[\$]*\?dspHTTPPassword\" TYPE=(?:.*) VALUE=\"([^"]+)\"/i)  
  
  if pass_hash_candidates[0][0].nil? || pass_hash_candidates[0][0].strip.empty?  
    pass_hash = pass_hash_candidates[1][0] unless (pass_hash_candidates[1][0].nil? || pass_hash_candidates[1][0].strip.empty?)  
  else  
    pass_hash = pass_hash_candidates[0][0]  
  end  
  puts("Shortname: #{short_name}")  
  puts("user_mail: #{user_mail}")  
  puts("pass_hash_candidates: #{pass_hash_candidates}")  
  puts("pass_hash: #{pass_hash}","")  
end
Shortname: test name
user_mail: test_IP
pass_hash_candidates: [["test_hash_dollar_sign"], ["test_hash"]]
pass_hash: test_hash_dollar_sign

Shortname: test name
user_mail: test_IP
pass_hash_candidates: [["test_hash"]]
pass_hash: test_hash

Shortname: test name
user_mail: test_IP
pass_hash_candidates: [["   "], ["test_hash"]]
pass_hash: test_hash

modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb Outdated Show resolved Hide resolved
Co-authored-by: jheysel-r7 <Jack_Heysel@rapid7.com>
@AdrianVollmer
Copy link
Contributor Author

Maybe my ruby skills are better described by "poor" than "modest" ;) thanks for the suggestion.

@cdelafuente-r7
Copy link
Contributor

Thanks for updating this @AdrianVollmer. Since it would be very challenging for us to setup a test environment, would you mind setting the HttpTrace option, and send us the output to verify the changes actually fix the issue. Also, that would be great to have the HTTP trace for both before and after the fix.

We could sanitize the data and use these traces as an input for unit test (specs).

@AdrianVollmer
Copy link
Contributor Author

That's 97k lines of output - each. I'll see what I can do, but that's a lot of data to sanitize...

@cdelafuente-r7
Copy link
Contributor

Regarding the HttpTrace data, these can be sent to the msfdev [at] metasploit.com email. Please, just add the related PR title and reference in the subject. We can take care of extracting the relevant information for the unit test and sanitizing it, no need for the entire trace. Thanks!

@AdrianVollmer
Copy link
Contributor Author

Thanks for the offer, but I have to sanitize this even before sending it to you, or else it would violate the NDA. I'm on it.

doc = res.get_html_document
short_name = doc.xpath('//input[@name="ShortName"]/@value').text
user_mail = doc.xpath('//input[@name="InternetAddress"]/@value').text
pass_hash = doc.xpath('//input[@name="$dspHTTPPassword" or @name="dspHTTPPassword"]/@value').first&.text
Copy link
Contributor

Choose a reason for hiding this comment

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

Will await the http logs, but we should just double check the case sensitivity around the node name of input or INPUT

@AdrianVollmer
Copy link
Contributor Author

logs are sent to the mail address above

@cdelafuente-r7
Copy link
Contributor

I confirmed, we received the logs. Thank you!

@jheysel-r7 jheysel-r7 merged commit 19abce7 into rapid7:master May 19, 2022
@jheysel-r7
Copy link
Contributor

Before

[+] [2022.04.28-17:07:00] 66.214.238.26.:443       - Lotus Domino - Account Found: NULL, NULL, (Fd9A78e5DEA2A6D2f04F0cCC5bE8C1cf)(Fd9A78e5DEA2A6D2f04F0cCC5bE8C1cf)
[!] [2022.04.28-17:07:00] *** auxiliary/scanner/lotus/lotus_domino_hashes is still calling the deprecated report_auth_info method! This needs to be updated!
[!] [2022.04.28-17:07:00] *** For detailed information about LoginScanners and the Credentials objects see:
[!] [2022.04.28-17:07:00]      https://github.com/rapid7/metasploit-framework/wiki/Creating-Metasploit-Framework-LoginScanners
[!] [2022.04.28-17:07:00]      https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-HTTP-LoginScanner-Module
[!] [2022.04.28-17:07:00] *** For examples of modules converted to just report credentials without report_auth_info, see:
[!] [2022.04.28-17:07:00]      https://github.com/rapid7/metasploit-framework/pull/5376
[!] [2022.04.28-17:07:00]      https://github.com/rapid7/metasploit-framework/pull/5377
[*] [2022.04.28-17:07:00] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
17:07:00>192.168.11.2[0] auxiliary(scanner/lotus/lotus_domino_hashes) >

After:

[+] [2022.04.29-16:18:39] 66.214.238.26.:443       - Lotus Domino - Account Found: Kwggr Wrbcpw, NULL, (Fd9A78e5DEA2A6D2f04F0cCC5bE8C1cf)
[!] [2022.04.29-16:18:39] *** auxiliary/scanner/lotus/lotus_domino_hashes is still calling the deprecated report_auth_info method! This needs to be updated!
[!] [2022.04.29-16:18:39] *** For detailed information about LoginScanners and the Credentials objects see:
[!] [2022.04.29-16:18:39]      https://github.com/rapid7/metasploit-framework/wiki/Creating-Metasploit-Framework-LoginScanners
[!] [2022.04.29-16:18:39]      https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-HTTP-LoginScanner-Module
[!] [2022.04.29-16:18:39] *** For examples of modules converted to just report credentials without report_auth_info, see:
[!] [2022.04.29-16:18:39]      https://github.com/rapid7/metasploit-framework/pull/5376
[!] [2022.04.29-16:18:39]      https://github.com/rapid7/metasploit-framework/pull/5377
[*] [2022.04.29-16:18:39] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
16:18:39>10.8.0.16[0] auxiliary(scanner/lotus/lotus_domino_hashes) >

Tested locally and verified these changes fix the parsing of the value, shortname, dspHTTPPassword (with and without the $) and the printing of the duplicate hash.
Thanks @AdrianVollmer for the fix and for sending over the logs!

@cdelafuente-r7 cdelafuente-r7 added the rn-fix release notes fix label May 20, 2022
@cdelafuente-r7
Copy link
Contributor

Release Notes

This fixes an issue in the auxiliary/scanner/lotus/lotus_domino_hashes #dump_hashes parsing logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rn-fix release notes fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants