Skip to content

Commit 9fb8cf3

Browse files
committed
Fix #17874: XSS in file uploads
An attacker can upload a Flash file with an image extension. If such an attachment is displayed inline, it becomes a vector for XSS attacks. This issue was reported by Matthias Karlsson (http://mathiaskarlsson.me) as part of Offensive Security's bug bounty program [1]. Patch with contribution from Victor Boctor.
1 parent 05378e0 commit 9fb8cf3

File tree

1 file changed

+36
-44
lines changed

1 file changed

+36
-44
lines changed

Diff for: file_download.php

+36-44
Original file line numberDiff line numberDiff line change
@@ -130,42 +130,24 @@
130130

131131
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s \G\M\T', $v_date_added ) );
132132

133+
$t_upload_method = config_get( 'file_upload_method' );
133134
$t_filename = file_get_display_name( $v_filename );
134-
# For Internet Explorer 8 as per http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
135-
# Don't let IE second guess our content-type!
136-
header( 'X-Content-Type-Options: nosniff' );
137135

138-
http_content_disposition_header( $t_filename, $f_show_inline );
139-
140-
header( 'Content-Length: ' . $v_filesize );
136+
# Content headers
141137

142138
# If finfo is available (always true for PHP >= 5.3.0) we can use it to determine the MIME type of files
143139
$finfo = finfo_get_if_available();
144140

145141
$t_content_type = $v_file_type;
146142

147143
$t_content_type_override = file_get_content_type_override ( $t_filename );
144+
$t_file_info_type = false;
148145

149-
# dump file content to the connection.
150-
switch ( config_get( 'file_upload_method' ) ) {
146+
switch( $t_upload_method ) {
151147
case DISK:
152148
$t_local_disk_file = file_normalize_attachment_path( $v_diskfile, $t_project_id );
153-
154-
if ( file_exists( $t_local_disk_file ) ) {
155-
if ( $finfo ) {
156-
$t_file_info_type = $finfo->file( $t_local_disk_file );
157-
158-
if ( $t_file_info_type !== false ) {
159-
$t_content_type = $t_file_info_type;
160-
}
161-
}
162-
163-
if ( $t_content_type_override ) {
164-
$t_content_type = $t_content_type_override;
165-
}
166-
167-
header( 'Content-Type: ' . $t_content_type );
168-
readfile( $t_local_disk_file );
149+
if( file_exists( $t_local_disk_file ) && $finfo ) {
150+
$t_file_info_type = $finfo->file( $t_local_disk_file );
169151
}
170152
break;
171153
case FTP:
@@ -179,32 +161,42 @@
179161

180162
if ( $finfo ) {
181163
$t_file_info_type = $finfo->file( $t_local_disk_file );
182-
183-
if ( $t_file_info_type !== false ) {
184-
$t_content_type = $t_file_info_type;
185-
}
186164
}
187-
188-
if ( $t_content_type_override ) {
189-
$t_content_type = $t_content_type_override;
190-
}
191-
192-
header( 'Content-Type: ' . $t_content_type );
193-
readfile( $t_local_disk_file );
194165
break;
195-
default:
166+
case DATABASE:
196167
if ( $finfo ) {
197168
$t_file_info_type = $finfo->buffer( $v_content );
198-
199-
if ( $t_file_info_type !== false ) {
200-
$t_content_type = $t_file_info_type;
201-
}
202169
}
170+
}
203171

204-
if ( $t_content_type_override ) {
205-
$t_content_type = $t_content_type_override;
206-
}
172+
if( $t_file_info_type !== false ) {
173+
$t_content_type = $t_file_info_type;
174+
}
175+
176+
if( $t_content_type_override ) {
177+
$t_content_type = $t_content_type_override;
178+
}
179+
180+
# Don't allow inline flash
181+
if( false !== strpos( $t_content_type, 'application/x-shockwave-flash' ) ) {
182+
http_content_disposition_header( $t_filename );
183+
} else {
184+
http_content_disposition_header( $t_filename, $f_show_inline );
185+
}
186+
187+
header( 'Content-Type: ' . $t_content_type );
188+
header( 'Content-Length: ' . $v_filesize );
207189

208-
header( 'Content-Type: ' . $t_content_type );
190+
# For Internet Explorer 8 as per http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
191+
# Don't let IE second guess our content-type!
192+
header( 'X-Content-Type-Options: nosniff' );
193+
194+
# dump file content to the connection.
195+
switch( $t_upload_method ) {
196+
case DISK:
197+
case FTP:
198+
readfile( $t_local_disk_file );
199+
break;
200+
case DATABASE:
209201
echo $v_content;
210202
}

0 commit comments

Comments
 (0)