-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
Update service mixins for NAT options #16250
Conversation
unless ip.nil? | ||
comm = Rex::Socket::SwitchBoard.best_comm(ip) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This avoids a crash if ip
is nil which is the case in some unit tests. If the IP is nil, and the comm should be automatically determined, it'll default to local.
@@ -26,7 +26,6 @@ def initialize(info = {}) | |||
|
|||
register_advanced_options( | |||
[ | |||
OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was unnecessary since the same option is inherited by the included SocketServer mixin.
@@ -193,8 +193,9 @@ def on_cred(creds) | |||
|
|||
def run | |||
@rsock = Rex::Socket::Tcp.create( | |||
'LocalHost' => datastore['SRVHOST'], | |||
'LocalPort' => datastore['SRVPORT'], | |||
'LocalHost' => bindhost, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be an existing issue, but are there any limitations with this solution in the scenario of a module wanting to have multiple different services with different bindports? For instance wanting to run an http server as well as an smb server in a module? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment not specific to this line of code, just an open question 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right it's an existing limitation. Hypothetically, if an exploit wanted to start both an HTTP server and an SMB server, that module author would need to decide if the SRVPORT
option should correspond to the SMB service, the HTTP service, or neither. Whichever one the SRVPORT
is not associated with will need to have its own port datastore option registered to replace SRVPORT and should have another option registered to replace ListenerBindPort
too which should be accounted for when the service is started. The way the service is started would also need to be updated to prevent the use of the default SRVHOST/SRVPORT options.
Edit Cool, confirmed I was indeed being an idiot - verified a pivoting scenario works as expected for me:
Previous message: I'm not sure if I'm being an idiot, and this is supposed to work, or if it's a feature request. But I was hoping to be able to use the So initial lab setup would be msfconsole having an open session between A<->B, and a target C which is only accessible via B flowchart LR
A("A\nmsfconsole\n192.168.123.1")
B("B\ncompromised target\n192.168.123.6")
C("C\nOther target\n 192.168.123.25")
A <-->| linux/x64/meterpreter_reverse_tcp\n192.168.123.1:4444| B
B <-->| | C
I'd like to spin up the So I was hoping to do something along the lines of: use multi/script/web_delivery
run ReverseListenerComm=-1 ReverseListenerBindAddress=192.168.123.6 ListenerBindAddress=192.168.123.6 lhost=192.168.123.1 srvhost=192.168.123.1 Which would then allow C to access the reverse listener flowchart LR
A("A\nmsfconsole\n192.168.123.1")
B("B\ncompromised target\n192.168.123.6\n(Now binding 8080 and 5000)")
C("C\nOther target\n 192.168.123.25")
A <-->| linux/x64/meterpreter_reverse_tcp\n192.168.123.1:4444| B
A <-->| multi/script/web_delivery\n192.168.123.1:8080| B
A <-->| python/meterpreter/reverse_tcp\n192.168.123.1:5000| B
B <-->| http://192.168.123.6:8080| C
Hopefully the visuals make sense🤞 From the TLV logging I see the reverse listener bind address get setup as expected, but not the reverse srv bind address:
|
@@ -172,19 +158,10 @@ def start_service(opts = {}) | |||
print_status("Intentionally using insecure SSL compression. Your operating system might not respect this!") | |||
end | |||
|
|||
print_status("Using URL: #{proto}://#{srvhost_addr}#{uopts['Path']}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the port was dropped here, was that intentional? 👀
[*] Using URL: http://192.168.123.6/R3ieTAhOv
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, that's a mistake. I was intending to leave the port out when it's the default based on the schema like #get_uri
does and I got mixed up. Thanks for catching this, fixed in 6e1d369.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs fixed still 👀
My lport is 8080 for the web delivery and the port is missing:
[*] Started reverse TCP handler on private_ip:4444
[*] Using URL: http://public_ip/iXjtZTZH7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally unrelated to this PR, I wish there was an easy way to see all the paths that were registered with the http service manager, or at least see where the web delivery module is running from. It's pretty easy to forget which paths are for what after the console screen's been cleared, and it's not possible to grab the info from the jobs
or service manager details from what I can see
msf6 exploit(multi/script/web_delivery) > jobs
Jobs
====
Id Name Payload Payload opts
-- ---- ------- ------------
2 Exploit: multi/script/web_delivery python/meterpreter/reverse_tcp tcp://x.x.x.x:4444
msf6 exploit(multi/script/web_delivery) > _servicemanager
Services
========
Id Name References
-- ---- ----------
0 HTTP Server 2
1 Rex::Proto::Http::Server8080-x.x.x.x-Rex::Socket::Comm::Local 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it looks like when I rebased, that change was lost. Let me do it again. Re-added in commit ff0ecfa.
I don't believe I'll be able to test the DNS functionality with the recent issues/pull requests for it: |
It'll crash if you do
Instead of returning nil from Rex::Socket::SwitchBoard.best_comm, return the local comm which Rex::Socket will defer to anyways.
6e1d369
to
a739083
Compare
Potentially pebkac - but it looks like the suggested DNS module doesn't work out of the box yet 👀 Not sure if I need to pull in #16364 - but from the git log, it looks like like the previous DNS fixes were pulled into this PR at least
|
I believe I've configured everything correctly, but it looks like the suggested log4shell module doesn't work for me:
I verified it works as expected locally before hand:
And it was tested against a newer version of the vulnerable log4shell app:
I'm guessing it's the custom http server which needs a similar tweak: metasploit-framework/modules/exploits/multi/http/log4shell_header_injection.rb Lines 266 to 278 in d6d8bd5
|
Tested a FTP module successfully, although there's really no use of For another http module I also tested the glue-code of |
The DNS issue appears to be unrelated. I was able to reproduce it using dig with the |
I went searching for similar patterns to the ldap code, and it seems like there might be some copy/pasta that we should probably align to use the new pattern - otherwise future folk will copy/paste code from these modules without this new logic present: metasploit-framework/modules/exploits/osx/browser/safari_file_policy.rb Lines 172 to 198 in da16aad
metasploit-framework/modules/auxiliary/gather/safari_file_url_navigation.rb Lines 219 to 247 in da16aad
metasploit-framework/modules/auxiliary/gather/apple_safari_ftp_url_cookie_theft.rb Lines 66 to 92 in da16aad
There may be other places too. Potentially the Happy for you to declare this out of scope of this particular pull request, just hoping to avoid future copy/pasting issues 😄 |
Verified:
|
Release NotesAdds new |
This PR adds capabilities to the service mixins listed below to enable them to start listeners in NATed environments. It does so by adding two new datastore options,
ListenerBindAddress
andListenerBindPort
. These names are intentionally similar to theReverseListenerBindAddress
andReverseListenerBindPort
options that are registered by the reverse_* handlers1, 2 and theListenerComm
option already registered by the SocketServer.The ReverseListerBindAddress allows the port on which the handler is bound to be different from that specified in LHOST. When only LHOST is specified, that IP address must be one that the system running the payload can connect to. This isn't feasible if Metasploit is running in a network behind a NAT with a port forwarding configuration. In this scenario, the public IP address specified in LHOST can't be bound to by the handler, so the ReverseListenerBindAddress allows it to be overridden. This PR updates the codebase to apply the same relation between ReverseListenerBindAddress and LHOST to ListenerBindAddress and SRVHOST. It solves the same problem, in the same way, but for modules that need to start listening services such as HTTP, LDAP, SMB, etc. The BindPort options serve the same purpose, allowing the port on which the service is bound to be different from the one the target is connecting to.
The following service listeners were updated as part of this PR:
Messages in the context of a location that targets should connect to (like URLs) were left unchanged. Messages that displayed where the service was listening were updated to use the actual bound address. Any instances that are incorrect should be called out.
Routing
Due to the way in which Metasploit's internal routing table works as provided by
Rex::Socket
if theListenerBindAddress
is to be routed through a session, then that session will be used as the comm to create the service. This is the exact say way that handlers work. An explicit comm can be specified using theListenerComm
andReverseListenerComm
options for services and handlers respectively.Demo
The following diagram outlines the topology of the network where 192.168.250.0/24 is the WAN on which the target Ubuntu system is and 192.168.199.0/24 is the LAN on which Metasploit Framework is running. The HTTP service and payload handler services are both running on Metasploit and the router has been configured with a port forward for both. In both cases, the port that is forwarded, is forwarded to the same port on the target, e.g. router:4444 to metasploit:4444.
When setting up Metasploit and the
exploit/multi/script/web_delivery
module, the first attempt that fails shows that theSRVHOST
address can not be bound to because 192.168.250.126 is not an IP address on the system where Metasploit is running. The user sets the two necessary options, the newListenerBindAddress
for the HTTP service and the existingReverseListenerBindAddress
for the reverse_tcp payload handler service. With that in place, the module works as intended. In the generated command output, the public address specified bySRVHOST
is clearly visible, showing what the target will connect to, while the staus output shows that the TCP handler is running on the private address.Testing
These changes are included in quite a few modules. Anything that starts an HTTP, FTP, LDAP, DNS, or SMB server using the provided mixins will have the new functionality.
For each of the new modules, they should all continue to work as intended. The
ListenerBindAddress
andListenerBindPort
options should alter how the socket is bound as visible bynetstat
or a similar monitoring utility.