SECURITY: Don't allow embedded application/xml in SVG's
[lhc/web/wiklou.git] / includes / upload / UploadBase.php
index a001fea..8c3f174 100644 (file)
@@ -1412,20 +1412,16 @@ abstract class UploadBase {
                                }
                        }
 
-                       # href with embedded svg as target
-                       if ( $stripped == 'href' && preg_match( '!data:[^,]*image/svg[^,]*,!sim', $value ) ) {
-                               wfDebug( __METHOD__ . ": Found href to embedded svg "
-                                       . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
-
-                               return true;
-                       }
-
-                       # href with embedded (text/xml) svg as target
-                       if ( $stripped == 'href' && preg_match( '!data:[^,]*text/xml[^,]*,!sim', $value ) ) {
-                               wfDebug( __METHOD__ . ": Found href to embedded svg "
-                                       . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
-
-                               return true;
+                       # only allow data: targets that should be safe. This prevents vectors like,
+                       # image/svg, text/xml, application/xml, and text/html, which can contain scripts
+                       if ( $stripped == 'href' && strncasecmp( 'data:', $value, 5 ) === 0 ) {
+                               // rfc2397 parameters. This is only slightly slower than (;[\w;]+)*.
+                               $parameters = '(?>;[a-zA-Z0-9\!#$&\'*+.^_`{|}~-]+=(?>[a-zA-Z0-9\!#$&\'*+.^_`{|}~-]+|"(?>[\0-\x0c\x0e-\x21\x23-\x5b\x5d-\x7f]+|\\\\[\0-\x7f])*"))*(?:;base64)?';
+                               if ( !preg_match( "!^data:\s*image/(gif|jpeg|jpg|png)$parameters,!i", $value ) ) {
+                                       wfDebug( __METHOD__ . ": Found href to unwhitelisted data: uri "
+                                               . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+                                       return true;
+                               }
                        }
 
                        # Change href with animate from (http://html5sec.org/#137). This doesn't seem