From b960949c36199aeaf2f2eac4d42cb0f54226f436 Mon Sep 17 00:00:00 2001
From: Matthias Prader <e1625755@student.tuwien.ac.at>
Date: Sat, 18 Jan 2020 08:49:39 +0000
Subject: [PATCH] Update asis19.md

---
 writeups/matthias/asis19.md | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/writeups/matthias/asis19.md b/writeups/matthias/asis19.md
index e90d76d..a9d074f 100644
--- a/writeups/matthias/asis19.md
+++ b/writeups/matthias/asis19.md
@@ -4,31 +4,34 @@ The Asis CTF was great fun. The two web challenges I looked at involved a little
 
 ## Web: Protected Area (solved)
 ---
-The link to the challenge leads to a website with a title `This site has a protected area`, the test `welcome` and a line of text (`I have to go GYM I should fix my site bugs`), that appear shortly after opening the site. A look into the pages HTML code showed, that jQuery is loaded and a custom is executed. The script consists of three methods: 
+The link to the challenge leads to a website with a title `This site has a protected area`, the text `welcome` and a line of text (`I have to go GYM I should fix my site bugs`), that appears shortly after opening the site. A look into the page's HTML code showed, that jQuery and a script get loaded. The script consists of three methods: 
 - `file_check(file)` makes an Ajax request to `/check_perm/readable/` with `file` added as the value of a parameter named file (`file_check(testfile)` would make the request `check_perm/readable?file=testfile`). If the response to that request is `True` the method `file_read(file)` is called. If not `fail` is printed to the console.
 - `file_read(file)` makes an Ajax request to `/read_file` and adds the same parameter. The result of that request is passed to the function `update_page(text)`
 - `update_page(text)` appends the `text` to an element in the HTML Document.
+
 The `$(document).ready()` function prints `ready` to the console and calls `file_check('public.txt')`
 
 We (the people on Mattermost) assumed that the backend could be in python because of `True` as a possible result of `check_perm/readable`. Also, we assumed, that we have to read the Flag somehow via `/read_file?file=xyz`.
 
 After a lot of trying and guessing we found out that:
-- `/read_file?file=xyz` returns `security` if it does not end with `.txit`. We interpreted it so, that the value of the parameter `file` must end tith `.txt`
+- `/read_file?file=xyz` returns `security` if the filename does not end with `.txt`. We interpreted it so, that the value of the parameter `file` must end with `.txt`
 - `/read_file?file=xyz` replaces `../` in the file value only once. So `/read_file?file=....//xyz` is possible
-- if the filename does not end tith `.txt` or contains multiple `.txt` the server responds with `security`. If the file ends with a single `.txt` but does not exist the server responds with `500`.
+- if the filename does not end tith `.txt` or contains multiple `.txt` the server responds with `security`. If the file ends with a single `.txt` but does not exist on the server the response is `500`.
 
 Someone then tried to add other parameters. It turned out that `/read_file/?file=private.txt&debug=true` resulted in `security` but `/read_file/?debug=true&file=private.txt` in `500`. So we tried to add a second parameter after `file` and end the value of that parameter with `.txt`:
-`/read_file/?file=xyz&test=ha.txt` worked! So our interpretation was wrong. Its only checked if the whole query string ends with `.txt` and nor the value of the `file` parameter.
+`/read_file/?file=xyz&test=ha.txt` worked! So our interpretation was wrong. It's only checked if the whole query string ends with `.txt` and nor the value of the `file` parameter.
+
+In the meantime we already could look at Protected Area 2, which pointed to a Github repo of a docker container that was apparently used for these challenges. So we knew that there was a folder `/app/` that contains a `main.py`.
 
-In the meantime we already could look at Protected Area 2, which pointed to a Github repo of a docker container that was apparently used for these challenges. So we knew that there was a folder `/app/` that contains a `main.py`
 `/read_file/?file=....//....//....///app/main.py&test=ha.txt` allowed us to read the content of the python file. 
