siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

static file server

Table of Contents

  1. Overview
  2. Background
  3. Enumeration
  4. Exploitation
  5. Conclusion

Overview

Background

Here’s a simple Python app that lets you view some files on the server.

Author: joseph

https://web-static-file-server-9af22c2b5640.2023.ductf.dev

Enumeration

Home page:

In here, we can view 2 static files: /files/ductf.png and /files/not_the_flag.txt:

In this challenge, we can download a file:

┌[siunam♥Mercury]-(~/ctf/DownUnderCTF-2023/web/static-file-server)-[2023.09.03|19:14:54(HKT)]
└> file static-file-server.zip 
static-file-server.zip: Zip archive data, at least v1.0 to extract, compression method=store
┌[siunam♥Mercury]-(~/ctf/DownUnderCTF-2023/web/static-file-server)-[2023.09.03|19:14:55(HKT)]
└> unzip static-file-server.zip 
Archive:  static-file-server.zip
   creating: static-file-server/
  inflating: static-file-server/app.py  
  inflating: static-file-server/Dockerfile  
   creating: static-file-server/files/
  inflating: static-file-server/files/not_the_flag.txt  
  inflating: static-file-server/files/ductf.png  

Dockerfile:

FROM python:3.10

WORKDIR /app
COPY app.py .
COPY flag.txt /flag.txt
COPY files/ files/

RUN pip3 install aiohttp

RUN /usr/sbin/useradd --no-create-home -u 1000 ctf
USER ctf

CMD ["python3", "app.py"]

This Docker builder script file will copy the flag.txt to /.

app.py:

from aiohttp import web

async def index(request):
    return web.Response(body='''
        <header><h1>static file server</h1></header>
        Here are some files:
        <ul>
            <li><img src="/files/ductf.png"></img></li>
            <li><a href="/files/not_the_flag.txt">not the flag</a></li>
        </ul>
    ''', content_type='text/html', status=200)

app = web.Application()
app.add_routes([
    web.get('/', index),

    # this is handled by https://github.com/aio-libs/aiohttp/blob/v3.8.5/aiohttp/web_urldispatcher.py#L654-L690
    web.static('/files', './files', follow_symlinks=True)
])
web.run_app(app)

In this web application, it’s using Python’s aiohttp asynchronous HTTP Client/Server.

In the /files static route, the follow_symlinks is set to True.

According to aiohttp documentation and the source code, it doesn’t prevent path traversal.

Exploitation

Armed with above information, we can use the /files route to perform path traversal, so that we can get the flag file:

Conclusion

What we’ve learned:

  1. Exploiting path traversal vulnerability