]> git.somenet.org - pub/jan/ctf-seminar.git/blob - writeups/chgue/seccon19.md
Upload sandstorm.png
[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 # Option-Cmd-U (Successfully sovled by a teammate)
8 ## Overview
9 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.
10 The challenge is powered by `nginx` and `php-fpm`.
11
12 ## Approach
13 A look at the sourcecode (see below) immediately hinted at a potential problem.
14
15     if($parsed_url["scheme"] !== "http"){
16         // only http: should be allowed. 
17         echo 'URL should start with http!';
18     } else if (gethostbyname(idn_to_ascii($parsed_url["host"])) === gethostbyname("nginx")) {
19         // local access to nginx from php-fpm should be blocked.
20         echo 'Oops, are you a robot or an attacker?';
21     } else {
22         // file_get_contents needs idn_to_ascii(): https://stackoverflow.com/questions/40663425/
23         highlight_string(file_get_contents(idn_to_ascii($url),
24                                            false,
25                                            stream_context_create(array(
26                                                'http' => array(
27                                                    'follow_location' => false,
28                                                    'timeout' => 2
29                                                )
30                                            ))));
31     }
32
33 Firstly, `Oops, are you a robot or an attacker?` is a strong indication that one should bypass this if check.
34 Secondly, `idn_to_ascii()` is used differently than in the provided stackoverflow link.
35
36 On a second look it became apparent that `idn_to_ascii` is used twice, however different parts of the URL are converted.
37 This seemed to hint at a potential attack vector.
38
39 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`.
40 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 as Punycode).
41 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.
42 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.
43
44 After not finding any fitting UTF-8 characters I gave up and tried different challenges. However, @smashing later solved it by further using some obscure features of `file_get_contents`. 
45 A host starting with `@` works in `file_get_contents` and that there exists a UTF-8 character that is parsed to `@`. Thereby bypassing the check and but still being parsed correctly by `file_get_contents`.
46
47 # ZKPay (Unsuccessful)
48 ## Overview
49 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.
50 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.
51
52 ## Approache
53 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.
54 First, I used the software barcode reader `zbar` to read some QR codes that I generated from my account (see below).
55
56     username=blurp&amount=1&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
57     username=blurp&amount=2&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
58     username=blurp&amount=3&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
59     username=blurp&amount=4&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
60     username=blurp&amount=5&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
61     username=blurp&amount=10&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
62     username=blurp&amount=100&proof=MHhCzoo/gCGDFP6tUp12doDKTC/p3uiklZ6ykG/VyKQLMCAwYQI7Q0zjyGerFCUqDqPb35cPXWcyd+dGaNy99JcJYCowCjC1GCIDWa/iVQbE45IBHChrkS4MC68BLHGcApiKSJkiLlkMiqWV3ALjj5h3WCxb5pqr9JAJzqoco6uu4AUEpvsdMSAwQYzKUGN6UX147Gm9rPvqn9UDF15HOTx+eyw02xX54BUwCjBRAyqPlz/XW4JFdKQ/KD3vI3l8iaCxQEf7y6KT31VNLDEgMKj4Wx+JLFMwfY7EvLdhHyHjr8JP8zwG/dbx7ivhcFAUMQow3AuO8oJxO002ulEHZ1Oi9DPiWnDhmX+o5zC35Qn8eRExCjC6XHq+/PgTI42EilzICJ+PDmyWv3Tn0nkjg/jhhNaAETAK&hash=fbea46e3ff4db1cb46199fb5e64771240709870628739b46e534f66abf730fb2
63
64 `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.
65 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. 
66 However, as there was no sourcecode and crypto challenges are often times pretty hard without the right knowledge I gave up. 
67
68 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)`...
69
70 # SECCON_multiplicater (Unsuccessful)
71 ## Overview
72 It's a webinterface that multiplies two numbers. The multiplication is powered by bash.
73
74 ## Approach
75 Part of the challenge below
76
77     typeset -i var1
78     typeset -i var2
79     
80     POST_STRING=$(cat)
81     
82     var1="$(echo $POST_STRING|awk -F'&' '{print $1}'|awk -F'=' '{print $2}'| nkf -w --url-input|tr -d a-zA-Z)"
83     var2="$(echo $POST_STRING|awk -F'&' '{print $2}'|awk -F'=' '{print $2}'| nkf -w --url-input|tr -d a-zA-Z)"
84     
85     echo  "$var1" '*' "$var2 = $((var1 * var2))"
86
87 Firstly, the program receives the variables in a string of the form `var1=10&var2=42`.
88 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`.
89
90 After reading the bash manpage it turns out that the variables are typeset to be integers and are subject to `arithmetic evaluation`. 
91 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. 
92 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.
93
94 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.
95
96 # Sandstorm (Unsuccessful)
97 ## Overview
98 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).
99
100 ## Approach
101 @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.
102
103     import cv2
104     import numpy as np
105     
106     def chunks(l, n):
107         n = max(1, n)
108         return (l[i:i+n] for i in range(0, len(l), n))
109     
110     img = cv2.imread("sandstorm.png", 0)
111     res = ""
112     counter = 0
113     for row in img:
114         for byte in chunks(list(map(lambda x: "1" if x == 255 else "0", row)), 8):
115             counter = counter + 1
116             res = res + (chr(int("".join(byte), 2)))
117     print(res.find("SECCON"))
118
119 However, it was only gibberish and no flag could be found.