Version in base suite: 4.2.5-1+lenny1 Version in overlay suite: (not present) Base version: typo3-src_4.2.5-1+lenny1 Target version: typo3-src_4.2.5-1+lenny2 Base file: /org/ftp.debian.org/ftp/pool/main/t/typo3-src/typo3-src_4.2.5-1+lenny1.dsc Target file: /org/ftp.debian.org/queue/p-u-new/typo3-src_4.2.5-1+lenny2.dsc debian/patches/04-SecBull-TYPO3-SA-2009-016.dpatch | 1045 +++++++++++++++++++++ typo3-src-4.2.5/debian/changelog | 18 typo3-src-4.2.5/debian/patches/00list | 1 3 files changed, 1064 insertions(+) diff -u typo3-src-4.2.5/debian/changelog typo3-src-4.2.5/debian/changelog --- typo3-src-4.2.5/debian/changelog +++ typo3-src-4.2.5/debian/changelog @@ -1,3 +1,21 @@ +typo3-src (4.2.5-1+lenny2) stable-security; urgency=high + + * Added patches (backported from 4.2.10) to fix the security issues + from "TYPO3 Security Bulletin TYPO3-SA-2009-016: Multiple + vulnerabilities in TYPO3 Core" with the following CVEs assigned: + CVE-2009-3628 TYPO3 Information disclosure + CVE-2009-3629 TYPO3 Cross-site scripting + CVE-2009-3630 TYPO3 Frame hijacking + CVE-2009-3631 TYPO3 Remote shell command execution + CVE-2009-3632 TYPO3 SQL injection + CVE-2009-3633 TYPO3 API function t3lib_div::quoteJSvalue XSS + CVE-2009-3634 TYPO3 Frontend Login Box (felogin) XSS + CVE-2009-3635 TYPO3 Insecure Authentication and Session Handling + CVE-2009-3636 TYPO3 Install Tool XSS + (Closes: 552020). + + -- Christian Welzel Thu, 22 Oct 2009 22:00:00 +0100 + typo3-src (4.2.5-1+lenny1) testing-security; urgency=high * Added patches (backported from 4.2.6) to fix a critical information diff -u typo3-src-4.2.5/debian/patches/00list typo3-src-4.2.5/debian/patches/00list --- typo3-src-4.2.5/debian/patches/00list +++ typo3-src-4.2.5/debian/patches/00list @@ -3,0 +4 @@ +04-SecBull-TYPO3-SA-2009-016.dpatch only in patch2: unchanged: --- typo3-src-4.2.5.orig/debian/patches/04-SecBull-TYPO3-SA-2009-016.dpatch +++ typo3-src-4.2.5/debian/patches/04-SecBull-TYPO3-SA-2009-016.dpatch @@ -0,0 +1,1045 @@ +#!/bin/sh /usr/share/dpatch/dpatch-run +## 04-SecBull-TYPO3-SA-2009-016.dpatch by Christian Welzel +## +## DP: Fixes TYPO3-SA-2009-016 + +@DPATCH@ + +diff -Naur typo3-src-4.2.9/t3lib/class.t3lib_div.php typo3-src-4.2.10/t3lib/class.t3lib_div.php +--- typo3-src-4.2.9/t3lib/class.t3lib_div.php 2009-09-28 19:58:33.000000000 +0200 ++++ typo3-src-4.2.10/t3lib/class.t3lib_div.php 2009-10-22 14:14:56.000000000 +0200 +@@ -3864,6 +3866,24 @@ + } + + /** ++ * Checks if a given string is a valid frame URL to be loaded in the ++ * backend. ++ * ++ * @param string $url potential URL to check ++ * ++ * @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 = ''; ++ } ++ ++ return $url; ++ } ++ ++ /** + * Moves $source file to $destination if uploaded, otherwise try to make a copy + * Usage: 4 + * +@@ -5207,21 +5227,27 @@ + return $paramsArr; + } + +- + /** +- * Quotes a string for usage as JS parameter. Depends wheter the value is used in script tags (it doesn't need/must not get htmlspecialchar'ed in this case) +- * +- * @param string The string to encode. +- * @param boolean If the values get's used in '; + +- $this->message('Password', 'Enter the Install Tool Password', $content,3); ++ if (!$this->session->isAuthorized() && $this->session->isExpired()) { ++ $this->message('Password', 'Your install tool session has expired', '', 3); ++ } ++ $this->message('Password', 'Enter the Install Tool Password', $content, 2); + $this->output($this->outputWrapper($this->printAll())); + } + +diff -Naur typo3-src-4.2.9/typo3/sysext/install/mod/class.tx_install_session.php typo3-src-4.2.10/typo3/sysext/install/mod/class.tx_install_session.php +--- typo3-src-4.2.9/typo3/sysext/install/mod/class.tx_install_session.php 1970-01-01 01:00:00.000000000 +0100 ++++ typo3-src-4.2.10/typo3/sysext/install/mod/class.tx_install_session.php 2009-10-22 14:15:18.000000000 +0200 +@@ -0,0 +1,363 @@ ++ ++* 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. ++* A copy is found in the textfile GPL.txt and important notices to the license ++* from the author is found in LICENSE.txt distributed with these scripts. ++* ++* ++* 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! ++***************************************************************/ ++ ++/** ++ * Secure session handling for the install tool. ++ * ++ * @author Ernesto Baschny ++ * ++ * @package TYPO3 ++ * @subpackage tx_install ++ * ++ * @version $Id$ ++ */ ++class tx_install_session { ++ ++ /** ++ * The path to our typo3temp (where we can write our sessions). Set in the ++ * constructor. ++ * ++ * @var string ++ */ ++ private $typo3tempPath; ++ ++ /** ++ * Path where to store our session files in typo3temp. %s will be ++ * non-guesseable. ++ * ++ * @var string ++ */ ++ private $sessionPath = 'sessions%s'; ++ ++ /** ++ * the cookie to store the session ID of the install tool ++ * ++ * @var string ++ */ ++ private $cookieName = 'Typo3InstallTool'; ++ ++ /** ++ * time (minutes) to expire an ununsed session ++ * ++ * @var integer ++ */ ++ private $expireTimeInMinutes = 60; ++ ++ /** ++ * time (minutes) to generate a new session id for our current session ++ * ++ * @var integer ++ */ ++ private $regenerateSessionIdTime = 5; ++ ++ /** ++ * Constructor. Starts PHP session handling in our own private store ++ * ++ * Side-effect: might set a cookie, so must be called before any other output. ++ */ ++ public function __construct() { ++ $this->typo3tempPath = PATH_site . 'typo3temp/'; ++ ++ // Start our PHP session early so that hasSession() works ++ $sessionSavePath = $this->getSessionSavePath(); ++ if (!is_dir($sessionSavePath)) { ++ if (!t3lib_div::mkdir($sessionSavePath)) { ++ die('Could not create session folder in typo3temp/. Make sure it is writeable!'); ++ } ++ t3lib_div::writeFile($sessionSavePath.'/.htaccess', 'Order deny, allow'."\n".'Deny from all'."\n"); ++ $indexContent = ''; ++ $indexContent .= ''; ++ $indexContent .= ''; ++ t3lib_div::writeFile($sessionSavePath.'/index.html', $indexContent); ++ } ++ // Register our "save" session handler ++ session_set_save_handler( ++ array($this, 'open'), ++ array($this, 'close'), ++ array($this, 'read'), ++ array($this, 'write'), ++ array($this, 'destroy'), ++ array($this, 'gc') ++ ); ++ session_save_path($sessionSavePath); ++ session_name($this->cookieName); ++ ini_set('session.cookie_path', t3lib_div::getIndpEnv('TYPO3_SITE_PATH')); ++ // Always call the garbage collector to clean up stale session files ++ ini_set('session.gc_probability', 100); ++ ini_set('session.gc_divisor', 100); ++ ini_set('session.gc_maxlifetime', $this->expireTimeInMinutes*2*60); ++ if (version_compare(phpversion(), '5.2', '<')) { ++ ini_set('session.cookie_httponly', TRUE); ++ } ++ session_start(); ++ } ++ ++ /** ++ * Returns the path where to store our session files ++ */ ++ private function getSessionSavePath() { ++ return sprintf( ++ $this->typo3tempPath . '/' . $this->sessionPath, ++ md5( ++ 'session:' . ++ $GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'] ++ ) ++ ); ++ } ++ ++ /** ++ * Starts a new session ++ * ++ * @return string The session ID ++ */ ++ public function startSession() { ++ $_SESSION['created'] = time(); ++ return session_id(); ++ } ++ ++ /** ++ * Generates a new session ID and sends it to the client. ++ * ++ * Also moves session information from the old session to the new one ++ * (in PHP 5.1 or later) ++ * ++ * @return string the new session ID ++ */ ++ private function renewSession() { ++ if (version_compare(phpversion(), '5.1', '<')) { ++ session_regenerate_id(TRUE); ++ } else { ++ session_regenerate_id(); ++ } ++ return session_id(); ++ } ++ ++ /** ++ * Checks whether we already have an active session. ++ * ++ * @return boolean true if there is an active session, false otherwise ++ */ ++ public function hasSession() { ++ return (isset($_SESSION['created'])); ++ } ++ ++ /** ++ * Returns the session ID of the running session. ++ * ++ * @return string the session ID ++ */ ++ public function getSessionId() { ++ return session_id(); ++ } ++ ++ /** ++ * Returns a session hash, which can only be calculated by the server. ++ * Used to store our session files without exposing the session ID. ++ * ++ * @param string An alternative session ID. Defaults to our current session ID ++ * ++ * @return string the session hash ++ */ ++ private function getSessionHash($sessionId = '') { ++ if (!$sessionId) { ++ $sessionId = $this->getSessionId(); ++ } ++ return md5($GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'].'|'.$sessionId); ++ } ++ ++ /** ++ * Marks this session as an "authorized" one (login successful). ++ * Should only be called if: ++ * a) we have a valid session running ++ * b) the "password" or some other authorization mechanism really matched ++ * ++ * @return void ++ */ ++ public function setAuthorized() { ++ $_SESSION['authorized'] = TRUE; ++ $_SESSION['lastSessionId'] = time(); ++ $_SESSION['tstamp'] = time(); ++ $_SESSION['expires'] = (time() + ($this->expireTimeInMinutes*60)); ++ } ++ ++ /** ++ * Check if we have an already authorized session ++ * ++ * @return boolean True if this session has been authorized before (by a correct password) ++ */ ++ public function isAuthorized() { ++ if (!$_SESSION['authorized']) { ++ return FALSE; ++ } ++ if ($_SESSION['expires'] < time()) { ++ // This session has already expired ++ return FALSE; ++ } ++ return TRUE; ++ } ++ ++ /** ++ * Check if our session is expired. ++ * Useful only right after a false "isAuthorized" to see if this is the ++ * reason for not being authorized anymore. ++ * ++ * @return boolean True if an authorized session exists, but is expired ++ */ ++ public function isExpired() { ++ if (!$_SESSION['authorized']) { ++ // Session never existed, means it is not "expired" ++ return FALSE; ++ } ++ if ($_SESSION['expires'] < time()) { ++ // This session was authorized before, but has expired ++ return TRUE; ++ } ++ return FALSE; ++ } ++ ++ /** ++ * Refreshes our session information, rising the expire time. ++ * Also generates a new session ID every 5 minutes to minimize the risk of ++ * session hijacking. ++ * ++ * @return void ++ */ ++ public function refreshSession() { ++ $_SESSION['tstamp'] = time(); ++ $_SESSION['expires'] = time() + ($this->expireTimeInMinutes*60); ++ if (time() > $_SESSION['lastSessionId']+$this->regenerateSessionIdTime*60) { ++ // Renew our session ID ++ $_SESSION['lastSessionId'] = time(); ++ $this->renewSession(); ++ } ++ } ++ ++ ++ /************************* ++ * ++ * PHP session handling with "secure" session files (hashed session id) ++ * see http://www.php.net/manual/en/function.session-set-save-handler.php ++ * ++ *************************/ ++ ++ /** ++ * Returns the file where to store our session data ++ * ++ * @return string A filename ++ */ ++ private function getSessionFile($id) { ++ $sessionSavePath = $this->getSessionSavePath(); ++ return $sessionSavePath . '/hash_' . $this->getSessionHash($id); ++ } ++ ++ /** ++ * Open function. See @session_set_save_handler ++ * ++ * @param string $savePath ++ * @param string $sessionName ++ * @return boolean ++ */ ++ public function open($savePath, $sessionName) { ++ return TRUE; ++ } ++ ++ /** ++ * Close function. See @session_set_save_handler ++ * ++ * @return boolean ++ */ ++ public function close() { ++ return TRUE; ++ } ++ ++ /** ++ * Read session data. See @session_set_save_handler ++ * ++ * @param string The session id ++ * ++ * @return string ++ */ ++ public function read($id) { ++ $sessionFile = $this->getSessionFile($id); ++ return (string) @file_get_contents($sessionFile); ++ } ++ ++ /** ++ * Write session data. See @session_set_save_handler ++ * ++ * @param string The session id ++ * @param string The data to be stored ++ * ++ * @return boolean ++ */ ++ public function write($id, $sessionData) { ++ $sessionFile = $this->getSessionFile($id); ++ if ($fp = @fopen($sessionFile, 'w')) { ++ $return = fwrite($fp, $sessionData); ++ fclose($fp); ++ return $return; ++ } else { ++ return FALSE; ++ } ++ } ++ ++ /** ++ * Destroys one session. See @session_set_save_handler ++ * ++ * @param string The session id ++ * ++ * @return string ++ */ ++ public function destroy($id) { ++ $sessionFile = $this->getSessionFile($id); ++ return(@unlink($sessionFile)); ++ } ++ ++ /** ++ * Garbage collect session info. See @session_set_save_handler ++ * ++ * @param integer The setting of session.gc_maxlifetime ++ * ++ * @return string ++ */ ++ public function gc($maxLifeTime) { ++ $sessionSavePath = $this->getSessionSavePath(); ++ foreach (glob($sessionSavePath . '/hash_*') as $filename) { ++ if (filemtime($filename) + ($this->expireTimeInMinutes*60) < time()) { ++ @unlink($filename); ++ } ++ } ++ return TRUE; ++ } ++ ++} ++ ++if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install_session.php']) { ++ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install_session.php']); ++} ++ ++?> +\ Kein Zeilenumbruch am Dateiende. +diff -Naur typo3-src-4.2.9/typo3/view_help.php typo3-src-4.2.10/typo3/view_help.php +--- typo3-src-4.2.9/typo3/view_help.php 2009-09-28 19:59:18.000000000 +0200 ++++ typo3-src-4.2.10/typo3/view_help.php 2009-10-22 14:15:26.000000000 +0200 +@@ -149,6 +149,10 @@ + + // Setting GPvars: + $this->tfID = t3lib_div::_GP('tfID'); ++ // Sanitizes the tfID using whitelisting. ++ if (!preg_match('/^[a-zA-Z0-9_\-\.]*$/', $this->tfID)) { ++ $this->tfID = ''; ++ } + if (!$this->tfID) { + if (($this->ffID = t3lib_div::_GP('ffID'))) { + $this->ffID = unserialize(base64_decode($this->ffID));