Skip to content

Commit f9b141c

Browse files
author
Brent Cook
committed
Land rapid7#4442, wchen-r7's configurable session response timeout option
fixes rapid7#4431
2 parents 72eb8e6 + bcf6597 commit f9b141c

File tree

1 file changed

+99
-46
lines changed
  • lib/msf/ui/console/command_dispatcher

1 file changed

+99
-46
lines changed

lib/msf/ui/console/command_dispatcher/core.rb

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class Core
4545
"-K" => [ false, "Terminate all sessions" ],
4646
"-s" => [ true, "Run a script on the session given with -i, or all"],
4747
"-r" => [ false, "Reset the ring buffer for the session given with -i, or all"],
48-
"-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ])
48+
"-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ],
49+
"-t" => [ true, "Set a response timeout (default: 15)"])
4950

5051
@@jobs_opts = Rex::Parser::Arguments.new(
5152
"-h" => [ false, "Help banner." ],
@@ -1222,7 +1223,7 @@ def cmd_route(*args)
12221223
Rex::Socket::SwitchBoard.flush_routes
12231224

12241225
when "print"
1225-
tbl = Table.new(
1226+
tbl = Table.new(
12261227
Table::Style::Default,
12271228
'Header' => "Active Routing Table",
12281229
'Prefix' => "\n",
@@ -1597,6 +1598,7 @@ def cmd_sessions(*args)
15971598
cmds = []
15981599
script = nil
15991600
reset_ring = false
1601+
response_timeout = 15
16001602

16011603
# any arguments that don't correspond to an option or option arg will
16021604
# be put in here
@@ -1646,6 +1648,10 @@ def cmd_sessions(*args)
16461648
when "-h"
16471649
cmd_sessions_help
16481650
return false
1651+
when "-t"
1652+
if val.to_s =~ /^\d+$/
1653+
response_timeout = val.to_i
1654+
end
16491655
else
16501656
extra << val
16511657
end
@@ -1684,30 +1690,39 @@ def cmd_sessions(*args)
16841690
session = verify_session(s)
16851691
next unless session
16861692
print_status("Running '#{cmd}' on #{session.type} session #{s} (#{session.session_host})")
1693+
last_known_timeout = session.response_timeout
1694+
session.response_timeout = response_timeout
16871695

1688-
if session.type == 'meterpreter'
1689-
# If session.sys is nil, dont even try..
1690-
unless session.sys
1691-
print_error("Session #{s} does not have stdapi loaded, skipping...")
1692-
next
1693-
end
1694-
c, c_args = cmd.split(' ', 2)
1695-
begin
1696-
process = session.sys.process.execute(c, c_args,
1697-
{
1698-
'Channelized' => true,
1699-
'Hidden' => true
1700-
})
1701-
rescue ::Rex::Post::Meterpreter::RequestError
1702-
print_error("Failed: #{$!.class} #{$!}")
1703-
end
1704-
if process && process.channel
1705-
data = process.channel.read
1706-
print_line(data) if data
1696+
begin
1697+
if session.type == 'meterpreter'
1698+
# If session.sys is nil, dont even try..
1699+
unless session.sys
1700+
print_error("Session #{s} does not have stdapi loaded, skipping...")
1701+
next
1702+
end
1703+
c, c_args = cmd.split(' ', 2)
1704+
begin
1705+
process = session.sys.process.execute(c, c_args,
1706+
{
1707+
'Channelized' => true,
1708+
'Hidden' => true
1709+
})
1710+
if process && process.channel
1711+
data = process.channel.read
1712+
print_line(data) if data
1713+
end
1714+
rescue ::Rex::Post::Meterpreter::RequestError
1715+
print_error("Failed: #{$!.class} #{$!}")
1716+
rescue Rex::TimeoutError
1717+
print_error("Operation timed out")
1718+
end
1719+
elsif session.type == 'shell'
1720+
output = session.shell_command(cmd)
1721+
print_line(output) if output
17071722
end
1708-
elsif session.type == 'shell'
1709-
output = session.shell_command(cmd)
1710-
print_line(output) if output
1723+
ensure
1724+
# Restore timeout for each session
1725+
session.response_timeout = last_known_timeout
17111726
end
17121727
# If the session isn't a meterpreter or shell type, it
17131728
# could be a VNC session (which can't run commands) or
@@ -1720,8 +1735,14 @@ def cmd_sessions(*args)
17201735
session_list.each do |sess_id|
17211736
session = framework.sessions.get(sess_id)
17221737
if session
1738+
last_known_timeout = session.response_timeout
1739+
session.response_timeout = response_timeout
17231740
print_status("Killing session #{sess_id}")
1724-
session.kill
1741+
begin
1742+
session.kill
1743+
ensure
1744+
session.response_timeout = last_known_timeout
1745+
end
17251746
else
17261747
print_error("Invalid session identifier: #{sess_id}")
17271748
end
@@ -1730,26 +1751,46 @@ def cmd_sessions(*args)
17301751
print_status("Killing all sessions...")
17311752
framework.sessions.each_sorted do |s|
17321753
session = framework.sessions.get(s)
1733-
session.kill if session
1754+
if session
1755+
last_known_timeout = session.response_timeout
1756+
session.response_timeout = response_timeout
1757+
begin
1758+
session.kill
1759+
ensure
1760+
session.response_timeout = last_known_timeout
1761+
end
1762+
end
17341763
end
17351764
when 'detach'
17361765
print_status("Detaching the following session(s): #{session_list.join(', ')}")
17371766
session_list.each do |sess_id|
17381767
session = verify_session(sess_id)
17391768
# if session is interactive, it's detachable
17401769
if session
1770+
last_known_timeout = session.response_timeout
1771+
session.response_timeout = response_timeout
17411772
print_status("Detaching session #{sess_id}")
1742-
session.detach
1773+
begin
1774+
session.detach
1775+
ensure
1776+
session.response_timeout = last_known_timeout
1777+
end
17431778
end
17441779
end
17451780
when 'interact'
17461781
session = verify_session(sid)
17471782
if session
1783+
last_known_timeout = session.response_timeout
1784+
session.response_timeout = response_timeout
17481785
print_status("Starting interaction with #{session.name}...\n") unless quiet
1749-
self.active_session = session
1750-
session.interact(driver.input.dup, driver.output)
1751-
self.active_session = nil
1752-
driver.input.reset_tab_completion if driver.input.supports_readline
1786+
begin
1787+
self.active_session = session
1788+
session.interact(driver.input.dup, driver.output)
1789+
self.active_session = nil
1790+
driver.input.reset_tab_completion if driver.input.supports_readline
1791+
ensure
1792+
session.response_timeout = last_known_timeout
1793+
end
17531794
end
17541795
when 'scriptall'
17551796
unless script
@@ -1770,15 +1811,21 @@ def cmd_sessions(*args)
17701811
session = framework.sessions.get(sess_id)
17711812
end
17721813
if session
1773-
if script_paths[session.type]
1774-
print_status("Session #{sess_id} (#{session.session_host}):")
1775-
print_status("Running script #{script} on #{session.type} session" +
1776-
" #{sess_id} (#{session.session_host})")
1777-
begin
1778-
session.execute_file(script_paths[session.type], extra)
1779-
rescue ::Exception => e
1780-
log_error("Error executing script: #{e.class} #{e}")
1814+
last_known_timeout = session.response_timeout
1815+
session.response_timeout = response_timeout
1816+
begin
1817+
if script_paths[session.type]
1818+
print_status("Session #{sess_id} (#{session.session_host}):")
1819+
print_status("Running script #{script} on #{session.type} session" +
1820+
" #{sess_id} (#{session.session_host})")
1821+
begin
1822+
session.execute_file(script_paths[session.type], extra)
1823+
rescue ::Exception => e
1824+
log_error("Error executing script: #{e.class} #{e}")
1825+
end
17811826
end
1827+
ensure
1828+
session.response_timeout = last_known_timeout
17821829
end
17831830
else
17841831
print_error("Invalid session identifier: #{sess_id}")
@@ -1790,13 +1837,19 @@ def cmd_sessions(*args)
17901837
session_list.each do |sess_id|
17911838
session = verify_session(sess_id)
17921839
if session
1793-
if session.type == 'shell'
1794-
session.init_ui(driver.input, driver.output)
1795-
session.execute_script('post/multi/manage/shell_to_meterpreter')
1796-
session.reset_ui
1797-
else
1798-
print_error("Session #{sess_id} is not a command shell session, skipping...")
1799-
next
1840+
last_known_timeout = session.response_timeout
1841+
session.response_timeout = response_timeout
1842+
begin
1843+
if session.type == 'shell'
1844+
session.init_ui(driver.input, driver.output)
1845+
session.execute_script('post/multi/manage/shell_to_meterpreter')
1846+
session.reset_ui
1847+
else
1848+
print_error("Session #{sess_id} is not a command shell session, skipping...")
1849+
next
1850+
end
1851+
ensure
1852+
session.response_timeout = last_known_timeout
18001853
end
18011854
end
18021855

0 commit comments

Comments
 (0)