Index: t3lib/class.t3lib_div.php =================================================================== --- t3lib/class.t3lib_div.php (Revision 6407) +++ t3lib/class.t3lib_div.php (Revision 6409) @@ -900,6 +900,17 @@ } /** + * Checks if a given URL matches the host that currently handles this HTTP request. + * Scheme, hostname and (optional) port of the given URL are compared. + * + * @param string $url: URL to compare with the TYPO3 request host + * @return boolean Whether the URL matches the TYPO3 request host + */ + public static function isOnCurrentHost($url) { + return (stripos($url . '/', self::getIndpEnv('TYPO3_REQUEST_HOST') . '/') === 0); + } + + /** * Check for item in list * Check if an item exists in a comma-separated list of items. * Usage: 163 @@ -1534,6 +1545,15 @@ return $output; } + /** + * Checks if a given string is a Uniform Resource Locator (URL). + * + * @param string $url: The URL to be validated + * @return boolean Whether the given URL is valid + */ + public static function isValidUrl($url) { + return (filter_var($url, FILTER_VALIDATE_URL) !== false); + } @@ -1546,6 +1566,7 @@ + /************************* * * ARRAY FUNCTIONS @@ -3876,13 +3897,38 @@ * @return string either $url if $url is considered to be harmless, or an * empty string otherwise */ - public static function sanitizeBackEndUrl($url = '') { - $whitelistPattern = '/^[a-zA-Z0-9_\/\.&=\?]+$/'; - if (!preg_match($whitelistPattern, $url)) { - $url = ''; + public static function sanitizeLocalUrl($url = '') { + $sanitizedUrl = ''; + $decodedUrl = rawurldecode($url); + + if (!empty($url) && self::removeXSS($decodedUrl) === $decodedUrl) { + $testAbsoluteUrl = self::resolveBackPath($decodedUrl); + $testRelativeUrl = self::resolveBackPath( + t3lib_div::dirname(t3lib_div::getIndpEnv('SCRIPT_NAME')) . '/' . $decodedUrl + ); + + // Pass if URL is on the current host: + if (self::isValidUrl($decodedUrl)) { + if (self::isOnCurrentHost($decodedUrl) && strpos($decodedUrl, self::getIndpEnv('TYPO3_SITE_URL')) === 0) { + $sanitizedUrl = $url; + } + // Pass if URL is an absolute file path: + } elseif (self::isAbsPath($decodedUrl) && self::isAllowedAbsPath($decodedUrl)) { + $sanitizedUrl = $url; + // Pass if URL is absolute and below TYPO3 base directory: + } elseif (strpos($testAbsoluteUrl, self::getIndpEnv('TYPO3_SITE_PATH')) === 0 && substr($decodedUrl, 0, 1) === '/') { + $sanitizedUrl = $url; + // Pass if URL is relative and below TYPO3 base directory: + } elseif (strpos($testRelativeUrl, self::getIndpEnv('TYPO3_SITE_PATH')) === 0 && substr($decodedUrl, 0, 1) !== '/') { + $sanitizedUrl = $url; + } } - return $url; + if (!empty($url) && empty($sanitizedUrl)) { + self::sysLog('The URL "' . $url . '" is not considered to be local and was denied.', 'Core', self::SYSLOG_SEVERITY_NOTICE); + } + + return $sanitizedUrl; } /** Index: typo3/alt_mod_frameset.php =================================================================== --- typo3/alt_mod_frameset.php (Revision 6407) +++ typo3/alt_mod_frameset.php (Revision 6409) @@ -87,7 +87,7 @@ global $BE_USER,$TBE_TEMPLATE,$TBE_STYLES; // GPvars: - $this->exScript = t3lib_div::sanitizeBackEndUrl(t3lib_div::_GP('exScript')); + $this->exScript = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('exScript')); $this->id = intval(t3lib_div::_GP('id')); $this->fW = t3lib_div::_GP('fW'); @@ -103,8 +103,8 @@ } // Navigation frame URL: - $script = t3lib_div::sanitizeBackEndUrl(t3lib_div::_GP('script')); - $nav = t3lib_div::sanitizeBackEndUrl(t3lib_div::_GP('nav')); + $script = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('script')); + $nav = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('nav')); $URL_nav = htmlspecialchars($nav.'¤tSubScript='.rawurlencode($script)); // List frame URL: @@ -114,12 +114,9 @@ $TBE_TEMPLATE->docType='xhtml_frames'; $this->content = $TBE_TEMPLATE->startPage('Frameset'); - // THis onload handler is a bug-fix for a possible bug in Safari browser for Mac. Posted by Jack COLE. Should not influence other browsers negatively. - $onLoadHandler = ' onload="if(top.content.nav_frame.location.href.length == 1) {top.content.nav_frame.location=\''.$URL_nav.'\';};"'; - if ($this->resizable) { $this->content.= ' - + @@ -129,7 +126,7 @@ } else { $this->content.= ' - +