rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
33.79k stars 13.9k forks source link

Can HttpClient use FQDN instead of IP addresses? #15757

Closed WayneJLee closed 1 year ago

WayneJLee commented 2 years ago

Summary

Currently tweaking a PoC and for some reason, Metasploit is resolving the FQDN set in RHOST and using the IP address instead when making requests. This obviously poses a challenge when dealing with applications behind Cloudflare and I'm struggling to find any documentation to force HttpClient to use an FQDN.

Does anyone have any idea on how to overcome this?

bcoles commented 2 years ago

How are you sending HTTP requests? Are you using send_request_cgi ?

Msf::Exploit::Remote::HttpClient is supposed to respect the RHOST value when setting the Host header in HTTP/1.1 and HTTP2 requests.

msf6 > use auxiliary/scanner/http/test 
msf6 auxiliary(scanner/http/test) > egrep test /etc/hosts
[*] exec: egrep test /etc/hosts

127.0.0.1 test.local
msf6 auxiliary(scanner/http/test) > set rhosts test.local
rhosts => test.local
msf6 auxiliary(scanner/http/test) > set httptrace true
httptrace => true
msf6 auxiliary(scanner/http/test) > run

####################
# Request:
####################
GET / HTTP/1.1
Host: test.local:1337
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

^C[*] Caught interrupt from the console...
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/http/test) > 
# nc -lvp 1337
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::1337
Ncat: Listening on 0.0.0.0:1337
Ncat: Connection from 127.0.0.1.
Ncat: Connection from 127.0.0.1:43187.
GET / HTTP/1.1
Host: test.local:1337
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HttpClient
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report

  def initialize
    super(
      'Name'        => 'test',
      'Description' => %q{
        test
      },
      'Author'      => 'bcoles',
      'License'     => MSF_LICENSE
    )
    register_options [Opt::RPORT(1337)]
  end

  def run_host(ip)
    puts send_request_cgi({
      'url' => '/test'
    })

  rescue OpenSSL::SSL::SSLError
  rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError
  rescue ::Timeout::Error, ::Errno::EPIPE
  end
end
WayneJLee commented 2 years ago

Yep I am. Below is the output of the trace and I also added print_status(datastore['RHOST']) at the start of the function.

msf6 exploit(itop/itop_rce) > set RHOST target.site.com
RHOST => target.site.com
msf6 exploit(itop/itop_rce) > run
[*] Exploiting target 172.67.159.126

[*] 172.67.159.126
####################
# Request:
####################
GET /pages/UI.php HTTP/1.1
Host: target.site.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

SSL_connect returned=1 errno=0 state=error: sslv3 alert handshake failure
[-] Exploit failed [unreachable]: OpenSSL::SSL::SSLError SSL_connect returned=1 errno=0 state=error: sslv3 alert handshake failure
[*] Exploiting target 104.21.41.30
[*] 104.21.41.30
####################
# Request:
####################
GET /pages/UI.php HTTP/1.1
Host: target.site.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

SSL_connect returned=1 errno=0 state=error: sslv3 alert handshake failure
[-] Exploit failed [unreachable]: OpenSSL::SSL::SSLError SSL_connect returned=1 errno=0 state=error: sslv3 alert handshake failure
[*] Exploiting target 2606:4700:3036::ac43:9f7e
[*] 2606:4700:3036::ac43:9f7e
####################
# Request:
####################
GET /pages/UI.php HTTP/1.1
Host: target.site.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

I've also included a screencap from an intercepted request on Burp. You can see in Burp that it's sending the request to the IP address instead of the FQDN that was set, causing requests to error out. Sending the same request in Repeater also results in a handshake failure, possibly due to some security mechanism in place by Cloudflare.

image

If I manually replace the target in Burp, the request gets handled correctly.

Here's a link to the exploit for reference - https://github.com/attackercan/itop-2.4.0-rce/blob/master/itop_rce.rb

I've made some changes to it but not much. The original script had some important values hardcoded and that's all I tweaked (besides adding in additional print statements for debugging).

jmartin-tech commented 2 years ago

The error reported should not be for an untrusted cert. It looks like the SSL protocol requested is failing to negotiate.

SSL_connect returned=1 errno=0 state=error: sslv3 alert handshake failure

When there is a certificate mis-match the error should look like:

SSL_connect returned=1 errno=0 state=error: certificate verify failed

I suspect a supported SSL version may need to be forced for the connection with the remote host. That or the openssl version ruby is loading does not support any protocols the server will allow.

helmutye0 commented 2 years ago

I'm encountering this issue as well when using scanner/http/dir_scanner with SSL set to true.

SSL_connect returned=1 errno=0 state=error: sslv3 alert handshake failure

When I proxy through Burp Suite I see the same thing--the request is being sent with the resolved IP address as the target and the RHOST value as the Host header. This results in an SSL failure when sent to an IP address that is hosting multiple sites.

Setting the specified RHOST as the host header isn't sufficient to negotiate SSL in these cases--the FQDN needs to be sent as the target.

WayneJLee commented 2 years ago

@jmartin-r7 I have tried forcing diff SSL versions through Burp as well with no success. I came across this article a while back on Domain Fronting and it explains some of the magic behind CloudFlare such as the usage of Server Name Indicator fields, which I'm not sure is supported by the MSF libraries at the moment.

github-actions[bot] commented 2 years ago

Hi!

This issue has been left open with no activity for a while now.

We get a lot of issues, so we currently close issues after 60 days of inactivity. It’s been at least 30 days since the last update here. If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request.

adfoster-r7 commented 2 years ago

I don't have replication steps to verify the original issue; but I think this was fixed by specifying the service name indication (SNI) for the ssl connections

https://github.com/rapid7/metasploit-framework/pull/16499

adfoster-r7 commented 1 year ago

I believe this is fixed by the SNI changes; Since there's been no replies in a while - I'll mark this as closed for now :+1: