Skip to content

Commit

Permalink
Fix security issue (breaking change)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaasuni committed Mar 18, 2024
1 parent 5fce932 commit 51cd1b3
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 76 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.TXT
@@ -1,3 +1,8 @@
6.7.0 (2024-03-18)
- Fix security issue.
- [BREAKING CHANGE] The tcpdf HTML tag syntax has changed, see example_049.php.
- New K_ALLOWED_TCPDF_TAGS configuration constant to set the allowed methods for the tcdpf HTML tag.

6.6.5 (2023-09-06)
- Fix corrupted file.

Expand Down
2 changes: 1 addition & 1 deletion LICENSE.TXT
Expand Up @@ -7,7 +7,7 @@
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

2002-2023 Nicola Asuni - Tecnick.com LTD
2002-2024 Nicola Asuni - Tecnick.com LTD

**********************************************************************
**********************************************************************
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -6,7 +6,7 @@

* **category** Library
* **author** Nicola Asuni <info@tecnick.com>
* **copyright** 2002-2023 Nicola Asuni - Tecnick.com LTD
* **copyright** 2002-2024 Nicola Asuni - Tecnick.com LTD
* **license** http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
* **link** http://www.tcpdf.org
* **source** https://github.com/tecnickcom/TCPDF
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
6.6.5
6.7.0
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -12,7 +12,7 @@
"barcodes"
],
"homepage": "http://www.tcpdf.org/",
"version": "6.6.5",
"version": "6.7.0",
"license": "LGPL-3.0-or-later",
"authors": [
{
Expand Down
12 changes: 12 additions & 0 deletions examples/config/tcpdf_config_alt.php
Expand Up @@ -212,6 +212,18 @@
*/
define('K_TCPDF_CALLS_IN_HTML', true);

/**
* List the TCPDF methods that are allowed to be called using HTML syntax.
* The constant K_TCPDF_CALLS_IN_HTML must be set to true.
* IMPORTANT: For security reason, disable this feature if you are allowing user HTML content.
*/
define('K_ALLOWED_TCPDF_TAGS', array(
'AddPage',
'Rect',
'SetDrawColor',
'write1DBarcode',
));

/**
* If true and PHP version is greater than 5, then the Error() method throw new exception instead of terminating the execution.
*/
Expand Down
34 changes: 18 additions & 16 deletions examples/example_049.php
Expand Up @@ -2,7 +2,7 @@
//============================================================+
// File name : example_049.php
// Begin : 2009-04-03
// Last Update : 2014-12-10
// Last Update : 2024-03-18
//
// Description : Example 049 for TCPDF class
// WriteHTML with TCPDF callback functions
Expand Down Expand Up @@ -78,11 +78,11 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
IMPORTANT:
If you are printing user-generated content, tcpdf tag can be unsafe.
You can disable this tag by setting to false the K_TCPDF_CALLS_IN_HTML
constant on TCPDF configuration file.
If you are printing user-generated content, the tcpdf tag should be considered unsafe.
This tag is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file.
Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.
For security reasons, the parameters for the 'params' attribute of TCPDF
For security reasons, the parameters for the 'params' attribute of TCPDF
tag must be prepared as an array and encoded with the
serializeTCPDFtagParameters() method (see the example below).
Expand All @@ -91,23 +91,25 @@

$html = '<h1>Test TCPDF Methods in HTML</h1>
<h2 style="color:red;">IMPORTANT:</h2>
<span style="color:red;">If you are using user-generated content, the tcpdf tag can be unsafe.<br />
You can disable this tag by setting to false the <b>K_TCPDF_CALLS_IN_HTML</b> constant on TCPDF configuration file.</span>
<span style="color:red;">If you are using user-generated content, the tcpdf tag should be considered unsafe.<br />
Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.<br />
This feature is disabled by default by the <b>K_TCPDF_CALLS_IN_HTML</b> constant on TCPDF configuration file.</span>
<h2>write1DBarcode method in HTML</h2>';

$params = $pdf->serializeTCPDFtagParameters(array('CODE 39', 'C39', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf method="write1DBarcode" params="'.$params.'" />';
$data = $pdf->serializeTCPDFtag('write1DBarcode', array('CODE 39', 'C39', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf data="'.$data.'" />';

$params = $pdf->serializeTCPDFtagParameters(array('CODE 128', 'C128', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf method="write1DBarcode" params="'.$params.'" />';
$data = $pdf->serializeTCPDFtag('write1DBarcode', array('CODE 128', 'C128', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf data="'.$data.'" />';

$html .= '<tcpdf method="AddPage" /><h2>Graphic Functions</h2>';
$data = $pdf->serializeTCPDFtag('AddPage');
$html .= '<tcpdf data="'.$data.'" /><h2>Graphic Functions</h2>';

$params = $pdf->serializeTCPDFtagParameters(array(0));
$html .= '<tcpdf method="SetDrawColor" params="'.$params.'" />';
$data = $pdf->serializeTCPDFtag('SetDrawColor', array(0));
$html .= '<tcpdf data="'.$data.'" />';

$params = $pdf->serializeTCPDFtagParameters(array(50, 50, 40, 10, 'DF', array(), array(0,128,255)));
$html .= '<tcpdf method="Rect" params="'.$params.'" />';
$data = $pdf->serializeTCPDFtag('Rect', array(50, 50, 40, 10, 'DF', array(), array(0,128,255)));
$html .= '<tcpdf data="'.$data.'" />';


// output the HTML content
Expand Down
2 changes: 1 addition & 1 deletion include/tcpdf_static.php
Expand Up @@ -55,7 +55,7 @@ class TCPDF_STATIC {
* Current TCPDF version.
* @private static
*/
private static $tcpdf_version = '6.6.5';
private static $tcpdf_version = '6.7.0';

/**
* String alias for total number of pages.
Expand Down
112 changes: 57 additions & 55 deletions tcpdf.php
@@ -1,13 +1,13 @@
<?php
//============================================================+
// File name : tcpdf.php
// Version : 6.6.5
// Version : 6.7.0
// Begin : 2002-08-03
// Last Update : 2023-09-06
// Last Update : 2024-03-18
// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
// -------------------------------------------------------------------
// Copyright (C) 2002-2023 Nicola Asuni - Tecnick.com LTD
// Copyright (C) 2002-2024 Nicola Asuni - Tecnick.com LTD
//
// This file is part of TCPDF software library.
//
Expand Down Expand Up @@ -128,7 +128,7 @@
* 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.<br>
* @package com.tecnick.tcpdf
* @brief PHP class for generating PDF documents without requiring external extensions.
* @version 6.6.5
* @version 6.7.0
* @author Nicola Asuni - info@tecnick.com
* @IgnoreAnnotation("protected")
* @IgnoreAnnotation("public")
Expand Down Expand Up @@ -17200,41 +17200,49 @@ protected function getSpaceString() {
}

/**
* Return an hash code used to ensure that the serialized data has been generated by this TCPDF instance.
* @param string $data serialized data
* @return string
* Serialize data to be used with TCPDF tag in HTML code.
* @param string $method TCPDF method name
* @param array $params Method parameters
* @return string Serialized data
* @public static
*/
protected function getHashForTCPDFtagParams($data) {
return md5(strlen($data).$this->file_id.$data);
}

/**
* Serialize an array of parameters to be used with TCPDF tag in HTML code.
* @param array $data parameters array
* @return string containing serialized data
* @public static
*/
public function serializeTCPDFtagParameters($data) {
public function serializeTCPDFtag($method, $params=array()) {
$data = array('m' => $method, 'p' => $params);
$encoded = urlencode(json_encode($data));
return $this->getHashForTCPDFtagParams($encoded).$encoded;
$hash = password_hash($encoded.'+'.$this->file_id, PASSWORD_DEFAULT);
return strlen($hash).'+'.$hash.'+'.$encoded;
}

/**
* Unserialize parameters to be used with TCPDF tag in HTML code.
* Unserialize data to be used with TCPDF tag in HTML code.
* @param string $data serialized data
* @return array containing unserialized data
* @protected static
*/
protected function unserializeTCPDFtagParameters($data) {
$hash = substr($data, 0, 32);
$encoded = substr($data, 32);
if ($hash != $this->getHashForTCPDFtagParams($encoded)) {
protected function unserializeTCPDFtag($data) {
$hpos = strpos($data, '+');
$hlen = intval(substr($data, 0, $hpos));
$hash = substr($data, $hpos + 1, $hlen);
$encoded = substr($data, $hpos + 2 + $hlen);
if (!password_verify($encoded.'+'.$this->file_id, $hash)) {
$this->Error('Invalid parameters');
}
return json_decode(urldecode($encoded), true);
}

/**
* Check if a TCPDF tag is allowed
* @param string $method TCPDF method name
* @return boolean
* @protected
*/
protected function allowedTCPDFtag($method) {
if (!defined('K_ALLOWED_TCPDF_TAGS') || empty(K_ALLOWED_TCPDF_TAGS)) {
return false;
}
return in_array($method, K_ALLOWED_TCPDF_TAGS, true);
}

/**
* Prints a cell (rectangular area) with optional borders, background color and html text string.
* The upper-left corner of the cell corresponds to the current position. After the call, the current position moves to the right or to the next line.<br />
Expand All @@ -17248,8 +17256,7 @@ protected function unserializeTCPDFtagParameters($data) {
* @param float|null $y upper-left corner Y coordinate
* @param string $html html text to print. Default value: empty string.
* @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)))
* @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL language)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
* @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL language)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
* @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false).
* @param boolean $reseth if true reset the last cell height (default true).
* @param string $align Allows to center or align the text. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul>
Expand Down Expand Up @@ -19510,17 +19517,14 @@ protected function openHTMLTagHandler($dom, $key, $cell) {
case 'tcpdf': {
if (defined('K_TCPDF_CALLS_IN_HTML') AND (K_TCPDF_CALLS_IN_HTML === true)) {
// Special tag used to call TCPDF methods
if (isset($tag['attribute']['method'])) {
$tcpdf_method = $tag['attribute']['method'];
if (method_exists($this, $tcpdf_method)) {
if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) {
$params = $this->unserializeTCPDFtagParameters($tag['attribute']['params']);
call_user_func_array(array($this, $tcpdf_method), $params);
} else {
$this->$tcpdf_method();
}
$this->newline = true;
// This tag is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file.
// Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.
if (!empty($tag['attribute']['data'])) {
$tcpdf_tag_data = $this->unserializeTCPDFtag($tag['attribute']['data']);
if ($this->allowedTCPDFtag($tcpdf_tag_data['m'])) {
call_user_func_array(array($this, $tcpdf_tag_data['m']), $tcpdf_tag_data['p']);
}
$this->newline = true;
}
}
break;
Expand Down Expand Up @@ -21867,25 +21871,23 @@ public function commitTransaction() {
* @since 4.5.029 (2009-03-19)
*/
public function rollbackTransaction($self=false) {
if (isset($this->objcopy)) {
$objcopy = $this->objcopy;
$this->_destroy(true, true);
if ($self) {
$objvars = get_object_vars($objcopy);
foreach ($objvars as $key => $value) {
$this->$key = $value;
}
$objcopy->_destroy(true, true);
/* The unique file_id should not be used during cleanup again */
$objcopy->file_id = NULL;
unset($objcopy);
return $this;
}
/* The unique file_id should not be used during cleanup again */
$this->file_id = NULL;
return $objcopy;
}
return $this;
if (!isset($this->objcopy)) {
return $this;
}
$file_id = $this->file_id;
$objcopy = $this->objcopy;
$this->_destroy(true, true);
if ($self) {
$objvars = get_object_vars($objcopy);
foreach ($objvars as $key => $value) {
$this->$key = $value;
}
$objcopy->_destroy(true, true);
unset($objcopy);
return $this;
}
$this->file_id = $file_id;
return $objcopy;
}

// --- MULTI COLUMNS METHODS -----------------------
Expand Down
4 changes: 4 additions & 0 deletions tcpdf_autoconfig.php
Expand Up @@ -228,6 +228,10 @@
define('K_TCPDF_CALLS_IN_HTML', false);
}

if (!defined('K_ALLOWED_TCPDF_TAGS')) {
define('K_ALLOWED_TCPDF_TAGS', array());
}

if (!defined('K_TCPDF_THROW_EXCEPTION_ERROR')) {
define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
}
Expand Down

0 comments on commit 51cd1b3

Please sign in to comment.