metasploit-framework icon indicating copy to clipboard operation
metasploit-framework copied to clipboard

Meterpreter Portforward Breaks When Route is Added

Open Invoke-Mimikatz opened this issue 2 years ago • 4 comments

Steps to reproduce

How'd you do it?

  1. Get a Meterpreter session (I used windows/x64/meterpreter/reverse_tcp but IT DOESN'T MATTER)
  2. Start a Python HTTP server on port 80: python3 -m http.server 80
  3. Start a reverse port forward on the Meterpreter session: portfwd add -R -l 80 -L 127.0.0.1 -p 8888
  4. Observe the successful portforward on the Windows victim host: curl 127.0.0.1:8888
  5. Create a new route in Metasploit: route add 0 0 -1
  6. Re-observe the portforward on the Windows victim host: curl 127.0.0.1:8888. The portforward is now broken :(
image

Environment: Meterpreter executed on Windows 10 Enterprise, 20H2 OS Build 19042.1110

Expected behavior

The reverse port forward should not break when creating a new route.

Current behavior

The reverse port forward no longer functions after creating a new route.

Metasploit version

Framework: 6.2.28-dev-de8a396b3af4aafc62121da0e5c67b8eeaa68ffd Console : 6.2.28-dev-de8a396b3af4aafc62121da0e5c67b8eeaa68ffd

Invoke-Mimikatz avatar Nov 23 '22 00:11 Invoke-Mimikatz

@smcintyre-r7 :)

Invoke-Mimikatz avatar Nov 23 '22 00:11 Invoke-Mimikatz

I wonder if this is a bug, or just unexpected behavior? It seems like you're globally setting the routing table to send all traffic destined 0.0.0.0 0 (i.e. everything) to go through your Meterpreter instance, so the incoming portfwd request gets sent back out to Meterpreter

I only took a quick glance, but enabling the tlv logging with setg sessiontlvlogging true after adding the route and I can see the following requests are made made from Meterpreter to msfconsole:

msf6 payload(windows/x64/meterpreter/reverse_tcp) > 
vvvvvvvvvvvvvvvvvvv incoming request from Meterpreter vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
RECV: #<Rex::Post::Meterpreter::Packet type=Request         tlvs=[
  #<Rex::Post::Meterpreter::Tlv type=COMMAND_ID      meta=INT        value=1027 command=stdapi_net_tcp_channel_open>
  #<Rex::Post::Meterpreter::Tlv type=CHANNEL_ID      meta=INT        value=4>
  #<Rex::Post::Meterpreter::Tlv type=CHANNEL_PARENTID meta=INT        value=1>
  #<Rex::Post::Meterpreter::Tlv type=LOCAL_HOST      meta=STRING     value="">
  #<Rex::Post::Meterpreter::Tlv type=LOCAL_PORT      meta=INT        value=8888>
  #<Rex::Post::Meterpreter::Tlv type=PEER_HOST       meta=STRING     value="">
  #<Rex::Post::Meterpreter::Tlv type=PEER_PORT       meta=INT        value=54749>
  #<Rex::Post::Meterpreter::Tlv type=REQUEST_ID      meta=STRING     value="}8%X9=]rPgn<5;S{oM4s9*}Lv-M/x|H">
  #<Rex::Post::Meterpreter::Tlv type=UUID            meta=RAW        value="\xC98\xF7b\x8Da\x88\xD3\xEF\xAB\xEE\xA9\x8C\xD6\x ...">
]>

RECV: #<Rex::Post::Meterpreter::Packet type=Request         tlvs=[
  #<Rex::Post::Meterpreter::Tlv type=COMMAND_ID      meta=INT        value=8 command=core_channel_write>
  #<Rex::Post::Meterpreter::Tlv type=CHANNEL_ID      meta=INT        value=4>
  #<Rex::Post::Meterpreter::Tlv type=CHANNEL_DATA    meta=RAW        value="GET / HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (Window ...">
  #<Rex::Post::Meterpreter::Tlv type=LENGTH          meta=INT        value=4>
  #<Rex::Post::Meterpreter::Tlv type=REQUEST_ID      meta=STRING     value="JLEwx;+?o9bH`\"|6r%BoXCQ\\+e@+i^z">
  #<Rex::Post::Meterpreter::Tlv type=UUID            meta=RAW        value="\xC98\xF7b\x8Da\x88\xD3\xEF\xAB\xEE\xA9\x8C\xD6\x ...">
]>
vvvvvvvvvvvvvvvvvvv Request going back out to Meterpreter vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
SEND: #<Rex::Post::Meterpreter::Packet type=Request         tlvs=[
  #<Rex::Post::Meterpreter::Tlv type=COMMAND_ID      meta=INT        value=4 command=core_channel_open>
  #<Rex::Post::Meterpreter::Tlv type=REQUEST_ID      meta=STRING     value="87220724851553125233311755194209">
  #<Rex::Post::Meterpreter::Tlv type=CHANNEL_TYPE    meta=STRING     value="stdapi_net_tcp_client">
  #<Rex::Post::Meterpreter::Tlv type=CHANNEL_CLASS   meta=INT        value=1>
  #<Rex::Post::Meterpreter::Tlv type=FLAGS           meta=INT        value=1>
  #<Rex::Post::Meterpreter::Tlv type=PEER_HOST       meta=STRING     value="127.0.0.1">
  #<Rex::Post::Meterpreter::Tlv type=PEER_PORT       meta=INT        value=80>
  #<Rex::Post::Meterpreter::Tlv type=LOCAL_HOST      meta=STRING     value="0.0.0.0">
  #<Rex::Post::Meterpreter::Tlv type=LOCAL_PORT      meta=INT        value=0>
  #<Rex::Post::Meterpreter::Tlv type=CONNECT_RETRIES meta=INT        value=0>
]>

RECV: #<Rex::Post::Meterpreter::Packet type=Response        tlvs=[
  #<Rex::Post::Meterpreter::Tlv type=COMMAND_ID      meta=INT        value=4 command=core_channel_open>
  #<Rex::Post::Meterpreter::Tlv type=REQUEST_ID      meta=STRING     value="87220724851553125233311755194209">
  #<Rex::Post::Meterpreter::Tlv type=RESULT          meta=INT        value=10061>
  #<Rex::Post::Meterpreter::Tlv type=UUID            meta=RAW        value="\xC98\xF7b\x8Da\x88\xD3\xEF\xAB\xEE\xA9\x8C\xD6\x ...">
]>

It looks like msfconsole reads the request for a connection to 8888, then attempts to connect back out to port 80 on the Meterpreter instance, as I believe that's what you've configured msfconsole to do with route add 0 0 -1. I believe msfconsole's internal routing logic is global, so the incoming request to 127.0.0.1 gets sent back out to Meterpreter with that routing configuration.

When I use a more specific route add command, it works as expected for me:

route add 172.17.0.1/32 -1

adfoster-r7 avatar Nov 23 '22 01:11 adfoster-r7

Thanks! It does seem like this is just unintended behavior. Feel free to close the issue! :)

Invoke-Mimikatz avatar Nov 26 '22 18:11 Invoke-Mimikatz

I wouldn't have expected it to work this way either 😄

I don't know if there's a better UX for this. Potentially generating a warning? Or if there was an easier way to configure msfconsole's routing table to say 'route everything to comm 1, apart from localhost'

adfoster-r7 avatar Nov 27 '22 03:11 adfoster-r7