Link Search Menu Expand Document

It is now possible to meticulously control a set of timeout-related behaviour in Meterpreter sessions. Timeouts may not seem important, but they change the noise levels of Meterpreter’s communication resiliency features, and allow for the extension/reduction of time of the Meterpreter session as a whole.

This document details what those timeouts are, and how to control them.

Meterpreter’s Timeout Values

There are four timeout values that can be controlled by the user, and they are documented in the sections below.

Meterpreter Session Timeout

Each instance of Meterpreter has a lifetime that is defined as a session. The length of Meterpeter’s life is defined by a parameter called the Session Timeout. This value can be specified when Meterpreter payloads are generated by using the SessionExpirationTimeout datastore option. The default value used is the equivalent of one whole week (604800 seconds), and hence this is what is used if the user does not override the value manually.

The session’s life begins at the point that metsrv (Meterpreter’s core) takes over from the initial stage (if there is one). Once running, the session timer begins, and Meterpeter will monitor this timeout so that as soon as it is reached the session will be closed.

If the timeout value is set to zero, this tells Meterpreter to never kill the session. If you’re looking to have Meterpreter run for as long as it can, then setting this value to zero is the way to do it.

It’s important to note that this value lives outside of the realms of the other timeout values. That is, this value applies to Meterpreter as a whole, where the other three timeouts are specific to the individual transports that have been configured within the session.

Meterpreter Transport Timeouts

Each transport that is configured inside Meterpreter has three timeouts. The are as follows:

Communication Timeout

When Meterpreter talks to Metasploit packets are exchanged at a low level in a request/response fashion. In the case of TCP transports, this req/rep pattern is basically instant because TCP is a persistent connection. A request is handled by Meterpreter, and the response is immediately transferred as soon as the command has finished executing.

In the case of HTTP/S payloads it’s slightly different because the protocols are stateless. Meterpreter makes a GET request to Metasploit to check to see if a command has been executed by the user. The command is returned, the connection is closed, and Meterpreter executes the command asynchronously. When the command execution finishes, a second request is made that POSTs the result back to Metasploit so that the user can consume it. Hence, for each command invocation, there are two HTTP/S requests.

With TCP transports, communication “times out” when the time between the last packet and the current socket poll is greater than the communications timeout value. This happens when there are network related issues that prevent data from being transmitted between the two endpoints, but doesn’t cause the socket to completely disconnect. With HTTP/S transports, the communication “times out” for the same reason, but the evaluation of the condition is slightly different in that failure can occur because there is either no response at all from the remote server, or the response to a GET request results in no acknowledgement.

By default, this value is set to 300 seconds (5 minutes), but can be overridden by the user via the SessionCommunicationTimeout setting.

If connectivity fails, or the communication is deemed to have timed out. Then the current transport is destroyed, and the next transport in the list of transports is invoked. From there, Meterpreter will use the Retry Total and Retry Wait values while attempting to re-establish a session with Metasploit.

Retry Total and Retry Wait

After a transport initialises inside Meterpreter, Meterpreter uses this transport to attempt to establish a new session with Metasploit. In some cases, Metasploit might not be available due to reasons like bad network connectivity, or a lack of configured listeners. If Meterpreter can’t connect to Metasploit, it will attempt to retry for a period of time. Once that period of time expires, Meterpreter will deem this transport “dead” and will move to the next one in the transport list.

The total amount of time that Meterpreter will attempt to connect back to Metasploit on the given transport is indicated by the retry total value. That is, retry total is the total amount of time that Meterpreter will retry communication on the transport. The default value is 3600 seconds (1 hour), and can be overridden via the SessionRetryTotal setting.

While the current time is within the retry total time, Meterpreter will constantly attempt to establish connectivity. If it fails, it will wait for a period of time before trying again. The time between retry attempts on the current transport is called retry wait. That is, Meterpreter will wait for the number of seconds specified in retry wait between each connection attempt on the current transport. The default value is 10 seconds, and can be overridden via the SessionRetryWait setting.

Changing Timeouts

Meterpreter supports the querying and updating of each of these timeouts via the console. In order to get the current timeout settings, users can invoke the get_timeouts command, which returns all four of the current timeout settings (one for the global session, and three for the transport-specific settings). An example of which is shown below:

meterpreter > get_timeouts 
Session Expiry  : @ 2015-06-09 19:56:05
Comm Timeout    : 100000 seconds
Retry Total Time: 50000 seconds
Retry Wait Time : 2500 seconds

The Session Expiry value is rendered as an absolute local time so that the user knows when the session is due to expire.

In order to update these values, users can invoke the set_timeouts command. Invoking it without parameters shows the help:

meterpreter > set_timeouts 
Usage: set_timeouts [options]

Set the current timeout options.
Any or all of these can be set at once.

OPTIONS:

    -c <opt>  Comms timeout (seconds)
    -h        Help menu
    -t <opt>  Retry total time (seconds)
    -w <opt>  Retry wait time (seconds)
    -x <opt>  Expiration timeout (seconds)

As the help implies, each of these settings takes a value that indicates the number of seconds. Each of the options of this command are optional, so the user can update only those values that they are interested in updating. When the command is invoked, Meterpreter is updated, and the result shows the updated values once the changes have been made.

In the case of the -x parameter, the value that is to be passed in should represent the total number of seconds from “now” until the session should expire.

The following example updates the session expiration timeout to be 2 minutes from “now”, and changes the retry wait time to 3 seconds:

meterpreter > set_timeouts -x 120 -t 3
Session Expiry  : @ 2015-06-02 22:45:13
Comm Timeout    : 100000 seconds
Retry Total Time: 3 seconds
Retry Wait Time : 2500 seconds

This command can be invoked any number of times while the session is valid, but as soon as the session has expired, Metepreter will shut down and it’s game over:

meterpreter > 
[*] 10.1.10.35 - Meterpreter session 2 closed.  Reason: Died