Skip to content

Instantly share code, notes, and snippets.

@ohader
Last active December 14, 2015 15:18
Show Gist options
  • Save ohader/5106476 to your computer and use it in GitHub Desktop.
Save ohader/5106476 to your computer and use it in GitHub Desktop.
<?php
/***************************************************************
* Copyright notice
*
* (c) 2013 TYPO3 CMS Core-Security Team <security@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* =========
* ATTENTION
* =========
*
* USE THIS SCRIPT AT YOUR OWN RISK!
* ---------------------------------
* It was build to show how to make use of the introduced jumpurl redirect handler.
* It is possible to by-pass any security checks for the cross-redirecting issue of
* the jumpurl feature - however the security check has been added for good reasons.
*/
/**
* jumpurl handlers concerning core-security issue #28587
*
* @author Steffen Ritter <steffen.ritter@typo3.org>
* @author Oliver Hader <oliver.hader@typo3.org>
* @see http://forge.typo3.org/issues/28587
*/
class Tx_JumpurlRedirect_Handler {
/**
* Handles jumpurl URLs that don't have a valid hash.
*
* @param string $url Submitted jumpurl
* @param tslib_fe $frontend Calling parent object (TSFE)
* @return boolean Whether to allow the redirect
*/
public function jumpurlRedirectHandler($url, tslib_fe $frontend) {
if (stripos($url, 'http://') !== 0 && stripos($url, 'https://') !== 0) {
return FALSE;
}
return (
// Uncomment the next "TRUE" line to by-pass the whole SECURITY mechanism
// TRUE ||
// Allow URLs that are used content elements and pages
$this->allowUrlsUsedInSiteContent($url) ||
// Allow URLs that are used in delivered direct mails
$this->allowUrlsUsedInDeliveredDirectMails($url) ||
// FALSE is returned if not other checks were valid
FALSE
);
}
/**
* Allow URLs that are used as external links in pages or linked in
* the bodytext of content elements.
*
* You may only need this if you have external sites caching your
* jumpurls. Your local page may be fixed by clearing cache.
*
* @param string $url Submitted jumpurl
* @return boolean Whether to allow the redirect
*/
protected function allowUrlsUsedInSiteContent($url) {
$pagesPattern = $this->getDatabase()->fullQuoteStr(
preg_replace('#^([a-z]+:)?//#i', '', $url),
'pages'
);
$pagesUsingUrl = $this->getDatabase()->exec_SELECTcountRows(
'*',
'pages',
'url = ' . $pagesPattern
);
$contentElementsPattern = $this->getDatabase()->fullQuoteStr(
'%' . $this->getDatabase()->escapeStrForLike($url, 'tt_content') . '%',
'tt_content'
);
$contentElementsUsingUrl = $this->getDatabase()->exec_SELECTcountRows(
'*',
'tt_content',
'bodytext LIKE ' . $contentElementsPattern .
'OR header_link LIKE ' . $contentElementsPattern
);
return ($pagesUsingUrl > 0 || $contentElementsUsingUrl > 0);
}
/**
* Allow URLs that are used in the content of for direct mail newsletters
* which have been delivered to accordant mail recipients.
*
* You may only need this if you have external sites caching your
* jumpurls. Your local page may be fixed by clearing cache.
*
* ATTENTION:
* Due to several decodings and queries, this be decrese your website's
* performance a lot if you've sent a lot of newsletters in the past.
*
* @param string $url Submitted jumpurl
* @return boolean Whether to allow the redirect
*/
protected function allowUrlsUsedInDeliveredDirectMails($url) {
if (!t3lib_extMgm::isLoaded('direct_mail')) {
return FALSE;
}
$directMailStatements = array();
$directMailNeedle = ':"' . t3lib_div::rawUrlEncodeFP($url) . '";';
$directMailPatterns = array(
$this->prepareBas64Pattern($directMailNeedle),
$this->prepareBas64Pattern(':' . $directMailNeedle),
$this->prepareBas64Pattern('::' . $directMailNeedle),
);
foreach ($directMailPatterns as $directMailPattern) {
$directMailStatements[] = 'mailContent LIKE ' . $this->getDatabase()->fullQuoteStr('%' . $directMailPattern . '%', 'sys_dmail');
}
$directMailSetsUsingUrl = $this->getDatabase()->exec_SELECTcountRows(
'*',
'sys_dmail',
'issent > 0 AND deleted = 0 AND (' . implode(' OR ', $directMailStatements) . ')'
);
return ($directMailSetsUsingUrl > 0);
}
/**
* Strips last four characters if original value is not a multiple
* of 3 and thus gets padding characters during base64 encoding.
* First four characters are always stripped, since it's unknown
* at which position the needle starts in the base64 representation.
*
* @param string $pattern
* @return string
*/
protected function prepareBas64Pattern($pattern) {
$encoded = base64_encode($pattern);
if (strlen($pattern) % 3 > 0) {
$encoded = substr($encoded, 0, -4);
}
$encoded = substr($encoded, 4);
return $encoded;
}
/**
* @return t3lib_DB
*/
protected function getDatabase() {
return $GLOBALS['TYPO3_DB'];
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment