Index: t3lib/class.t3lib_div.php =================================================================== --- t3lib/class.t3lib_div.php (revision 6382) +++ t3lib/class.t3lib_div.php (working copy) @@ -4173,12 +4173,36 @@ * empty string otherwise */ public static function sanitizeBackEndUrl($url = '') { - $whitelistPattern = '/^[a-zA-Z0-9_\/\.&=\?]+$/'; - if (!preg_match($whitelistPattern, $url)) { - $url = ''; + $sanitizedUrl = ''; + $decodedUrl = rawurldecode($url); + + if (!empty($url) && self::removeXSS($decodedUrl) === $decodedUrl) { + $resolvedUrl = 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)) { + $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($decodedUrl, self::getIndpEnv('TYPO3_SITE_PATH')) === 0) { + $sanitizedUrl = $url; + // Pass if URL is relative and below TYPO3 base directory: + } elseif (strpos($resolvedUrl, self::getIndpEnv('TYPO3_SITE_PATH')) === 0) { + $sanitizedUrl = $url; + } + } - - return $url; + // Log if url didn't passed + if ($sanitizedUrl === '' && !empty($url)) { + self::sysLog('Insecure Url was called: ' . $url, 't3lib_div::sanitizeBackEndUrl', 2); + } + return $sanitizedUrl; } /** Index: tests/t3lib/t3lib_div_testcase.php =================================================================== --- tests/t3lib/t3lib_div_testcase.php (revision 6382) +++ tests/t3lib/t3lib_div_testcase.php (working copy) @@ -346,71 +346,77 @@ //////////////////////////////////////// - // Tests concerning sanitizeBackEndUrl + // Tests concerning sanitizeLocalUrl //////////////////////////////////////// /** - * @test + * Data provider for valid URLs. + * @see sanitizeLocalUrlAcceptsValidUrls */ - public function sanitizeBackEndUrlForEmptyStringReturnsEmptyString() { - $this->assertEquals( - '', - t3lib_div::sanitizeBackEndUrl('') + public function validLocalUrlDataProvider() { + return array( + array('alt_intro.php'), + array('alt_intro.php?foo=1&bar=2'), + array('/typo3/alt_intro.php'), + array('../index.php'), + array('../typo3/alt_intro.php'), + array('../~userDirectory/index.php'), + array('../typo3/mod.php?var1=test-case&var2=~user'), + array(PATH_site . 'typo3/alt_intro.php'), + array(t3lib_div::getIndpEnv('TYPO3_SITE_URL') . 'typo3/alt_intro.php'), + array(t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST') . '/index.php'), ); } /** - * @test + * Data provider for invalid URLs. + * @see sanitizeLocalUrlDeniesInvalidUrls */ - public function sanitizeBackEndUrlLeavesAbsoluteIntroUrlUnchanged() { - $this->assertEquals( - '/typo3/alt_intro.php', - t3lib_div::sanitizeBackEndUrl('/typo3/alt_intro.php') + public function invalidLocalUrlDataProvider() { + return array( + array(''), + array('http://www.google.de/'), + array('https://www.google.de/'), + array('../typo3/whatever.php?argument=javascript:alert(0)'), ); } /** + * Tests whether valid local URLs are handled correctly. + * @dataProvider validLocalUrlDataProvider * @test */ - public function sanitizeBackEndUrlLeavesRelativeIntroUrlUnchanged() { - $this->assertEquals( - 'alt_intro.php', - t3lib_div::sanitizeBackEndUrl('alt_intro.php') - ); + public function sanitizeLocalUrlAcceptsPlainValidUrls($url) { + $this->assertEquals($url, t3lib_div::sanitizeBackEndUrl($url)); } /** + * Tests whether valid local URLs are handled correctly. + * @dataProvider validLocalUrlDataProvider * @test */ - public function sanitizeBackEndUrlLeavesRelativeIntroUrlWithParameterUnchanged() { - $this->assertEquals( - 'alt_intro.php?foo=1&bar=2', - t3lib_div::sanitizeBackEndUrl('alt_intro.php?foo=1&bar=2') - ); + public function sanitizeLocalUrlAcceptsEncodedValidUrls($url) { + $this->assertEquals(rawurlencode($url), t3lib_div::sanitizeBackEndUrl(rawurlencode($url))); } /** + * Tests whether valid local URLs are handled correctly. + * @dataProvider invalidLocalUrlDataProvider * @test */ - public function sanitizeBackEndUrlForFullUrlReturnsEmptyString() { - $this->assertEquals( - '', - t3lib_div::sanitizeBackEndUrl('http://www.google.de/') - ); + public function sanitizeLocalUrlDeniesPlainInvalidUrls($url) { + $this->assertEquals('', t3lib_div::sanitizeBackEndUrl($url)); } /** + * Tests whether valid local URLs are handled correctly. + * @dataProvider invalidLocalUrlDataProvider * @test */ - public function sanitizeBackEndUrlForRelativeIntroUrlWithEncodedCharacterReturnsEmptyString() { - $this->assertEquals( - '', - t3lib_div::sanitizeBackEndUrl('alt_intro.php?%20') - ); + public function sanitizeLocalUrlDeniesEncodedInvalidUrls($url) { + $this->assertEquals('', t3lib_div::sanitizeBackEndUrl(rawurlencode($url))); } - - ////////////////////////////////////// // Tests concerning removeDotsFromTS ////////////////////////////////////// Index: typo3/alt_mod_frameset.php =================================================================== --- typo3/alt_mod_frameset.php (revision 6382) +++ typo3/alt_mod_frameset.php (working copy) @@ -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.= ' - +