[SECURITY] Open redirection with jumpurl 27/18727/2
authorFranz G. Jahn <franzjahn@cron-it.de>
Wed, 6 Mar 2013 10:48:37 +0000 (11:48 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Wed, 6 Mar 2013 10:48:41 +0000 (11:48 +0100)
jumpurl allows redirect to any given URL. A hash on the url
is now required to know if the jumpurl has been created
by the system or by the outside.

The hook "jumpurlRedirectHandler" can be used to allow
redirects without hash or to custom redirects.

Fixes: #28587
Releases: 6.1, 6.0, 4.7, 4.6, 4.5
Change-Id: I63da18b1963ec50cd95dd49d1669c9873b7bab54
Security-Commit: 3c9774e15f7e0873addd48688be44110d1eccbb7
Security-Bulletin: TYPO3-CORE-SA-2013-001
Reviewed-on: https://review.typo3.org/18727
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
t3lib/class.t3lib_div.php
typo3/sysext/cms/tslib/class.tslib_content.php
typo3/sysext/cms/tslib/class.tslib_fe.php

index b18c8d8..bfe7bf6 100644 (file)
@@ -1195,27 +1195,28 @@ final class t3lib_div {
        /**
         * Returns a proper HMAC on a given input string and secret TYPO3 encryption key.
         *
-        * @param        string         Input string to create HMAC from
-        * @return       string         resulting (hexadecimal) HMAC currently with a length of 40 (HMAC-SHA-1)
+        * @param string $input Input string to create HMAC from
+        * @param string $additionalSecret additionalSecret to prevent hmac beeing used in a different context
+        * @return string resulting (hexadecimal) HMAC currently with a length of 40 (HMAC-SHA-1)
         */
-       public static function hmac($input) {
+       public static function hmac($input, $additionalSecret = '') {
                $hashAlgorithm = 'sha1';
                $hashBlocksize = 64;
                $hmac = '';
-
+               $secret = $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . $additionalSecret;
                if (extension_loaded('hash') && function_exists('hash_hmac') && function_exists('hash_algos') && in_array($hashAlgorithm, hash_algos())) {
-                       $hmac = hash_hmac($hashAlgorithm, $input, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']);
+                       $hmac = hash_hmac($hashAlgorithm, $input, $secret);
                } else {
                                // outer padding
                        $opad = str_repeat(chr(0x5C), $hashBlocksize);
                                // innner padding
                        $ipad = str_repeat(chr(0x36), $hashBlocksize);
-                       if (strlen($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']) > $hashBlocksize) {
+                       if (strlen($secret) > $hashBlocksize) {
                                        // keys longer than blocksize are shorten
-                               $key = str_pad(pack('H*', call_user_func($hashAlgorithm, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])), $hashBlocksize, chr(0x00));
+                               $key = str_pad(pack('H*', call_user_func($hashAlgorithm, $secret)), $hashBlocksize, chr(0x00));
                        } else {
                                        // keys shorter than blocksize are zero-padded
-                               $key = str_pad($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], $hashBlocksize, chr(0x00));
+                               $key = str_pad($secret, $hashBlocksize, chr(0x00));
                        }
                        $hmac = call_user_func($hashAlgorithm, ($key ^ $opad) . pack('H*', call_user_func($hashAlgorithm, ($key ^ $ipad) . $input)));
                }
@@ -6258,4 +6259,4 @@ final class t3lib_div {
        }
 }
 
-?>
+?>
\ No newline at end of file
index 169901c..5267eb7 100644 (file)
@@ -4849,12 +4849,9 @@ class tslib_cObj {
                                }
                                $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
                                if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
-                                       $res = '<a' . ' href="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix .
-                                               $GLOBALS['TSFE']->config['mainScript'] . $initP .
-                                               '&jumpurl=' . rawurlencode('http://' . $parts[0]) . $GLOBALS['TSFE']->getMethodUrlIdToken) . '"' .
-                                               ($target ? ' target="' . $target . '"' : '') .
-                                               $aTagParams . $this->extLinkATagParams('http://' . $parts[0], 'url') .
-                                               '>';
+                                       $jumpurl = 'http://' . $parts[0];
+                                       $juHash = t3lib_div::hmac($jumpurl, 'jumpurl');
+                                       $res = '<a' . ' href="' . htmlspecialchars(($GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP . '&jumpurl=' . rawurlencode($jumpurl))) . '&juHash=' . $juHash . $GLOBALS['TSFE']->getMethodUrlIdToken . '"' . ($target ? ' target="' . $target . '"' : '') . $aTagParams . $this->extLinkATagParams(('http://' . $parts[0]), 'url') . '>';
                                } else {
                                        $res = '<a' . ' href="http://' . htmlspecialchars($parts[0]) . '"' .
                                                ($target ? ' target="' . $target . '"' : '') .
@@ -5603,10 +5600,10 @@ class tslib_cObj {
                                                $scheme = '';
                                        }
                                        if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
-                                               $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix .
-                                                       $GLOBALS['TSFE']->config['mainScript'] . $initP .
-                                                       '&jumpurl=' . rawurlencode($scheme . $link_param) .
-                                                       $GLOBALS['TSFE']->getMethodUrlIdToken;
+                                               $url = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP;
+                                               $jumpurl = $scheme . $link_param;
+                                               $juHash = t3lib_div::hmac($jumpurl, 'jumpurl');
+                                               $this->lastTypoLinkUrl = $url . '&jumpurl=' . rawurlencode($jumpurl) . '&juHash='. $juHash . $GLOBALS['TSFE']->getMethodUrlIdToken;
                                        } else {
                                                $this->lastTypoLinkUrl = $scheme . $link_param;
                                        }
@@ -5622,11 +5619,13 @@ class tslib_cObj {
                                                        $linktxt = rawurldecode($link_param);
                                                if ($GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $conf['jumpurl']) {
                                                        $theFileEnc = str_replace('%2F', '/', rawurlencode(rawurldecode($link_param)));
-                                                       $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix .
-                                                               $GLOBALS['TSFE']->config['mainScript'] . $initP .
-                                                               '&jumpurl=' . rawurlencode($link_param) .
-                                                               ($conf['jumpurl.']['secure'] ? $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) : '') .
-                                                               $GLOBALS['TSFE']->getMethodUrlIdToken;
+                                                       $url = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP . '&jumpurl=' . rawurlencode($link_param);
+                                                       if ($conf['jumpurl.']['secure']) {
+                                                               $url .= $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']);
+                                                       } else {
+                                                               $url .= '&juHash=' . t3lib_div::hmac($link_param, 'jumpurl');
+                                                       }
+                                                       $this->lastTypoLinkUrl =  $url . $GLOBALS['TSFE']->getMethodUrlIdToken;
                                                } else {
                                                        $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix . $link_param;
                                                }
@@ -6240,8 +6239,8 @@ class tslib_cObj {
                                $linktxt = str_ireplace($mailAddress, $spamProtectedMailAddress, $linktxt);
                        }
                } else {
-                       $mailToUrl = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] .
-                               $initP . '&jumpurl=' . rawurlencode($mailToUrl) . $GLOBALS['TSFE']->getMethodUrlIdToken;
+                       $juHash = t3lib_div::hmac($mailToUrl, 'jumpurl');
+                       $mailToUrl = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP . '&jumpurl=' . rawurlencode($mailToUrl) . '&juHash=' . $juHash . $GLOBALS['TSFE']->getMethodUrlIdToken;
                }
                return array(
                        $mailToUrl, $linktxt
index ea3d024..d986303 100644 (file)
                                                        break;
                                        }
                                }
