If you're a returning visitor to our CTF Recaps, feel free to dive straight into the insights! For first-time explorers, let us quickly introduce you to the essence of these recaps. Wizer CTFs were introduced to challenge developers, encouraging them to adopt a hacker's mindset and thereby code more securely. This initiative is a pivotal part of our new security awareness training, specially crafted for development teams - Wizer's Secure Code Training for Developers!
After a challenge retires, our Wizer Wizard and CTO, Itzik Spitzen, crafts takeaways that offer valuable insights into the challenge, focusing on the defensive perspective for your script. Curious to test-drive a CTF before delving into the notes? Visit wizer-ctf.com – it's free, and there's something for all skill levels!
In this challenge, we identify an SSTI (Server-Side Template Injection) vulnerability which results in exposing a secret environment variable.
Our code is an invite card creator that allows users to generate cards to invite others. It does it by using the EJS (Embedded Javascript) template engine. A user can provide a first-name, last-name and role, which will then result in a lovely invite card for that person. The code is intended to strictly limit the use of the following arguments <%=firstName%>, <%=lastName%> and <%=role%>, which it does pretty well. The code then uses the `ejs.render()` method to generate the card which is sent back to the API caller as a string.
The main flaw of the code is that it's passing through extended options as the 3rd argument to the `ejs.render()`, and by that, allowing the settings to be fully controlled through user input. If we read the manual, we can see that one could provide certain options which change the behavior of the library.
By reading the manual of that intended functionality here:
We can quickly spot an interesting setting which could be altered in order to potentially inject malicious code to run within the context of the app.
Once the attacker realizes that it's possible to alter the delimiters, the code which is restricting the arguments to specific ones is no longer relevant, an attacker could change the delimiter and then provide a new argument, one or more, which will be interpreted in the context of the app.
For example providing the following delimiters:
"delimiter": ".",
"openDelimiter": "[",
"closeDelimiter": "]"
Then, providing a `[.<malicious code goes here>.]` argument, won't be restricted by the app code and will indeed run in the app. To achieve the goal of the game, a malicious code should read the `champ_key` and then, once known, the next API invocation could include the champ key and capture the flag.
Needless to point out that an SSTI is a remarkably capable attack, which allows an attacker to practically run malicious code within the context of a currently running app. Since it's a server side attack, an SSTI is a powerful entry point which could result in gaining unauthorized access to data from various sources (such as environment variables, database, other APIs which are accessible in that code etc.) and even executing shell commands remotely and potentially taking over the server.
Wanna join us on our next challenge? Sign up for our mailing list at wizer-ctf.com.