tl;dr
- Reversing Hogan.js
- RCE - using Hogan-js
Introduction
In this Blog i will be explaining how i gained RCE using Twitter Hogan.js when Prototype Pollution exists.
Few days back Michał Bentkowski released a server side prototype pollution challengewhere RCE is required to get flag all we have is Prototype Pollution , which reminds me of AST-Injection
I started looking through the challenge and suddenly my eyes caught on Hogan.js which is used to compile the Mustache Templating language so I started looking into its source code.Even After checking them multiple times I couldn’t find any chains that helps to gain RCE as per the challenge.But yeah I found a few lines that could be useful to gain RCE apart from challenge.
In this blog I will be explaining how I was able to chain Prototype pollution to RCE via Hogan Js.
For those who need more information check this amazing Findings by POSIX
Reversing Hogan.js
In short, Hogan.codegen in compiler.js
is responsible for code generation depending on the cases and later , this generated code gets executed.
While going through each function and the way each builds the code by appending objects to Strings.Most of the objects where pre defined so Prototype Pollution is ineffective in such situations.
1 | Hogan.codegen = { |
But the function createPartial
looks unsafe.When it comes to context.prefix
and node.indent
value is added if value exists else it keeps it as empty.
1 | function createPartial(node, context) { |
Yay!!! So Prototype Pollution can Pollute them but how is this function called by Hogan.codegen
?
In Hogan.js there is something called tokens
which is used to generate codes. Token can be extracted by following way.
code
1 |
|
Output
1 | tokens [ |
In tokens tags are used to call corresponding functions checking Hogan.codegen
in this case tag : ‘>’ calls createPartial
.
Code Execution
Now we have Prototype Pollution that Successfully pollutes the generated codes but creating a working Exploit was a bit challenging.When I debugged generated code I came to the conclusion that directly adding “ to break the generated code returns bad syntax and ends executing.So my idea was to use console.log
1 | console.log(\"));console.log(process.mainModule.require('child_process').execSync('id').toString())//\") |
When console.log("some string")
is used this ends as a function so no more bad syntax when Double quotes are used.
This is how the generated code looks like when it gets polluted with above exploit.
1 |
|
POC
Code
1 | var hogan = require("hogan.js"); |
1 | ┌──(sbk㉿kali)-[/media/sbk/1n73rc3p70r_B10g] |