]> git.somenet.org - pub/jan/ctf-seminar.git/blob - writeups/theguy/seccon19.md
Example
[pub/jan/ctf-seminar.git] / writeups / theguy / seccon19.md
1 # SECCON 2019
2
3 ## Conclusion
4 Sadly I could only participate a few hours on saturday, but the challenges were fun to work on. I didn't really have time to dig into any challenge quite deep. But the writeups that were published afterwards are interesting and I learnt some new things from them like JSONP and some stuff about Shell Globbing.
5
6 ## Challenges I worked on
7
8 ### Option-Cmd-U
9
10 The intended purpose of the site is to show the source code of the websites you input. The URLs have to start with `http`.
11
12 First thing was of course a bit of information gathering.
13 The server runs PHP version 7.2.0 (X-Powered-By header field from the response).
14 The source code hinted towards the source code at `/index.php?action=source` and pointed out that the flag is located at `flag.php` and that the server is running *php-fm* and *nginx* and where the *docker-compose* file is located.
15
16 So I downloaded the source code and the *docker-compose.yml* file.
17
18 The source code shows that the `url` GET-parameter is filtered using the PHP function `filter_input` given no parameter. The documentation says that the default behaviour is to do nothing. So the function call is useless and can be ignored.
19
20 The url then gets parsed using `parse_url` which splits the url into its different parts. It returns an associative array with `scheme`, `host`, `path`, `port` and so on.
21
22 Then the `scheme` is checked to be `http`.
23
24 After that it is checked that the hostname of the url is not equal to `gethostbyname('nginx')`. If it wasn't then there was a call to `file_get_contents` and the url was read and displayed on the webpage.
25
26 The check for `nginx` was kinda strange and I thought it might be part of the challenge or just part of some strange edge case. Either way I first tried to see if just using the same domain as used by the challenge worked, but it just returned `Forbidden. Your IP: 172.25.0.1`. So I tried `http://172.25.0.1:10000/flag.php` but that yielded the same result.
27
28 So it seemed to really only worked if url was pointing to a local target.
29
30 So I tried: `http://127.0.0.1:10000/flag.php` but that just resulted in nothing.
31 So I set up the PHP code on my local system.
32
33 I tried `http://127.0.0.1:10000/flag.php` and noticed that the problem was the function `file_get_contents` timing out. To verify that I removed the `timeout` parameter and then it took it 30 seconds instead of 2 to abort.
34
35 I still don't know why, but I've read something about php file opening functions trying to see a given path/url are local files and then instead of opening them like usual do something weird. I guess that's the reason, but I'm not entirely sure.
36
37 Then I found a presentation of Orange Tsai called "A New Era of SSRF". It was about problems in URL parsers and filter bypassing.
38 One such idea was to use a DNS A record entry that points to 127.0.0.1 to bypass filters for `localhost` and `127.0.0.1`.
39
40 So I set up an DNS entry on my own domain (and @lavish gladly did the same on his domain). But that didn't work either.
41
42 After that I was kinda stuck and wandered off to another challenge.
43
44 ### Web Search
45
46 The website consisted of only one input field and a submit button.
47 The requests are sent to the path `/` using a GET request. The query is sent using the `q` parameter.
48 The site can be used to search for RFCs.
49
50 The first thing I've tried of course is a SQL injection.
51 Basics first: `' or 1=1--` -> Error and the query in the input field got modified.
52 The query was modified to `'1=1--`. So I immediately thought of sanitization and luckily for use they showed you the query after it got sanitized. You could bypass the filtering of `or` or any other potentially filtered keyword by just putting another `or` into the word, like `OorR`. 
53 The space filtering can be easily bypassed using `/**/` (thanks Introsec UE ;) ) (From this point on I will only write the queries without the sanitization bypassing to better show what the intention was).
54
55 The next thing I tried is bypassing the sanitization with `' or 1=1--` -> still Error, so I tried `' or 1=1#` instead. That worked!
56
57 When scrolling down you could see 
58 ```
59 FLAG
60     The flag is "SECCON{Yeah_Sqli_Success_" ... well, the rest of flag is in "flag" table. Try more!
61 ```
62 So the next thing I thought was to use Blind SQLi, so I tried to find out if the table actually existed using `' or exists(select * from flag limit 1)` -> Worked!
63 So the table actually exists and it is not just trying to throw you off.
64
65 Next thing is to check if the information schema tables are available and readable.
66 The query I used for that was `' or exists(select * from information_schema.table where table_name='flag')#` (here `information_schema` would also be written as `infoorrmation_schema`). Luckily `'`s where not filtered, else you could have used MySQL hex notation for strings. (Not that bad, but a bit more annoying).
67  
68 Next step I would have done is finding the column name (which is not needed in hindsight, but that's what I thought to do) using `' or (select substr(column_name from {place} for 1) from information_schema.columns where table_name='flag')='{guess}'#`.
69
70 After finding the column I would have extracted the value of the column using `' of (select substr({column_name} from {place} for 1) from flag)='{guess}'#`. But I didn't even get to this point, since I had to leave.
71
72 So I also don't have an exploit script. What it was essentially like the challenge from IntroSec UE course.
73
74 ### Fileserver
75 I also very briefly looked over this challenge.
76
77 I found the source code and I found the possibilty to do a bit of path traversal by just removing the `/public/index.html` part of the url. But since I'm not really at all comfortable in *Ruby* I didn't find anything useful.
78
79 I looked for *Ruby* or *webrick* CVEs and found some, but none that would help here.
80
81 I just noticed that you would have to either have a full path traversal bug or to pop a shell, since the flag is stored in a tmp file with a random name.