TryHackMe — MD2PDF Walkthrough (Understanding the Vulnerability, Not Just the Flag)

While solving the MD2PDF room on TryHackMe, I initially thought this would be a simple Markdown injection challenge. However, as I spent more time exploring the application, I realized the real learning point was how server-side rendering can be abused to access internal resources.

Reconnaissance

As usual, I started with a basic port scan.

nmap -sC -sV <target-ip>

The scan revealed two interesting ports:

  • Port 80 — Web application
  • Port 5000 — Another service running internally

Visiting port 80 in the browser showed a web application that converts Markdown text into a PDF file.

At first glance, everything looked normal.

Screenshot of the MD2PDF web interface on TryHackMe with a Markdown input box used to generate PDFs.

Application Behavior

The application accepts Markdown input and generates a downloadable PDF. While testing basic Markdown features, I noticed something important:

👉 HTML tags were also being rendered, not just Markdown.

This immediately raised a red flag.

Finding the Restricted Admin Page

Next, I performed some directory enumeration and discovered an /admin endpoint on the service running on port 5000.

None

Trying to access it directly from the browser resulted in:

403 Forbidden
his page can only be seen internally (localhost:5000)

So:

  • External users ❌ cannot access /admin
  • Internal server ✔️ can access /admin

This distinction is crucial.

Understanding the Vulnerability

The application works like this:

User Input → Markdown → HTML → PDF (on the server)

Because the server renders the HTML while creating the PDF, any HTML that forces the server to load a URL will be executed from the server's perspective.

This is a classic example of Server-Side Request Forgery (SSRF).

Primary Exploitation Method (Iframe Injection)

I tested whether I could force the server to load the internal admin page during PDF generation.

I submitted the following payload into the Markdown input field:

<iframe src="http://localhost:5000/admin"></iframe>

What happened next?

  1. The application accepted the input
  2. The server processed the HTML
  3. While generating the PDF, the server loaded the internal /admin page
  4. The admin page content was embedded inside the PDF
  5. 🎉 The flag was visible inside the generated PDF
None

Alternative Ways to Exploit the Same Vulnerability

Although the iframe payload works perfectly, it is not the only way to exploit this challenge.

The real vulnerability is:

1️⃣ Image Tag Injection

<img src="http://localhost:5000/admin">

2️⃣ Object Tag Injection

<object data="http://localhost:5000/admin"></object>

3️⃣ Embed Tag Injection

<embed src="http://localhost:5000/admin">

4️⃣ Localhost Variations

Sometimes filters block localhost but allow:

http://127.0.0.1:5000/admin

Why This Works (Simple Explanation)

  • You are not accessing the admin page
  • You are making the server access it for you
  • The server trusts itself
  • The PDF renderer blindly includes whatever the server loads

This is SSRF via server-side HTML rendering.

Key Takeaways

  • Markdown to PDF converters can be dangerous if HTML is not sanitized
  • Internal services are often more trusted than external users
  • SSRF doesn't always need APIs or cloud metadata — simple HTML rendering is enough
  • Always test how input is processed on the server

Final Thoughts

This room is a great example of how small misconfigurations can lead to serious vulnerabilities. Instead of focusing only on payloads, understanding why the exploit works makes it easier to identify similar issues in real-world applications.

Highly recommended room for anyone learning web exploitation or threat hunting basics.