Skip to content
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

[Vulnerability] Server side template injection leads to RCE #663

Closed
netcode opened this issue Apr 10, 2022 · 7 comments
Closed

[Vulnerability] Server side template injection leads to RCE #663

netcode opened this issue Apr 10, 2022 · 7 comments

Comments

@netcode
Copy link
Contributor

netcode commented Apr 10, 2022

Hey team, Thank you for this awesome project.

I found a template injection leads to Remote code execution. Using this vulnerability an attacker can update the value of outputFunctionName to inject a JS code which will be executed with the template compiled function.

I didn't post the details here, waiting for your confirmation on the right place to report the full details of this vulnerability.

Thanks again, waiting for your response.

@mde
Copy link
Owner

mde commented Apr 11, 2022

If you are giving end-users unfettered access to the render method, then you are using EJS in an inherently non-secure way. EJS is not meant to be used in this way.

EJS is effectively a JavaScript runtime. That's what it does — execute JavaScript. Reporting this type of issue in EJS would be like reporting something similar in bash.

@mde mde closed this as completed Apr 11, 2022
@netcode
Copy link
Contributor Author

netcode commented Apr 11, 2022

Thanks, @mde for the response.

template engines should have some safeguards against untrusted inputs (you already implemented some countermeasures to reduce the risk of unvalidated inputs (eg. escape* functions in utils)., you can't expect all the inputs used in the template to be static 🤷🏻‍♂️

I'm talking about vulnerable code like this

const express = require('express')
const app = express()
app.set('view engine', 'ejs');

app.get('/page', (req,res) => {
    res.render('page', req.query);
})

If you allow me I can put the full attack payload and clarify what happens.

@mde
Copy link
Owner

mde commented Apr 12, 2022

Thank you for this example. It is precisely how you should NOT be using EJS. You should never, ever run the render method with untrusted inputs — any more than you should be passing raw user-input to be used in raw SQL calls to your DB.

This doesn't imply the inputs have to be static. It implies that the app-developer creating userland code should be escaping or otherwise checking those user inputs, before handing them to what is, as I have noted, is in fact, a JavaScript runtime.

This is not a templating library that does simple parameterized variable substitution. It's "simply JavaScript," in every sense of those words. You get all the power of running full-blown JavaScript in your templates, which means YOU as the developer have the responsibility of securing your code.

Early on, I indulged these 'vulnerability' reports, because I imagined I was being a good community citizen, and indeed, some of them involved making sure the old API of passing options along with the data was safe to use in earlier versions of Express. That was actually worth doing.

But it is not possible to secure EJS from unfettered access to the render method. It's a fool's errand, and it gives the consumers of the library a false sense of security. You, as a user of the library, are responsible for securing the inputs you handle to render. Full stop.

@netcode
Copy link
Contributor Author

netcode commented Apr 13, 2022

Thank you for your detailed response. While I'm not aligned with what you said but every library is free to declare how it should be used and what is risky and what is not.

Also, I found that there is a fix already to this kind of issue created by @nicdumz here: 15ee698 - so I highly recommend just create a release and that's it.

To avoid this in the future I've updated my PR here #664 to clarify that in the readme.md & in security.md

@netcode
Copy link
Contributor Author

netcode commented Apr 18, 2022

@mde are you planning to do a release anytime soon?
I believe the validation implemented in the main branch is good. You can do a release (the last ejs release was > 1 year ago).

Also if you want to avoid further security reports targeting the render options, the best way is to highlight that in the readme.md to ensure users are not using ejs the wrong way. and security.md to make it clear for security researchers.

@mde
Copy link
Owner

mde commented Apr 20, 2022

@netcode You are 100% correct about that. We should do a much better job of setting expectations in the docs. I am totally underwater with work this week, but I am hoping to have some time this weekend to push out a release. Maybe I can add some caveating to the docs at the same time. Thanks so much for your understanding!

@kokushkin
Copy link

So, what is the outcome of this conversation?

Option 1: The documentation was mostly clear. So, update the docs. Maybe, apply the fix... just in case. Delete the vulnerability report so it doesn't show up with npm audit. (if the report is still there, it creates additional noise and it's harder to see what's really matter)

Option 2: The documentation was misleading so people are likely to be affected by this vulnerability. Then, fix the vulnerability. Because it's gonna be a major update of the documentation (read interface of the library) , create a new major version where the docs will be changed. (if major version isn't bumped - nobody notices and continues to use the package according to the old docs)

It looks to me that you've chosen Option 1. So @netcode maybe you delete(/decrease the severity level) this report so I don't see 3 critical errors (somehow it's getting multiplied) in my console ?

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

No branches or pull requests

3 participants