-By looking at the python files that are imported in the main file we found the protected endpoint `/protected_area_0098` which sends the flag back (in the file `/app/application/api.py`). But a `check_login` method is executed before. In a file imported by the `api.py`, the file `/api/application/functions.py` was the `check_login` method. The method looks for a header named `ah` and checks if its value is equal than a MD5 hash of some values located in a configfile. We found the config.py at `/app/config.py` so we had the values, could craft the correct header. `curl -H "ah: cbd54a3499ba0f4b221218af1958e281" http://66.172.33.148:8008/protected_area_0098` resulted in `ASIS{f70a0203d638a0c90a490ad46a94e394}`
+By looking at the python files that are imported in the main file we found the protected endpoint `/protected_area_0098` which sends the flag back (in the file `/app/application/api.py`). But a `check_login` method is executed before. In a file imported by the `api.py`, the file `/api/application/functions.py` was the `check_login` method. The method looks for a header named `ah` and checks if its value is equal to a MD5 hash of some values located in a configfile. We found the config.py at `/app/config.py` so we had the values and could craft the correct header. `curl -H "ah: cbd54a3499ba0f4b221218af1958e281" http://66.172.33.148:8008/protected_area_0098` resulted in `ASIS{f70a0203d638a0c90a490ad46a94e394}`
 
-## Web: Protected Area 2 (not solved)
+##Web: Protected Area 2 (not solved)
 ---
-Protected Area 2 had exactly the same structure as Protected Area 2. The only defference in the pages sources was a hint to a file named `private.txt`. This file contained the link to the already mentioned Github repo.
-We could move between directories with `read_file` as in Protected Area 1. But this time the trick with adding another parameter to bypass the check if the file ends with `.txt` did not work.
-We found out, that this time the `check_perm` function was implemented differently. `http://66.172.33.148:5008/check_perm/wtf/?file=public.txt` showed the error message `'_io.TextIOWrapper' object has no attribute 'wtf'`.  So apparently we can decide which method to execute. By changing the `wtf` to `read` we were able to read files. 
+Protected Area 2 had exactly the same structure as Protected Area. The only difference in the page's sources was a hint to a file named `private.txt`. This file contained the link to the already mentioned Github repo.
+We could move between directories with `read_file` as in Protected Area. But this time the trick with adding another parameter to bypass the check if the file ends with `.txt` did not work.
+We found out, that this time the `check_perm` function was implemented differently. `http://66.172.33.148:5008/check_perm/wtf/?file=public.txt` showed the error message `'_io.TextIOWrapper' object has no attribute 'wtf'`.  So apparently we can decide which method in `io.TextIOWrapper`  should be executed. As `io.TextIOWrapper` inherits `io.TextIOBase`, which contains a `read` method, by changing the `wtf` to `read` we were able to read files. 
+
 We looked at the `nginx.conf` file 
 ```
 server { 
@@ -47,8 +50,8 @@ server {
     } 
 }
 ```
-which told us, that the base bolder for the app must be in `/opt/py/app`. In that folder we found a `config.py` which contained the path to the flag but unfortunately we couldn't read it with our method (no permission i think).
+which told us, that the base bolder for the app must be in `/opt/py/app`. In that folder we found a `config.py` which contained the path to the flag but unfortunately we couldn't read it with our method (no permission I think).
 
-As we saw that all requests are passed to `uwsgi` we searched for a config file for it but found only the two standard ones. And thats where we couldn't make any progress anymore. 
+As we saw that all requests are passed to `uwsgi` we searched for a config file for it but found only the two standard ones (= the ones that we found by downloading the docker container and searching for files named `uwsgi.ini`). And thats where we couldn't make any progress anymore. 
 
-After the CTF has ended, I looked at a Writeup and saw, that the `uwsgi.ini` we looked for was located in `opt/py/app`. I am sure that i've tried to look in that folder for this file. Probably i misspelled `uwsgi` that happened a lot during that ctf. I often wrote `uswgi`. Too bad.
\ No newline at end of file
+After the CTF has ended, I looked at a Writeup and saw, that the `uwsgi.ini` we looked for was located in `opt/py/app`. I am sure that i've tried to look in that folder for this file. Probably i misspelled `uwsgi`. That happened a lot during that ctf. I often wrote `uswgi`. Too bad.
\ No newline at end of file
-- 
2.43.0