summaryrefslogtreecommitdiff
path: root/includes/specials/SpecialUpload.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/specials/SpecialUpload.php')
-rw-r--r--includes/specials/SpecialUpload.php65
1 files changed, 60 insertions, 5 deletions
diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php
index 8fe2f52f..3a79e052 100644
--- a/includes/specials/SpecialUpload.php
+++ b/includes/specials/SpecialUpload.php
@@ -1326,11 +1326,11 @@ wgUploadAutoFill = {$autofill};
$magic = MimeMagic::singleton();
$mime = $magic->guessMimeType($tmpfile,false);
+
#check mime type, if desired
global $wgVerifyMimeType;
if ($wgVerifyMimeType) {
-
- wfDebug ( "\n\nmime: <$mime> extension: <$extension>\n\n");
+ wfDebug ( "\n\nmime: <$mime> extension: <$extension>\n\n");
#check mime type against file extension
if( !self::verifyExtension( $mime, $extension ) ) {
return new WikiErrorMsg( 'uploadcorrupt' );
@@ -1338,9 +1338,22 @@ wgUploadAutoFill = {$autofill};
#check mime type blacklist
global $wgMimeTypeBlacklist;
- if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist)
- && $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
- return new WikiErrorMsg( 'filetype-badmime', htmlspecialchars( $mime ) );
+ if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist) ) {
+ if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
+ return new WikiErrorMsg( 'filetype-badmime', htmlspecialchars( $mime ) );
+ }
+
+ # Check IE type
+ $fp = fopen( $tmpfile, 'rb' );
+ $chunk = fread( $fp, 256 );
+ fclose( $fp );
+ $extMime = $magic->guessTypesForExtension( $extension );
+ $ieTypes = $magic->getIEMimeTypes( $tmpfile, $chunk, $extMime );
+ foreach ( $ieTypes as $ieType ) {
+ if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
+ return new WikiErrorMsg( 'filetype-bad-ie-mime', $ieType );
+ }
+ }
}
}
@@ -1348,6 +1361,11 @@ wgUploadAutoFill = {$autofill};
if( $this->detectScript ( $tmpfile, $mime, $extension ) ) {
return new WikiErrorMsg( 'uploadscripted' );
}
+ if( $extension == 'svg' || $mime == 'image/svg+xml' ) {
+ if( $this->detectScriptInSvg( $tmpfile ) ) {
+ return new WikiErrorMsg( 'uploadscripted' );
+ }
+ }
/**
* Scan the uploaded file for viruses
@@ -1399,6 +1417,7 @@ wgUploadAutoFill = {$autofill};
}
}
+
/**
* Heuristic for detecting files that *could* contain JavaScript instructions or
* things that may look like HTML to a browser and are thus
@@ -1459,6 +1478,7 @@ wgUploadAutoFill = {$autofill};
*/
$tags = array(
+ '<a href',
'<body',
'<head',
'<html', #also in safari
@@ -1497,6 +1517,41 @@ wgUploadAutoFill = {$autofill};
return false;
}
+ function detectScriptInSvg( $filename ) {
+ $check = new XmlTypeCheck( $filename, array( $this, 'checkSvgScriptCallback' ) );
+ return $check->filterMatch;
+ }
+
+ /**
+ * @todo Replace this with a whitelist filter!
+ */
+ function checkSvgScriptCallback( $element, $attribs ) {
+ $stripped = $this->stripXmlNamespace( $element );
+
+ if( $stripped == 'script' ) {
+ wfDebug( __METHOD__ . ": Found script element '$element' in uploaded file.\n" );
+ return true;
+ }
+
+ foreach( $attribs as $attrib => $value ) {
+ $stripped = $this->stripXmlNamespace( $attrib );
+ if( substr( $stripped, 0, 2 ) == 'on' ) {
+ wfDebug( __METHOD__ . ": Found script attribute '$attrib'='value' in uploaded file.\n" );
+ return true;
+ }
+ if( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) {
+ wfDebug( __METHOD__ . ": Found script href attribute '$attrib'='$value' in uploaded file.\n" );
+ return true;
+ }
+ }
+ }
+
+ private function stripXmlNamespace( $name ) {
+ // 'http://www.w3.org/2000/svg:script' -> 'script'
+ $parts = explode( ':', strtolower( $name ) );
+ return array_pop( $parts );
+ }
+
/**
* Generic wrapper function for a virus scanner program.
* This relies on the $wgAntivirus and $wgAntivirusSetup variables.