Live data from Hacker News

How we exploited a code execution vulnerability in math.js

capacitorset.github.io

11–20 of 32 posts

Re: How we exploited a code execution vulnerability in math.js

#11

EDIT: removed my suggestion since it was unsafe. Thanks for pointing it out. I was hoping vm to offer you an isolated v8 interpreter without bindings that could used as a sandbox, but this wasn't the case.

The page explicitly says: "Note: The vm module is not a security mechanism. Do not use it to run untrusted code."

https://nodejs.org/api/vm.html#vm_vm_executing_javascript

Re: How we exploited a code execution vulnerability in math.js

#12

EDIT: removed my suggestion since it was unsafe. Thanks for pointing it out. I was hoping vm to offer you an isolated v8 interpreter without bindings that could used as a sandbox, but this wasn't the case.

Though the docs pretty clearly state "Note: The vm module is not a security mechanism. Do not use it to run untrusted code."

Re: How we exploited a code execution vulnerability in math.js

#16
post #13

Blacklists are a losing game. Always use a whitelist.

This was actually the second fix I had in mind, after the author mentioned that they would like mathjs to have complete browser support (and therefore couldn't use the `vm` module from Node.js):

>If, anyway, you want to make math.eval resistant against arbitrary code execution, I think it would be best to have a whitelist of methods and constructs (i.e. you parse the code that is meant to be evaluated and ensure that every construct is allowed). I analyze JS malware in my free time (see [box-js](https://github.com/CapacitorSet/box-js)), and I found that it is virtually impossible to blacklist functions. For instance, if the parser forbids `[].map.constructor`, I could very well use `[].map["constructor"]`; and if you blacklist the word "constructor", I could use `[].map["rotcurtsnoc".split("").reverse().join("")]`, and so on, there's an infinity of methods one can come up with to avoid blacklists.

The examples didn't really work in math.js, but it turns out that there's still [quite a few ways to get around it](https://github.com/josdejong/mathjs/issues/821).

Re: How we exploited a code execution vulnerability in math.js

#18
post #14

> Gist [here]( https://gist.github.com/CapacitorSet/c41ab55a54437dcbcb4e627... An unmatched left parenthesis creates an unresolved tension that will stay with you all day.

Whoops, thank you - it went unnoticed because I didn't proofread the noscript version as much as the default one. I pushed an edit.

Re: How we exploited a code execution vulnerability in math.js

#19
post #13

Blacklists are a losing game. Always use a whitelist.

This was actually the second fix I had in mind, after the author mentioned that they would like mathjs to have complete browser support (and therefore couldn't use the `vm` module from Node.js): >If, anyway, you want to make math.eval resistant against arbitrary code execution, I think it would be best to have a whitelist of methods and constructs (i.e. you parse the code that is meant to be evaluated and ensure that…

I'm not really an expert on JS, but I'm guessing that the constructor function is the same function object, although it can be accessed in different ways. Wouldn't it be possible to blacklist the function object itself, instead of the access path?

Re: How we exploited a code execution vulnerability in math.js

#20
post #19

Earlier quoted context omitted.

This was actually the second fix I had in mind, after the author mentioned that they would like mathjs to have complete browser support (and therefore couldn't use the `vm` module from Node.js): >If, anyway, you want to make math.eval resistant against arbitrary code execution, I think it would be best to have a whitelist of methods and constructs (i.e. you parse the code that is meant to be evaluated and ensure that…

I'm not really an expert on JS, but I'm guessing that the constructor function is the same function object, although it can be accessed in different ways. Wouldn't it be possible to blacklist the function object itself, instead of the access path?

This is what the author attempted to do: if you read the first commit linked in the article, they made it so that math.js wouldn't execute Function when it encountered it (either an actual Function or a variable that equals Function).

However, the trick is to make Javascript execute Function, through a function that math.js won't mind executing. What I found was simply using Function.apply and Function.call; the author found Function.bind, and someone in this thread found several more.

Post reply on HN