diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 7aa577f33fb..cb7e0729930 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -165,7 +165,7 @@ typo3 Typo3 GPL - 4.7.15 + 4.7.19 2.0+ diff --git a/lib/typo3/class.t3lib_div.php b/lib/typo3/class.t3lib_div.php index 3a3ba920197..c5012a675f3 100644 --- a/lib/typo3/class.t3lib_div.php +++ b/lib/typo3/class.t3lib_div.php @@ -59,6 +59,17 @@ final class t3lib_div { const SYSLOG_SEVERITY_ERROR = 3; const SYSLOG_SEVERITY_FATAL = 4; + const ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL = '.*'; + const ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME = 'SERVER_NAME'; + + /** + * State of host header value security check + * in order to avoid unnecessary multiple checks during one request + * + * @var bool + */ + static protected $allowHostHeaderValue = FALSE; + /** * Singleton instances returned by makeInstance, using the class names as * array keys @@ -3570,6 +3581,12 @@ final class t3lib_div { $retVal = $host; } } + if (!self::isAllowedHostHeaderValue($retVal)) { + throw new UnexpectedValueException( + 'The current host header value does not match the configured trusted hosts pattern! Check the pattern defined in $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'trustedHostsPattern\'] and adapt it, if you want to allow the current host header \'' . $retVal . '\' for your installation.', + 1396795884 + ); + } break; // These are let through without modification case 'HTTP_REFERER': @@ -3690,6 +3707,51 @@ final class t3lib_div { return $retVal; } + /** + * Checks if the provided host header value matches the trusted hosts pattern. + * If the pattern is not defined (which only can happen early in the bootstrap), deny any value. + * + * @param string $hostHeaderValue HTTP_HOST header value as sent during the request (may include port) + * @return bool + */ + static public function isAllowedHostHeaderValue($hostHeaderValue) { + if (self::$allowHostHeaderValue === TRUE) { + return TRUE; + } + + // Allow all install tool requests + // We accept this risk to have the install tool always available + // Also CLI needs to be allowed as unfortunately AbstractUserAuthentication::getAuthInfoArray() accesses HTTP_HOST without reason on CLI + if (defined('TYPO3_REQUESTTYPE') && (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_INSTALL) || (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI)) { + return self::$allowHostHeaderValue = TRUE; + } + + // Deny the value if trusted host patterns is empty, which means we are early in the bootstrap + if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'])) { + return FALSE; + } + + if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === self::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) { + self::$allowHostHeaderValue = TRUE; + } elseif ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === self::ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME) { + // Allow values that equal the server name + // Note that this is only secure if name base virtual host are configured correctly in the webserver + $defaultPort = self::getIndpEnv('TYPO3_SSL') ? '443' : '80'; + $parsedHostValue = parse_url('http://' . $hostHeaderValue); + if (isset($parsedHostValue['port'])) { + self::$allowHostHeaderValue = ($parsedHostValue['host'] === $_SERVER['SERVER_NAME'] && (string)$parsedHostValue['port'] === $_SERVER['SERVER_PORT']); + } else { + self::$allowHostHeaderValue = ($hostHeaderValue === $_SERVER['SERVER_NAME'] && $defaultPort === $_SERVER['SERVER_PORT']); + } + } else { + // In case name based virtual hosts are not possible, we allow setting a trusted host pattern + // See https://typo3.org/teams/security/security-bulletins/typo3-core/typo3-core-sa-2014-001/ for further details + self::$allowHostHeaderValue = (bool)preg_match('/^' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] . '$/', $hostHeaderValue); + } + + return self::$allowHostHeaderValue; + } + /** * Gets the unixtime as milliseconds. * @@ -4846,15 +4908,7 @@ final class t3lib_div { } // Create new instance and call constructor with parameters - if (func_num_args() > 1) { - $constructorArguments = func_get_args(); - array_shift($constructorArguments); - - $reflectedClass = new ReflectionClass($finalClassName); - $instance = $reflectedClass->newInstanceArgs($constructorArguments); - } else { - $instance = new $finalClassName; - } + $instance = static::instantiateClass($finalClassName, func_get_args()); // Register new singleton instance if ($instance instanceof t3lib_Singleton) { @@ -4864,6 +4918,54 @@ final class t3lib_div { return $instance; } + /** + * Speed optimized alternative to ReflectionClass::newInstanceArgs() + * + * @param string $className Name of the class to instantiate + * @param array $arguments Arguments passed to self::makeInstance() thus the first one with index 0 holds the requested class name + * @return mixed + */ + protected static function instantiateClass($className, $arguments) { + switch (count($arguments)) { + case 1: + $instance = new $className(); + break; + case 2: + $instance = new $className($arguments[1]); + break; + case 3: + $instance = new $className($arguments[1], $arguments[2]); + break; + case 4: + $instance = new $className($arguments[1], $arguments[2], $arguments[3]); + break; + case 5: + $instance = new $className($arguments[1], $arguments[2], $arguments[3], $arguments[4]); + break; + case 6: + $instance = new $className($arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5]); + break; + case 7: + $instance = new $className($arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6]); + break; + case 8: + $instance = new $className($arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6], $arguments[7]); + break; + case 9: + $instance = new $className($arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6], $arguments[7], $arguments[8]); + break; + default: + // The default case for classes with constructors that have more than 8 arguments. + // This will fail when one of the arguments shall be passed by reference. + // In case we really need to support this edge case, we can implement the solution from here: https://review.typo3.org/26344 + $class = new ReflectionClass($className); + array_shift($arguments); + $instance = $class->newInstanceArgs($arguments); + return $instance; + } + return $instance; + } + /** * Returns the class name for a new instance, taking into account the * class-extension API. @@ -5734,4 +5836,4 @@ final class t3lib_div { } } -?> \ No newline at end of file +?> diff --git a/lib/typo3/readme_moodle.txt b/lib/typo3/readme_moodle.txt index 0e188da4154..246aebfe16b 100644 --- a/lib/typo3/readme_moodle.txt +++ b/lib/typo3/readme_moodle.txt @@ -1,4 +1,4 @@ -Description of Typo3 libraries (v 4.7.15) import into Moodle +Description of Typo3 libraries (v 4.7.19) import into Moodle Changes: 1/ hacked relative include of class.t3lib_utility_debug.php