diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index 7e57f36..fd4c141 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -1,5 +1,10 @@ +6.9.3 (2025-04-20) + - New fix for "Deserialization of untrusted data" (check on valid protocols). + - Removed global phar configuration. + 6.9.2 (2025-04-18) - - Fixed "Deserialization of untrusted data" security vulnerability reported by Positive Technologies. + - Quick fix for "Deserialization of untrusted data" security vulnerability reported by Positive Technologies. + - Disable phar protocol globally. 6.9.1 (2025-04-03) - Fixed "Path Traversal" security vulnerability reported by Positive Technologies. diff --git a/VERSION b/VERSION index 6b9255c..5f54f91 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.9.2 +6.9.3 diff --git a/composer.json b/composer.json index 2c3e484..0668869 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "barcodes" ], "homepage": "http://www.tcpdf.org/", - "version": "6.9.2", + "version": "6.9.3", "license": "LGPL-3.0-or-later", "authors": [ { diff --git a/include/tcpdf_static.php b/include/tcpdf_static.php index 8842920..956f34a 100644 --- a/include/tcpdf_static.php +++ b/include/tcpdf_static.php @@ -55,7 +55,7 @@ class TCPDF_STATIC { * Current TCPDF version. * @private static */ - private static $tcpdf_version = '6.9.2'; + private static $tcpdf_version = '6.9.3'; /** * String alias for total number of pages. diff --git a/tcpdf.php b/tcpdf.php index 3b1bc40..deefe4a 100644 --- a/tcpdf.php +++ b/tcpdf.php @@ -1,7 +1,7 @@ * @package com.tecnick.tcpdf * @author Nicola Asuni - * @version 6.9.2 + * @version 6.9.3 */ // TCPDF configuration @@ -128,7 +128,7 @@ require_once(dirname(__FILE__).'/include/tcpdf_static.php'); * TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.
* @package com.tecnick.tcpdf * @brief PHP class for generating PDF documents without requiring external extensions. - * @version 6.9.2 + * @version 6.9.3 * @author Nicola Asuni - info@tecnick.com * @IgnoreAnnotation("protected") * @IgnoreAnnotation("public") @@ -6989,7 +6989,7 @@ class TCPDF { unset($imgdata); $imsize = @getimagesize($file); if ($imsize === FALSE) { - unlink($file); + $this->_unlink($file); $file = $original_file; } } @@ -7222,7 +7222,7 @@ class TCPDF { $tempname = TCPDF_STATIC::getObjFilename('img', $this->file_id); $img->writeImage($tempname); $info = TCPDF_IMAGES::_parsejpeg($tempname); - unlink($tempname); + $this->_unlink($tempname); $img->destroy(); } catch(Exception $e) { $info = false; @@ -7858,15 +7858,16 @@ class TCPDF { if ($handle = @opendir(K_PATH_CACHE)) { while ( false !== ( $file_name = readdir( $handle ) ) ) { if (strpos($file_name, '__tcpdf_'.$this->file_id.'_') === 0) { - unlink(K_PATH_CACHE.$file_name); + $this->_unlink(K_PATH_CACHE.$file_name); } } closedir($handle); } if (isset($this->imagekeys)) { foreach($this->imagekeys as $file) { - if (strpos($file, K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_') === 0 && TCPDF_STATIC::file_exists($file)) { - @unlink($file); + if ((strpos($file, K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_') === 0) + && TCPDF_STATIC::file_exists($file)) { + $this->_unlink($file); } } } @@ -18875,10 +18876,22 @@ class TCPDF { * @protected * @since 6.9.1 */ - protected function isRelativePath($path) { + protected function isRelativePath($path) { return (strpos(str_ireplace('%2E', '.', $this->unhtmlentities($path)), '..') !== false); } + /** + * Check if it contains a non-allowed external protocol. + * @param string $path path to check + * @return boolean true if the protocol is not allowed. + * @protected + * @since 6.9.3 + */ + protected function hasExtForbiddenProtocol($path) { + return ((strpos($path, '://') !== false) + && (preg_match('|^https?://|', $path) !== 1)); + } + /** * Process opening tags. * @param array $dom html dom array @@ -19078,6 +19091,8 @@ class TCPDF { // get image type from a local file path $imgsrc = substr($imgsrc, 7); $type = TCPDF_IMAGES::getImageFileType($imgsrc); + } elseif ($this->hasExtForbiddenProtocol($imgsrc)) { + break; } else { if (($imgsrc[0] === '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) { // fix image path @@ -24478,8 +24493,7 @@ class TCPDF { $img = '@'.base64_decode(substr($img, strlen($m[0]))); } else { // fix image path - if ($this->isRelativePath($img)) { - // accessing parent folders is not allowed + if ($this->isRelativePath($img) || $this->hasExtForbiddenProtocol($img)) { break; } if (!TCPDF_STATIC::empty_string($this->svgdir) AND (($img[0] == '.') OR (basename($img) == $img))) { @@ -24802,6 +24816,20 @@ class TCPDF { return TCPDF_STATIC::file_exists($file); } + /** + * Wrapper for unlink with disabled protocols. + * @param string $file + * @return bool + */ + protected function _unlink($file) + { + if ((strpos($file, '://') !== false) && ((substr($file, 0, 7) !== 'file://') || (!$this->allowLocalFiles))) { + // forbidden protocol + return false; + } + return @unlink($file); + } + } // END OF TCPDF CLASS //============================================================+ diff --git a/tcpdf_autoconfig.php b/tcpdf_autoconfig.php index 4c6cb83..d31ee87 100644 --- a/tcpdf_autoconfig.php +++ b/tcpdf_autoconfig.php @@ -40,10 +40,10 @@ * @version 1.2.1 */ -// Disable phar stream wrapper to prevent deserialization vulnerability. -if (in_array('phar', stream_get_wrappers(), true)) { - stream_wrapper_unregister('phar'); -} +// Disable phar stream wrapper globally. +// if (in_array('phar', stream_get_wrappers(), true)) { +// stream_wrapper_unregister('phar'); +// } // DOCUMENT_ROOT fix for IIS Webserver if ((!isset($_SERVER['DOCUMENT_ROOT'])) OR (empty($_SERVER['DOCUMENT_ROOT']))) {