From e03ccbd7a9d0d46b05adb0362a974889ec8efd52 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 18 Sep 2018 02:45:48 +0900 Subject: [PATCH 1/2] Also filter XML and HTML file uploads - Detect possible XML (including SVG) by actual content, not extension - Check large files in overlapping chunks to reduce memory usage - Check XML files for external entities - Check HTML files for SSI and PHP code --- classes/security/UploadFileFilter.class.php | 107 +++++++++++++++++--- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/classes/security/UploadFileFilter.class.php b/classes/security/UploadFileFilter.class.php index 1b3b73a34..38843005f 100644 --- a/classes/security/UploadFileFilter.class.php +++ b/classes/security/UploadFileFilter.class.php @@ -1,5 +1,4 @@ */ class UploadFileFilter { @@ -19,7 +18,7 @@ class UploadFileFilter } // Return error if the file size is zero. - if (!filesize($file)) + if (($filesize = filesize($file)) == 0) { return false; } @@ -27,38 +26,120 @@ class UploadFileFilter // Get the extension. $ext = $filename ? strtolower(substr(strrchr($filename, '.'), 1)) : ''; + // Check the first 4KB of the file for possible XML content. + $fp = fopen($file, 'rb'); + $first4kb = fread($fp, 4096); + $is_xml = preg_match('/<(?:\?xml|!DOCTYPE|html|head|body|meta|script|svg)\b/i', $first4kb); + // Check SVG files. - if ($ext === 'svg' && !self::_checkSVG($file)) + if (($ext === 'svg' || $is_xml) && !self::_checkSVG($fp, 0, $filesize)) { + fclose($fp); + return false; + } + + // Check XML files. + if (($ext === 'xml' || $is_xml) && !self::_checkXML($fp, 0, $filesize)) + { + fclose($fp); + return false; + } + + // Check HTML files. + if (($ext === 'html' || $ext === 'shtml' || $ext === 'xhtml' || $ext === 'phtml' || $is_xml) && !self::_checkHTML($fp, 0, $filesize)) + { + fclose($fp); return false; } // Return true if everything is OK. + fclose($fp); return true; } /** * Check SVG file for XSS or SSRF vulnerabilities (#1088, #1089) * - * @param string $file + * @param resource $fp + * @param int $from + * @param int $to * @return bool */ - protected static function _checkSVG($file) + protected static function _checkSVG($fp, $from, $to) { - $content = file_get_contents($file); - - if (preg_match('/xlink:href\s*=\s*"(?!data:)/i', $content)) - { - return false; - } - - if (preg_match('/