]> git.somenet.org - pub/jan/ctf-seminar.git/blob - writeups/chgue/seccon19.md
Add writeup for OTW day-02
[pub/jan/ctf-seminar.git] / writeups / chgue / seccon19.md
1 # Retrospective
2 I tried multiple challenges that day, mainly together with @smashing and @HaH__. Below are four challenges I attempted the longest most of which were rather frustrating, especially looking at the bash documentation/PHP sourcecode for quite a long time. 
3 Sadly, I didn't notice that the event ended early Sunday since I wanted to do a second take on the bash challenge but I was too late.
4
5 All in all it was interesting but in my opinion the CTF wasn't as fun as other CTFs in the past since it kinda seemed a bit reliant on guesswork (Sandstorm: Hinted (for me unknown) algorithm in the image, ZKPay: crypto but no source).
6
7 Time spent: ~10 hours total (I don't remember the breakdown exactly)
8
9 # Option-Cmd-U (Successfully sovled by a teammate)
10 ## Overview
11 The enables one to view the pagesource of an http webpage. The flag is located at `\flag.php`, however it is only accessible on the local network.
12 The challenge is powered by `nginx` and `php-fpm`.
13
14 ## Approach
15 A look at the sourcecode (see below) immediately hinted at a potential problem.
16
17     if($parsed_url["scheme"] !== "http"){
18         // only http: should be allowed. 
19         echo 'URL should start with http!';
20     } else if (gethostbyname(idn_to_ascii($parsed_url["host"])) === gethostbyname("nginx")) {
21         // local access to nginx from php-fpm should be blocked.
22         echo 'Oops, are you a robot or an attacker?';
23     } else {
24         // file_get_contents needs idn_to_ascii(): https://stackoverflow.com/questions/40663425/
25         highlight_string(file_get_contents(idn_to_ascii($url),
26                                            false,
27                                            stream_context_create(array(
28                                                'http' => array(
29                                                    'follow_location' => false,
30                                                    'timeout' => 2
31                                                )
32                                            ))));
33     }
34
35 Firstly, `Oops, are you a robot or an attacker?` is a strong indication that one should bypass this if check.
36 Secondly, `idn_to_ascii()` is used differently than in the provided stackoverflow link.
37
38 On a second look it became apparent that `idn_to_ascii` is used twice, however different parts of the URL are converted.
39 This seemed to hint at a potential attack vector.
40
41 Thus, I tried to trigger `Oops, are you a robot or an attacker?`. After lots of trial and error I found the rather obvious solution `http://nginx`.
42 Consequently, I tried various UTF-8 characters, such as `http://nginxä/flag.php` which bypassed the filter but resulted in errors as it was parsed as `xn--http://nginx/flag-1qb.php` (aka Punycode).
43 I had at look at the PHP sourcecode to find out if one could discard the `xn--` part by tricking the parser somehow but it didn't seem possible, especially since the `scheme` is checked at first.
44 Next, I tried `http://nginxß/flag.php` which was parsed as `http://nginxss/flag.php` so some unicode characters did not result in punycode starting with `xn--` but were converted to ASCII.
45
46 After not finding any fitting UTF-8 characters I gave up and tried different challenges. However, @smashing later solved it by using some obscure features of `file_get_contents`. 
47 A host starting with `@` is accepted by `file_get_contents` and there exists a UTF-8 character that is parsed to `@`. Thereby bypassing the check and but still being parsed correctly by `file_get_contents`.
48 The final payload was `http://ocu.chal.seccon.jp:10000/index.php?url=http%3A%2F%2F%EF%B9%ABnginx%2Fflag.php`.
49
50 # ZKPay (Unsuccessful)
51 ## Overview
52 It is basically some sort of banking app. One can create an account (which is heavily delayed to make the creation of many accounts difficult) and get 500 starting cash by the admin.
53 To receive the flag one has to accrue 1000000 cash. Transactions are handled by generating QR codes in order to send money and scanning (i.e. uploading them) in order to receive money.
54
55 ## Approache
56 As it was listed as a crypto challenge and its name starts with `ZK` I assumed that it somehow is connected to zero-knowledge proofs.
57 First, I used the software barcode reader `zbar` to read some QR codes that I generated from my account (see below).
58
59     username=blurp&amount=1&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
60     username=blurp&amount=2&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
61     username=blurp&amount=3&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
62     username=blurp&amount=4&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
63     username=blurp&amount=5&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
64     username=blurp&amount=10&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
65     username=blurp&amount=100&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
66
67 `username` is the username, `hash` is the address of the user, `amount` is the amount transferred and `proof` is presumably a zero knowledge proof. However, as one can notice the proof is always the same.
68 One can get the `hash` of the admin by clicking on the name of the admin in the transaction overview. Therefore, I thought one should generate a proof for the admin to transfer the money. 
69 However, as there was no sourcecode and crypto challenges are often times pretty hard without the right knowledge I gave up. 
70
71 Later it turned out that they (probably) had an error in their challenge and one could just send a negative value from ones account to another and therby increase the balance of the first account `(balance - (-100000000)`..
72
73 # SECCON_multiplicater (Unsuccessful)
74 ## Overview
75 It's a webinterface that multiplies two numbers. The multiplication is powered by bash.
76
77 ## Approach
78 Part of the challenge below
79
80     typeset -i var1
81     typeset -i var2
82     
83     POST_STRING=$(cat)
84     
85     var1="$(echo $POST_STRING|awk -F'&' '{print $1}'|awk -F'=' '{print $2}'| nkf -w --url-input|tr -d a-zA-Z)"
86     var2="$(echo $POST_STRING|awk -F'&' '{print $2}'|awk -F'=' '{print $2}'| nkf -w --url-input|tr -d a-zA-Z)"
87     
88     echo  "$var1" '*' "$var2 = $((var1 * var2))"
89
90 Firstly, the program receives the variables in a string of the form `var1=10&var2=42`.
91 It filters the first (and afterwards the second) variable  using `awk`, decodes characters such as `%20` to ASCII by using `nkf` and then removes all letters using `tr`.
92
93 After reading the bash manpage it turns out that the variables are typeset to be integers and are subject to `arithmetic evaluation`. 
94 I further studied the manpage to find out if I could somehow use arithmetic expansion to parse conditional expressions and expand shell commands to conduct something similar to a blind SQL injection. 
95 However, I didn't manage to get around the letter filter and it seemed like arithmetic evaluation does not expand and execute shell commands (to for example read filecontents) on my local test setup.
96
97 After spending way too much time with the bash manpage I decided I was making no progress and quit hoping to try it on the next day but when I returned the CTF was already over.
98
99 # Sandstorm (Unsuccessful)
100 ## Overview
101 It's a steganography challenge. The image is mainly black and white noise with some text inside. I assumed that the text was a hint but I sadly didn't get it (it later turned out to be vital in order to solve the challenge).
102
103 ## Approach
104 @HaH__ mentioned that one could try to parse the image as a binary string (white = 0, black = 1). I tried that and implemented it in python parsing from top left to bottom right.
105
106     import cv2
107     import numpy as np
108     
109     def chunks(l, n):
110         n = max(1, n)
111         return (l[i:i+n] for i in range(0, len(l), n))
112     
113     img = cv2.imread("sandstorm.png", 0)
114     res = ""
115     counter = 0
116     for row in img:
117         for byte in chunks(list(map(lambda x: "1" if x == 255 else "0", row)), 8):
118             counter = counter + 1
119             res = res + (chr(int("".join(byte), 2)))
120     print(res.find("SECCON"))
121
122 However, it was only gibberish and no flag could be found.