Skip to content

node-html-pdf - Two Arbitrary File Read - Fix #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from

Conversation

huntr-helper
Copy link

@huntr-helper huntr-helper commented Feb 21, 2020

Fix 1 - Arbitrary File Read

https://github.com/mufeedvh fixed the vulnerability associated with Arbitrary File Read.
This fix is being submitted on behalf of https://github.com/mufeedvh - they have been awarded $25 for fixing the vulnerability through the huntr bug bounty program.
Think you could fix a vulnerability like this - get involved (https://huntr.dev).
Q | A
Version Affected | ALL
Bug Fix | YES
Further References | 418sec#2

Fix 2 - Arbitrary File Read

https://huntr.dev/users/Mik317 fixed the vulnerability associated with Arbitrary File Read.
This fix is being submitted on behalf of https://huntr.dev/users/Mik317 - they have been awarded $25 for fixing the vulnerability through the huntr bug bounty program.
Think you could fix a vulnerability like this - get involved (https://huntr.dev).
Q | A
Version Affected | ALL
Bug Fix | YES
Further References | 418sec#3

User Comments:

📊 Metadata *

Bounty URL: https://www.huntr.dev/bounties/1-npm-html-pdf

⚙️ Description *

The node-html-pdf module is vulnerable against arbitrary file read due to a unsafe usage of phantomjs, which makes possible reading local files when parsing html files to convert in pdf ones.

💻 Technical Description *

As suggested on #530 (comment), I added as default argument the --local-url-access=false options, which makes impossible reading local files 😄
The user is still able to provide access to the local files setting the readLocalFile option to true 😄

🐛 Proof of Concept (PoC) *

  1. Download the repo
  2. Go on the directory node-html-pdf
  3. Create the poc.js file:
var fs = require('fs');
var pdf = require('./');
var html = fs.readFileSync('./test/example.html', 'utf8');
var options = { format: 'Letter' , phantomArgs: ["--web-security=no"]};

pdf.create(html, options).toFile('./example.pdf', function(err, res) {
  if (err) return console.log(err);
  console.log(res); // { filename: '/app/businesscard.pdf' }
});
  1. node poc.js
  2. A example.pdf file with the content of /etc/passwd is created

🔥 Proof of Fix (PoF) *

Same steps with fixed version doesn't create a file with the content of the /etc/passwd file

If the user explicity uses readLocalFile inside the options, then the internal files are fetched again (only who writes the code can change it, so no possible bypasses are allowed for other users 😄)

👍 User Acceptance Testing (UAT)

Run a unit test or a legitimate use case to prove that your fix does not introduce breaking changes.

@JamieSlome
Copy link

@marcbachmann - any updates on this?

@huntr-helper
Copy link
Author

@marcbachmann - code quality issues addressed and fixed.

@theaccordance
Copy link

Hi, checking in on the status for accepting this PR, it surfaced in a recent app scan

@huntr-helper huntr-helper changed the title node-html-pdf - Arbitrary File Read - Fix: node-html-pdf - Two Arbitrary File Read - Fix Sep 3, 2020
@navjotdhanawat
Copy link

@marcbachmann @huntr-helper when we are planning to publish fix for this issue?

Thanks

@JamieSlome
Copy link

@navjotdhanawat - we are just waiting to hear back from the maintainer, but hopefully as soon as possible!

Copy link
Owner

@marcbachmann marcbachmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the absence.

We can merge that and release it in a major bump as it's a breaking change.
I guess we should also deprecate the library because it's api is phantomjs-oriented and doesn't make sense with more modern setup where a pool of headless workers should be used.

@Drarox
Copy link

Drarox commented Sep 30, 2020

Any updates ?

@clawdaddy
Copy link

@chriskinsman any chance you could take a look at this?

@marcbachmann
Copy link
Owner

marcbachmann commented Nov 9, 2020

Should we trigger a breaking change here and release v3?
I'd keep the default value to allow file access in v2. But also expose the option to disable it.

@JamieSlome
Copy link

@marcbachmann - let me know if you need any changes made to the PR, cheers! 👍

@ucefkh
Copy link

ucefkh commented Nov 10, 2020

wow nice this is moving, I was about to make a fork and merge this then deploy to npm because this is very serious and needed fix!

Can this be merged today?

thank you guys

@@ -22,7 +27,7 @@ function help () {
}

function htmlpdf (source, destination) {
var html = fs.readFileSync(source, 'utf8')
var html = DOMPurify.sanitize(fs.readFileSync(source, 'utf8'))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this won't help anything regardong security. I wouldn't take jsdom into the project as dependency.
the option which sets the flag is enough. Let's release that as v3 then.
I guess we can can skip a release in v2 as it won't help anything.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean we should check whether we can limit the origins of urls (content security policy maybe?). That would be much cleaner. In some cases remote content is desired.

Copy link

@ucefkh ucefkh Nov 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, normally there should be a restriction to the source or format of origins or urls in the config before even been able to read the file?

Some like

const config = {
          allowedFolders:  ['/tmp','render'],
         allowedDomains: ['domain1.tld','domain2']
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be supported using page.onResourceRequested: https://phantomjs.org/api/webpage/handler/on-resource-requested.html

Copy link

@ucefkh ucefkh Nov 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow. spot on! then we just match the options in the config with


  var match = requestData.url.match(/wordfamily.js/g); or includes? 
const allowed = config.allowedFolders.contains(requestData.url.split('/')[0])// a bit hacky but you get the idea?
if(!allowed) return networkRequest.abort()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So glad y'all are figuring this out. Cause I don't really know what is going on. I just want that npm audit vulnerability to go away.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well this is easy to fix just the incentive to is the issues sometimes :D I can write a good fix for it tho before it goes even to phantomjs

@eran10
Copy link

eran10 commented Mar 18, 2021

any new here ? can this be merged ?

@olvresc
Copy link

olvresc commented Apr 14, 2021

Hi, any update on this?

@ucefkh
Copy link

ucefkh commented Apr 14, 2021 via email

@PabloMontoya
Copy link

Any news on this?

@marcbachmann
Copy link
Owner

marcbachmann commented Apr 22, 2021

Fixed in #616 and released with Version 3.

There's a new localUrlAccess option, which sets --local-url-access=false by default.
Sorry for the looong wait. I just don't think it's feasable to maintain this lib as phantomjs got deprecated a long time ago.
I also don't use it anymore and it originally was developed for much simpler use cases than what most people use it for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.