-                               t3lib_utility_Http::redirect($this->jumpurl, $statusCode);
+                               $allowRedirect = FALSE;
+                               if (t3lib_div::hmac($this->jumpurl, 'jumpurl') === (string)t3lib_div::_GP('juHash')) {
+                                       $allowRedirect = TRUE;
+                               } elseif (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['jumpurlRedirectHandler'])) {
+                                       foreach ($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['jumpurlRedirectHandler'] as $classReference) {
+                                               $hookObject = t3lib_div::getUserObj($classReference);
+                                               $allowRedirectFromHook = FALSE;
+                                               if (method_exists($hookObject, 'jumpurlRedirectHandler')) {
+                                                       $allowRedirectFromHook = $hookObject->jumpurlRedirectHandler($this->jumpurl, $this);
+                                               }
+                                               if ($allowRedirectFromHook === TRUE) {
+                                                       $allowRedirect = TRUE;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if ($allowRedirect) {
+                                       t3lib_utility_Http::redirect($this->jumpurl, $statusCode);
+                               } else {
+                                       throw new Exception('jumpurl: Calculated juHash did not match the submitted juHash.', 1359987599);
+                               }
                        }
                }
        }
@@ -4892,4 +4912,4 @@ if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLA
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_fe.php']);
 }
 
-?>
+?>
\ No newline at end of file