Introduction
TLDR
In 2024, the Holiday Hack Challenge is about the elves fighting each other.
It was a lot of fun again and I hope I can help people with this walkthrough in case they get stuck somewhere.
First login and intro
Sign in with Email/Password, Google or X:
Click “Play Now!”:
Prologue
Goto Jingle Ringford to get the Snowball Badge:
After we have the snowball badge you can start your first terminal challenge:
First Terminal
So from the conversation you now should search for Poinsettia McKittens and Angel Candysalt. Both can be found nearby.
Elf Connect
Talk to Angel Candysalt:
So let’s play connections :)
Angel Candysalt gives some more information to manipulate the score itself in the code. If you look into the code in the browser you see:
The score is set based on sessionStorage score. After the first round I tried to change it from 400 to 400000. But editing it directly in session storage does not work:
So the next idea was to set a breakpoint at a line where the score is updated. There is a line where a new line connections is awarded with 100 points. So let’s set a breakpoint here:
The next time you have a correct line of connections the breakpoint will be triggered and you can set up an arbitrary value:
If you now disable all breakpoints and let the program continue you will get the gold level of this challenge:
Now let’s search for Poinsettia McMittens:
Elf Minder 9000
The following where the solutions I found in the usual way to play Elf Minder 9000:
After that I tried to find the gold level:
If you look into the code you see that there is an edit mode:
Data seems to be stored as json:
There is also a strange variable named whyCantIHoldAllTheseThings
:
And Websockets seems to be used:
There is a function disappointHackers
:
Looking above the comments mentioning edit there is an interesting variable isEditor
:
Double Excalamation marks mean convert to boolean true if not empty
https://hhc24-elfminder.holidayhackchallenge.com/index.html?id=171bcaee-cb15-43de-852d-c987458aacc9&level=A%20Real%20Pickle&edit=true goes in the edit mode
This could lead to something like:
But you cannot end this level.
The game is based on json:
But I haven’t found out how I can use this to solve the gold challenge.
Act I
In your snowball click to go to Act I:
cURLing
On of the first places you find is:
Bow Ninecandle introduces you to the task:
Possible solutions are:
y
curl curlingfun:8080 ->
"""
You have successfully accessed the site on port 8080!
If you need help, please remember to run "hint" for a hint!
"""
curl -k https://curlingfun:9090
curl -X POST -d "skip=alabaster" -k https://curlingfun:9090
curl --cookie "end=3" -k https://curlingfun:9090
curl -I -k https://curlingfun:9090
curl -H "Stone:Granite" -k https://curlingfun:9090
curl -k --path-as-is 'https://curlingfun:9090/../../etc/hacks'
Look into the folder:
ls
There is a file explaining hard mode:
cat HARD-MODE.txt
To solve these constraints run:
curl -H "Hack:12ft" --cookie "end=10" -X POST -d "skip=bow" -k https://curlingfun:9090
Ok then access this URL:
curl -H "Hack:12ft" --cookie "end=10" -X POST -d "skip=bow" -k --path-as-is 'https://curlingfun:9090/../../etc/button'
Finally follow the redirection with -L
:
curl -L -H "Hack:12ft" --cookie "end=10" -X POST -d "skip=bow" -k --path-as-is 'https://curlingfun:9090/GoodSportsmanship'
"""
Excellent work, you have solved hard mode! You may close this terminal once HHC grants your achievement.
"""
After the challenge is solved perhaps Bow Ninecandle tells you a little bit additional:
The next I visited was Alabaster Snowball left to the curling area:
At the left of this area is Tinsel Upatree:
So this probably gives the hint to look into the crates.
A little bit lower at the left side is Noel Boetie:
There is a monitoring station in the middle:
Frosty Keypad
Right at the top you can find Morcel Nougat and a keypad challenge:
The book can be found here:
And there is a UV flashlight:
The book contains the following text:
To proceed you can read about the Ottendorf Cipher: https://nationaltreasure.fandom.com/wiki/Ottendorf_Cipher
There is a hint at the postit at left upper side:
So from the Ottendorf cipher this is the combination “Page:Word:Character in Word” which results in
SANTA
With the UV flash light you can identify the numbers used. This can narrow the set to find the combination of numbers.
The numbers are 2,6,7 and 8.
What could the word SANTA
be in numbers?
I found the solution at the mobile phone - T9:
Now let’s try to permutate 2,6, 7 and 8, brute force the key pad and find the gold solution. I took the HTTP request from the web site put it into python using the requests library. You have to toggle the speed a bit to get correct solution in the responses. I took 1 second:
import requests
import time
from itertools import product
def submit_answer(answer):
# Define the URL, headers, and data
# url = "https://hhc24-frostykeypad.holidayhackchallenge.com/submit?id=c5e47b3c-3816-4a83-81e2-d76d6be16286"
url = "https://hhc24-frostykeypad.holidayhackchallenge.com/submit?id=b973b6b2-ab9f-43a4-8554-7bad47c15195"
headers = {
"User-Agent": "<your User Agent>",
"Accept": "*/*",
"Accept-Language": "de,en-US;q=0.7,en;q=0.3",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Referer": "https://hhc24-frostykeypad.holidayhackchallenge.com/?&challenge=termFrostyKeypad&username=IeFeec2e&id=b973b6b2-ab9f-43a4-8554-7bad47c15195&area=frontyardact1&location=62,22&tokens=easy,termFrostyKeypad,hard&dna=ATATATTAATATATATATATTACGATATATATTATAGCATATATATATATATTAGCATATATATATATGCCGATATTATAATATATATATATGCGCATATATATATATATCGATATTACG",
#"Referer": "https://hhc24-frostykeypad.holidayhackchallenge.com/?&challenge=termFrostyKeypad&username=IeFeec2e&id=c5e47b3c-3816-4a83-81e2-d76d6be16286&area=frontyardact1&location=62,23&tokens=&dna=ATATATTAATATATATATATTACGATATATATTATAGCATATATATATATATTAGCATATATATATATGCCGATATTATAATATATATATATGCGCATATATATATATATCGATATTACG",
"Content-Type": "application/json",
"Origin": "https://hhc24-frostykeypad.holidayhackchallenge.com",
"Alt-Used": "hhc24-frostykeypad.holidayhackchallenge.com",
"Connection": "keep-alive",
"Cookie": "CreativeCookieName=eyJ1c2VyaWQiOiI1NzgxYjBkMi02YTdjLTRjNTEtYWZlZS0zMmVkZmUxODVmNmEifQ.Z1I3Qg.iRNJPtIXeYJt9XFndzErrrNeiOE",
#"Cookie": "CreativeCookieName=eyJ1c2VyaWQiOiIwODlmY2MwNS04ZmI2LTRmNDctODc0Ni01OThiYzVhOWEwNDAifQ.Zz594g._3M5KLOrZW-wLC6ilcHuGEoUM5k",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"DNT": "1",
"Sec-GPC": "1",
"Priority": "u=0",
"TE": "trailers",
}
data = {"answer": answer} # Replace with your actual answer
# Send the POST request
response = requests.post(url, headers=headers, json=data)
time.sleep(1)
# Print the response status code
print(answer+ " "+ str(response.status_code))
# If successful (status code 200), you can print the response content
# if response.status_code == 200:
# print(response.text)
if __name__ == "__main__":
# Loop through potential answers (replace 100000 with the desired upper limit)
for combo in product('2678', repeat=5):
#for combo in product('8039', repeat=5):
#for combo in product('9140', repeat=5):
submit_answer(''.join(combo))
This yields in a lot of 400 HTTP Status Codes:
400
{"error":"The data you've provided seems to have gone on a whimsical adventure, losing all sense of order and coherence!"}
and finally to:
If you grep in the output:
you have the gold solution! :)
So the first answer is from the word
SANTA
at the Keypad:
72682
and by using brute force:
22786
Shredded Pieces
If you talk to Morcel Nougat again
you get shredded pieces
The whole text from Morcel:
and you have a new item in your pocket:
Morcel Nougat has a hint for you:
as well as Jewel Loggins:
So let’s use the mentioned github gist https://gist.github.com/arnydo/5dc85343eca9b8eb98a0f157b9d4d719:
mkdir shredded_pieces
cd shredded_pieces
mv ~/Downloads/shreds.zip .
curl -LO https://gist.githubusercontent.com/arnydo/5dc85343eca9b8eb98a0f157b9d4d719/raw/78aa80e7fcead23fdd7f890b466a5f00ad956b7d/heuristic_edge_detection.py
unzip shreds.zip
sudo apt install python3-numpy
After that you can use python3 heuristic_edge_detection.py
and as a result get assembled_image.png
:
From the picture you can extract:
BAUD: 112500
PARITY: EVEN
DATA: 7 BITS
STOP BITS: 1 BIT
FLOW CONTROL: RTS
Hardware Hacking
At the right side there is a hardware hacking challenge with Jewel Loggins:
There is also Wombley Cube a little bit more above:
Hardware Part 1
Let’s tackle the hardware challenge:
With the information from shredded pieces you can piece together the shreds and the configuration (cf shredded pieces)
BAUD: 115200
PARITY: EVEN
DATA: 7 BITS
STOP BITS: 1 BIT
FLOW CONTROL: RTS
I used the AI which responded to the colors with:
**Frequently used color assignments:**
- Red:** Often used for the positive supply voltage (VCC).
- Black:** Usually used for ground (GND).
- Green:** Often used for the TX (Transmit) pin.
- Blue:** Often used for the RX (Receive) pin.
- White:** Can be used for various signals, but is less common than the other colors.
and therefore set TX to RX and RX to TX with the corresponding colors.
With the aforementioned settings it burned the chip:
So change 5V to 3V. After that it works:
Now Jewel Loggins tells you a little bit more
Hardware Part 2
Let us now turn to the left-hand side “Hardware Part 2”
If you check the folder and look into the bash history you can find the following
slh --passcode CandyCaneCrunch77 --set-access 1 --id 42
Lets use that to grant access to card number 42
Jewel Loggins now gives you a hint for gold
So let’s relogin to the shell. If you look into the folder you can find a file access_cards
which is an sqlite database
It has two tables access_cards
and config
. What is inside the access_cards
table
select * from access_cards
Card ID 42 has the following data
sqlite> select * from access_cards where id=42;
42|c06018b6-5e80-4395-ab71-ae5124560189|0|ecb9de15a057305e5887502d46d434c9394f5ed7ef1a51d2930ad786b02f6ffd
Let’s take a short glimpse into the config
table
sqlite> select * from config;
1|hmac_secret|9ed1515819dec61fd361d5fdabb57f41ecce1a5fe1fe263b98c0d6943b9b232e
2|hmac_message_format|{access}{uuid}
3|admin_password|3a40ae3f3fd57b2a4513cca783609589dbe51ce5e69739a33141c5717c20c9c1
4|app_version|1.0
The signature from card id 42 is most probably SHA2-256
The format for the hmac message format from the config
table says
{access}{uuid}
From this format and the hint from Jewel Loggins to CyberChef, let’s try to create the HMAC.
Open CyberChef and search in the left upper corner in the search box for “HMAC” and move it in the recipe panel. Then write in the input panel (according to
{access}{uuid} - uuid is the second row in the access_cards
table).
Set key format to UTF-8 and the key to the HMAC secret found from the config
table.
1c06018b6-5e80-4395-ab71-ae5124560189
The result is the missing signature which can be used to update the card number 42:
135a32d5026c5628b1753e6c67015c0f04e26051ef7391c2552de2816b1b7096
UPDATE access_cards
SET
id=42,
uuid='c06018b6-5e80-4395-ab71-ae5124560189',
access=1,
sig='135a32d5026c5628b1753e6c67015c0f04e26051ef7391c2552de2816b1b7096'
WHERE id = 42;
Jewel Loggins tells nothing new after that.
Alabaster Snowball:
Wombley Cube:
Frosty’s Beach
There is some stuff going on at Frosty’s Beach the context of which I have not yet understood:
Act II
If you enter Act II the following will happen
Alabaster Snowball gives you a bit information about what happened
Toilet Tunnel Network
Sparkle Redberry tells you about some hidden tunnel which you can probably use
You can those hidden tunnel in small toilets which you then can use as tunnel between Alabaster area, Wombley and a DMZ
Mobile Analysis
The first you can talk to Eve Snowshoes who opens a new task
Eve gives you two hints
This is the debug version
and this the release
If you open SantaSwipe.apk
with Genymotion you can see
Install jadx and start the gui
SantaSwipe.apk
with JADX-GUI reveals a database in the code
private static final String DATABASE_NAME = "naughtynicelist.db";
private static final int DATABASE_VERSION = 3;
/* JADX WARN: 'super' call moved to the top of the method (can break code semantics) */
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, (SQLiteDatabase.CursorFactory) null, 3);
Intrinsics.checkNotNullParameter(context, "context");
}
@Override // android.database.sqlite.SQLiteOpenHelper
public void onCreate(SQLiteDatabase db) {
Intrinsics.checkNotNullParameter(db, "db");
db.execSQL("CREATE TABLE IF NOT EXISTS NiceList (Item TEXT);");
db.execSQL("CREATE TABLE IF NOT EXISTS NaughtyList (Item TEXT);");
db.execSQL("CREATE TABLE IF NOT EXISTS NormalList (Item TEXT);");
db.execSQL("DELETE FROM NiceList;");
db.execSQL("DELETE FROM NaughtyList;");
db.execSQL("DELETE FROM NormalList;");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Carlos, Madrid, Spain');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Aiko, Tokyo, Japan');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Maria, Rio de Janeiro, Brazil');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Liam, Dublin, Ireland');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Emma, New York, USA');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Chen, Beijing, China');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Fatima, Casablanca, Morocco');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Hans, Berlin, Germany');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Olga, Moscow, Russia');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ravi, Mumbai, India');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Amelia, Sydney, Australia');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Juan, Buenos Aires, Argentina');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Sofia, Rome, Italy');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ahmed, Cairo, Egypt');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Yuna, Seoul, South Korea');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ellie, Alabama, USA');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Lucas, Paris, France');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Mia, Toronto, Canada');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Sara, Stockholm, Sweden');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ali, Tehran, Iran');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Nina, Lima, Peru');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Anna, Vienna, Austria');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Leo, Helsinki, Finland');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Elena, Athens, Greece');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Davi, Sao Paulo, Brazil');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Marta, Warsaw, Poland');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Noah, Zurich, Switzerland');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ibrahim, Ankara, Turkey');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Emily, Wellington, New Zealand');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Omar, Oslo, Norway');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Fatou, Dakar, Senegal');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Olivia, Vancouver, Canada');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ethan, Cape Town, South Africa');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Santiago, Bogota, Colombia');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Isabella, Barcelona, Spain');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ming, Shanghai, China');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Chloe, Singapore, Singapore');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Mohammed, Dubai, UAE');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Ava, Melbourne, Australia');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Luca, Milan, Italy');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Sakura, Kyoto, Japan');");
db.execSQL("INSERT INTO NormalList (Item) VALUES ('Edward, New Jersey, USA');");
}
If you search for NaughtyList
in the files
Let’s look into the DELETE FROM NaughtyList WHERE Item =
Statement in more detail. This seems to be
vulnerable to SQL Injection because the code uses string concatenation
There is also a SELECT
statement which filters a specific name in the same file
This is the answer for who has been left out from the list.
Solution:
Ellie
Talk to Eve Snowshoes again
He gives you two hints for the gold solution
First I started with some investigations using JADX-GUI in SantaSwipeSecure.aab
.
There you can find the naughtynicelist.db
and some interesting inital data
You can use Genymotion to get some visual experience how SantaSwipeSecure looks like
959 keytool -genkey -alias server -validity 365 -keyalg RSA -keystore keystore
962 java -jar bundletool-all-1.17.2.jar build-apks --bundle=<path_to_SantaSwipeSecure_aab>/SantaSwipeSecure.aab --output=<path_to_SantaSwipeSecure_aab>/output.apks --mode=universal --ks=<path_to_SantaSwipeSecure_aab>/keystore --ks-key-alias=server --ks-pass=pass:keystore
964 mv output.apks generate_apk/output.apks
965 cd generate_apk
967 cp output.apks output.zip
968 unzip output.zip -d <path_to_SantaSwipeSecure_aab>/generate_apk/
Back in SantaSwipe.apk
in the file DatabaseHelper
you can find this function
and
If you convert this to java code
cat Charsets.java
import java.nio.charset.Charset;
public final class Charsets {
public static final Charsets INSTANCE = new Charsets();
public static final Charset ISO_8859_1;
public static final Charset US_ASCII;
public static final Charset UTF_16;
public static final Charset UTF_16BE;
public static final Charset UTF_16LE;
public static final Charset UTF_8;
private static volatile Charset utf_32;
private static volatile Charset utf_32be;
private static volatile Charset utf_32le;
private Charsets() {
}
static {
Charset forName = Charset.forName("UTF-8");
UTF_8 = forName;
Charset forName2 = Charset.forName("UTF-16");
UTF_16 = forName2;
Charset forName3 = Charset.forName("UTF-16BE");
UTF_16BE = forName3;
Charset forName4 = Charset.forName("UTF-16LE");
UTF_16LE = forName4;
Charset forName5 = Charset.forName("US-ASCII");
US_ASCII = forName5;
Charset forName6 = Charset.forName("ISO-8859-1");
ISO_8859_1 = forName6;
}
public final Charset UTF32() {
Charset charset = utf_32;
if (charset != null) {
return charset;
}
Charset forName = Charset.forName("UTF-32");
utf_32 = forName;
return forName;
}
public final Charset UTF32_LE() {
Charset charset = utf_32le;
if (charset != null) {
return charset;
}
Charset forName = Charset.forName("UTF-32LE");
utf_32le = forName;
return forName;
}
public final Charset UTF32_BE() {
Charset charset = utf_32be;
if (charset != null) {
return charset;
}
Charset forName = Charset.forName("UTF-32BE");
utf_32be = forName;
return forName;
}
}
cat Decrypt.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class Decrypt {
private final byte[] iv;
private final SecretKeySpec secretKeySpec;
private final byte[] encryptionKey;
public Decrypt() {
String obj = "rmDJ1wJ7ZtKy3lkLs6X9bZ2Jvpt6jL6YWiDsXtgjkXw=";
byte[] decode = Base64.getDecoder().decode(obj);
this.encryptionKey = decode;
this.secretKeySpec = new SecretKeySpec(decode, "AES");
obj = "Q2hlY2tNYXRlcml4";
decode = Base64.getDecoder().decode(obj);
this.iv = decode;
}
private final String decryptData(String encryptedData) {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(2, this.secretKeySpec, new GCMParameterSpec(128, this.iv));
byte[] doFinal = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
if (doFinal == null) return "";
return new String(doFinal, Charsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
Decrypt d = new Decrypt();
System.out.println(d.decryptData("Base64todecrypt"));
}
}
Take the following as the input for the decryptData
function
and run this code
java Decrypt
the output is
Another interesting value to decrypt is
which yields to
Oh! This is something deleting from the list. Let’s inspect that:
The output KGfb0vd4u/4EWMN0bp035hRjjpMiL4NQurjgHIQHNaRaDnIYbKQ9JusGaa1aAkGEVV8=
decrypted is
So the solution then for gold would be
Joshua
Snowball Showdown
The next thing I tackled was the Snowball Showdown. This is where Dusty Giftwrap is located
So the task is
Run Snowball Showdown in Chrome or Safari - Firefox is really laggy
In the background web sockets are used
If you start the game in the url you can find a key value pair which controls if the game is single player
Set it to true to play alone
From the files copy phaser-snowball-game.js
to a local file
Set a breakpoint and disbalance team strength
data.alabasterElves.push(data.alabasterElves[0])
I tried to add elves to increase team of Alabaster
On the other side I tried to decrease the size of the team from Wombley
data.wombleyElves = data.wombleyElves.pop()
Then I played and try to get more points, finally resulting in bronze rating for the challenge
Drone Path
For the next challenge go through the tunnels in the DMZ to Chimney Scissorsticks
The task is the following
So let’s start!
I downloaded the file and viewed it with a KML viewer in the internet
So this looks like DROP1
? But this you cannot use anywhere. From the characters left this seems to be incomlete.
So I analyzed the file fritjolf-Path.kml
deeper using cat
.
Mm, there seems to be a link to google earth. So open the KML with Google Earth
If you import the KML file here you get this
And this is the needed password for login. The username you can get from the filename. The credentials:
fritjolf/GUMDROP1
There is the next challenge
Download CSV. Let’s inspect what’s inside.
For that I used libreoffice: libreoffice Preparations-drone-name.csv
and imported the csv there.
The longitude and latitude coordinates there yields to a route https://maps.app.goo.gl/uGa2YFD12wx4VDLF6
If you inspect those coordinate with google maps you can find some interesting thing. If you from map to satellite and look at the environment you can see:
This is definitely an E
:)
Here is an L
!
F
-
or I
H
A
W
K
So we have ELF-HAWK
or ELFIHAWK
If you search for this as a Drone you get
So you have a new CSV file.
I would say the keywords LONG and LATTER are a hint for Longitude and Latitude inside the file
For longitude values you can use
cut -f 5 ../ELF-HAWK-dump.csv -d "," | paste -s -d,
For the latitude values
cut -f 6 ../ELF-HAWK-dump.csv -d "," | paste -s -d,
Copy those values into a geopandas python script. geopandas needs a CRS. The most commonly used in the US seems to be EPSG: 4326:
WGS84 (EPSG: 4326) - Commonly used by organizations that provide GIS data for the entire globe or many countries. CRS used by Google Earth
Overview of Coordinate Reference Systems (CRS) in R
So you can set EPSG:4326 / WGS84 (https://en.wikipedia.org/wiki/World_Geodetic_System#WGS84) as CRS
cat dronepath.py
import pandas as pd
from shapely.geometry import LineString
import geopandas as gpd
import folium
# prepare data
data = {'Latitude': [<Latitude values comma separated],
'Longitude': [<Longitude Values comma separated>]}
df = pd.DataFrame(data)
# create lines
geometry = [LineString([(lon, lat) for lat, lon in zip(df['Latitude'], df['Longitude'])])]
gdf = gpd.GeoDataFrame(geometry=geometry)
# create map
m = folium.Map(location=[df['Latitude'].mean(), df['Longitude'].mean()], zoom_start=5)
gdf.crs = "epsg:4326"
folium.GeoJson(gdf).add_to(m)
m.save('flugroute.html')
So the final solution (for silver) is
DroneDataAnalystExpertMedal
Back to Chimney Scissorsticks
On the Wombley side there is Garland Candlesticks
and Wombley Cube
PowerShell
Piney Sappington introduces to a new challenge about PowerShell
The solutions are
y
dir
type welcome.txt
type welcome.txt | Measure-Object -word
netstat -an
Invoke-WebRequest http://127.0.0.1:1225
function BasicAuth($user, $pass, $url, $cookie_name, $cookie_value) {
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$headers = @{
Authorization = "Basic $encodedCreds"
}
if (-not $cookie_name)
{
$response = Invoke-WebRequest $url -Headers $headers
}
else
{
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$cookie = New-Object System.Net.Cookie
$cookie.Name = $cookie_name
$cookie.Value = $cookie_value
$cookie.Domain = "127.0.0.1"
$session.Cookies.Add($cookie);
$response = Invoke-WebRequest $url -Headers $headers -WebSession $session
}
$response
}
function BasicAuth($user, $pass, $url, $cookieHashTable) {
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$headers = @{
Authorization = "Basic $encodedCreds"
}
if (-not $cookieHashTable)
{
$response = Invoke-WebRequest $url -Headers $headers
}
else
{
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
foreach ($element in $cookieHashTable.getEnumerator()) {
$cookie = New-Object System.Net.Cookie
$cookie.Name = $element.Key
$cookie.Value = $element.Value
$cookie.Domain = "127.0.0.1"
$session.Cookies.Add($cookie);
}
$response = Invoke-WebRequest $url -Headers $headers -WebSession $session
}
$response
}
# Use it like BasicAuth admin admin http://127.0.0.1:1225 @{token ="xyz"; mfa_token ="abc"}
$response = BasicAuth "admin" "admin" "http://127.0.0.1:1225"
$response.Links
$links = $response.Links
foreach ($link in $links) {
$href = $link.href
$r = Invoke-WebRequest $href
$x = ($r.Content -split '\s+').Count
if ($x -eq 138) { Write-Host $href }
}
So there is one interesting endpoint http://localhost:1225/endpoints/13
. Let’s look into it
$r = Invoke-WebRequest "http://localhost:1225/endpoints/13"
$r.Content
There is a hint for a csv file what you can analyze
$r=Invoke-WebRequest http://127.0.0.1:1225/token_overview.csv
$r.Content
This seems to need more so let’s try to authenticate us with the Basic Auth credentials already used
$r = BasicAuth "admin" "admin" "http://127.0.0.1:1225/token_overview.csv"
$r.Content
Mm, from the response you can infer http://127.0.0.1:1225/tokens/<sha256sum>
.
Call this page and evaluate the response
$r=BasicAuth "admin" "admin" "http://127.0.0.1:1225/tokens/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C"
$r.Content
A cookie is missing. Our BasicAuth
function can handle this with the 3rd and 4th parameter
$r=BasicAuth "admin" "admin" "http://127.0.0.1:1225/tokens/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C" @{token="5f8dd236f862f4507835b0e418907ffc"}
$r.Content
The response
<h1>Cookie 'mfa_code', use it at <a href='1734742884.0846226'>/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C</a></h1>
is an MFA code which you can use at the mentioned endpoint url.
So those two approaches did not work, let’s try to put the code as cookie this way:
It’s seems that the site needs two cookies, the token cookie and the mfa cookie.
Our written Basic function works like this:
# Use it like BasicAuth admin admin http://127.0.0.1:1225 @{token ="xyz"; mfa_token ="abc"}
so you can do
$r=BasicAuth admin admin http://127.0.0.1:1225/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C @{token = "5f8dd236f862f4507835b0e418907ffc"; mfa_code = "1734822972.8962357"}
$r.Content
And from the response you can infer instead of mfa_code
(which was given you as hint before) , it seems that a cookie named mfa_token
is expected.
Let’s try that:
$r=BasicAuth admin admin http://127.0.0.1:1225/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C @{token = "5f8dd236f862f4507835b0e418907ffc"; mfa_token = "1734822972.8962357"}
$r.Content
Oh, this time took it too long, so probably you need to code something to make it faster. Let’s check that and do the last steps again:
Seems only the part for href
is changing if you compare it to the last time which is the value for mfa_token
. To extract you can do
$html = $r.Content
$match = $html | Select-String -Pattern "<a href='(.*?)'>"
$href = $match.Matches.Groups[1].Value
This uses
The complete snippet then is
$r=BasicAuth "admin" "admin" "http://127.0.0.1:1225/tokens/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C" @{token="5f8dd236f862f4507835b0e418907ffc"}
$html = $r.Content
$match = $html | Select-String -Pattern "<a href='(.*?)'>"
$href = $match.Matches.Groups[1].Value
$r=BasicAuth admin admin http://127.0.0.1:1225/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C @{token = "5f8dd236f862f4507835b0e418907ffc"; mfa_token = $href}
$r.Content
Response:
$r.Content
<h1>[+] Success</h1><br><p>Q29ycmVjdCBUb2tlbiBzdXBwbGllZCwgeW91IGFyZSBncmFudGVkIGFjY2VzcyB0byB0aGUgc25vdyBjYW5ub24gdGVybWluYWwuIEhlcmUgaXMgeW91ciBwZXJzb25hbCBwYXNzd29yZCBmb3IgYWNjZXNzOiBTbm93TGVvcGFyZDJSZWFkeUZvckFjdGlvbg==</p>
Looks like base64. To decode it you can implement
$encodedString = "Q29ycmVjdCBUb2tlbiBzdXBwbGllZCwgeW91IGFyZSBncmFudGVkIGFjY2VzcyB0byB0aGUgc25vdyBjYW5ub24gdGVybWluYWwuIEhlcmUgaXMgeW91ciBwZXJzb25hbCBwYXNzd29yZCBmb3IgYWNjZXNzOiBTbm93TGVvcGFyZDJSZWFkeUZvckFjdGlvbg=="
$decodedBytes = [System.Convert]::FromBase64String($encodedString)
$decodedString = [System.Text.Encoding]::UTF8.GetString($decodedBytes)
Write-Host "Decoded String: $decodedString"
which gives you the silver solution
The final secret is:
SnowLeopard2ReadyForAction
To get gold, there seems currently to be no clue inside the terminal. So let’s close the terminal and talk to Piney Sappington again who gives you some hints
North Pole Monitor Station
There is also a monitor station again in the middle in the DMZ
The Great Elf Conflict
Near Pepper Minstix and Wunorse Openslae in the DMZ you can find the Great Elf Conflict challenge.
Pepper Minstix tells you
From Wunorse Openslae you get
This results in multiple tasks - from what there first are
To start the challenge create for Microsoft KC7 and account or login using Google or Microsoft. You are greated with the following text
There is a small introduction to the web interface what tells you where clusters, query results can be found, or queries be made
The intro text tells you the solution for the first question
let's do this
Question 2 pops up
Let’s perform the steps described
Employees
which gives you a list of all employees
Employees
| take 10
filters you the first 10 entries of this list
At available tables you can get an overview of all tables existing
So to end question 2
enter the mentioned text
when in doubt take 10
Question 3 asks to count the employees
The solution:
90
Now specific entries of the table are of interest
Enter
Shinny Upatree
In the next step operators are explained
To proceed enter the text described
operator
In question 6 two tables are connected the first time. Get the email address from
Angel Candysalt from the Employee
table and then put it into the query in the Email
table.
So the email address i
angel_candysalt@santaworkshopgeeseislands.org
Now let’s us it like in the text mentioned to retrieve the amount of recipients
Solution:
31
The next question is about how to get how many distinct recipients for a specific sender are in the logs.
The sender to be analyzed is twinkle_frostington@santaworkshopgeeseisland.org
.
This can be done with:
Solution
32
Ok, so Twinkle Frostington has written to 32 different recipients. In the next question the task this gets broadened to websites.
So the Employees table contains IPs (look before). Get the IP from Twinkle from it.
And search it as source IP in the outbound network events as Twinkle should be the source for the website calls. From the results lets check how many different urls Twinkle has visited
Solution:
4
This was it for level 1, you reached level 2 ! :) The first question here is how many domains visited contain the word “green”
The solution is
10
Now we have to handle two queries where the first is used as a variable in the second
We got the solution:
8
This is also the solution for silver Microsoft KC7 “KQL 101”:
To start level 2
just enter
surrender
This level is about attacks against Team Wombley. The next question is more lengthy
So now there is no help anymore. You have to get the answer from what we learned already. First let’s check what information you can get from the Email table:
There is a column verdict which labels an email from the spam filter as phishing or not The keyword mentioned in the task to search for in the emails is “surrender”
Solution:
surrender@northpolemail.com
To find the amount of elves from Team Wombley who received the email do
Solution:
22
Mm, so how to find the filename? There is a column called link
in the Email table which could fit:
So from all those links you can infer the solution:
Team_Wombley_Surrender.doc
Let’s use this snippet to find the patient zero, the first computer infected in Team Wombley
Solution:
Joyelle Tinseltoe
There are two variables to be found timestamp and hostname. The timestamp can be used from the last query response:
The ProcessEvents
table contains a column hostname
.
Let’s search for the hostname from Joyelle Tinseltoe in this table.
The corresponding query gives us the solution
So this gives us
keylogger.exe
The next step is about getting the flag for the second challenge in the main Microsoft KC7 challenge
“Operation Surrender”. You have to encode the last solution keylogger.exe
Solution:
a2V5bG9nZ2VyLmV4ZQ==
Enter this solution for part two in the Microsoft KC7 challenge “Operation Surrender”:
The last question for level 2
Just enter
snowfall
This finished level 2. Time to start level 3!
In contrast to the last level, level 3 is now about attacks against Team Alabaster. It starts with the task to find the root of a password spraying against this team.
Let’s just use the snippet
So the source IP is:
59.171.58.12
In the next question you have to identify into how many accounts were logged into successfully from the attacker IP
If you check the AuthenticationEvents
table you can see that there is a column which
stores successful logins
Let’s check for the given IP 59.171.58.12
and list the hostnames connected to those successful logins
You now only have to count the hostnames together
19
Mm, this didn’t work for me. Ah, it’s not hostname it has to be username! Reason is because at each hostname you can perhaps have multiple users who can log in. Let’s try that
This worked! The solution is:
23
The next task is about identifying a service externally available which was misused.
First I thought perhaps this can be identified using InboundNetworkEvents
and the aforementioned
attacker source ip.
But to no avail. Next I focused on ProcessEvents
and search the parent processes I could find
Oh, this is not so much! I wanted to analyze the services, so I thought services.exe
or sc.exe
is probably correct. I used that to filter for the underlying processes started:
This also lead to a dead end.
Finally, I came back to the AuthenticationEvents
table from the task before and looked a deeper into it there.
If you inspect the column description
it carefully you can see that RDP
was used.
So this is the answer for the current question.
Ok, your task is to find this exfiltrated file! What is the username for Alabaster`s laptop:
In the description there is a hint that says that you can narrow down the events using the timestamp. I took the time around the results from the last solution
This yields to the solution:
Secret_Files.zip
So now the task is to find the file which encrypted the device. For this you can use the same query from the last question
Solution:
EncryptEverything.exe
In the next step you can catch the next flag and accomplish the third question “Operation Snowfall” for the Microsoft KC7 challenge.
Solution:
RW5jcnlwdEV2ZXJ5dGhpbmcuZXhl
The fourth part starts with a simple string to enter
Solution:
stay frosty
This part starts to look into Emails from Noel Boetie
Solution:
2024-12-12T14:48:55Z
You have to check when Noel clicked the link. For that you first need to identify the link and afterward can analyze the time linked to that.
The link in the email is:
https://holidaybargainhunt.io/published/files/files/echo.exe
The corresponding table to connect is OutboundNetworkEvents
Solution:
2024-12-12T15:13:55Z
Ok. To get the IP you can use the table PassiveDns
. Passive DNS are historical DNS logs which you can
use to analyze incidents.
Solution:
182.56.23.122
This time you use the IP from the attacker server before to check if it was also used
to log in into the victim system. This could be if it was just one Kali server for example.
Let’s use the AuthenticationEvents
table as mentioned.
Solution:
WebApp-ElvesWorkshop
is the hostname in which the IP has logged in.
So now we know the hostname which was probably initially compromised.
If you look in the ProcessEvents
table for it, you get 8 entries
Solution:
Invoke-Mimikatz.ps1
If you look deeper in the ProcessEvents you can extract that the executed file was echo.exe
.
And the first time this was executed is
Solution:
2024-12-12T15:14:38Z
Oh, this was it for level 3!
Let’s start level 4 :)
Mm, domain …
The table OutboundNetworkEvents
has a column url
which contains all the urls
the users tried to reach from outside.
So the solution is:
compromisedchristmastoys.com
Remember from questions 2-4 it was Noel Boetie who first clicked the phishing link.
So lets first inspect which processes ran at this user which had this file frosty.zip
used:
We can use the timestamp to look what happened in this time range
Solution:
sqlwriter.exe
The solution can be extracted from the same log entry as the last answer
Solution:
frosty
Hey let’s get the badge for the complete module :)
Solution:
ZnJvc3R5
This is also the final solution for the fourth part in the Microsoft KC7 challenge “Echoes in the Frost”:
After you enter the solution you will have gold in the Microsoft KC7 challenge:
Next I moved to Act III
Act III
Entering Act III a lot of new objectives get unlocked
And Santa appears and he seems to be very angry :)
Santa Vision
If you go a little bit you come to Ribb Bonbowford:
The goals are
Ribb also delivers you with some hints
So this is a repo about a tool to analyze the file system jffs called jefferson
The technology used in this task seems to be MQTT
If you open the application
There is a small crocodile in the lower right corner to click
The first link goes to
In this description the link GateXOR opens:
https://www.youtube.com/watch?v=6JXRHZsV9u0
The video there plays the american pronounciation of “gator”:
The second link “Time Travel” opens a console and starts a server:
If you scan this target you get
➜ santavision sudo nmap -A 34.135.21.17
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-22 03:21 CET
Nmap scan report for 17.21.135.34.bc.googleusercontent.com (34.135.21.17)
Host is up (0.13s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
| 256 a9:29:8e:6b:08:91:72:8a:cb:d1:e8:d4:f4:af:5f:c2 (ECDSA)
|_ 256 f0:f8:c0:5e:5c:c0:bb:81:99:34:0f:47:35:10:23:f7 (ED25519)
8000/tcp open http-alt gunicorn
|_http-title: Santa Vision
|_http-server-header: gunicorn
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 404 NOT FOUND
| Server: gunicorn
| Date: Sun, 22 Dec 2024 02:21:53 GMT
| Connection: close
| Content-Type: text/html; charset=utf-8
| Content-Length: 1820
| Vary: Cookie
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Santa Vision</title>
| <!-- meta -->
| <meta name="description" content="">
| <meta name="author" content="">
| <meta name="viewport" content="width=device-width,initial-scale=1">
| <!-- styles -->
| <!-- CSS only -->
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
| <link rel="stylesheet" href="/static/css/styles.css">
| </head>
| <body>
| <!-- Navigation -->
| <header class="p-3 mb-3 text-bg-dark">
| <div class="container">
| <div class="d-flex flex-
| GenericLines:
| HTTP/1.1 400 Bad Request
| Connection: close
| Content-Type: text/html
| Content-Length: 193
| <html>
| <head>
| <title>Bad Request</title>
| </head>
| <body>
| <h1><p>Bad Request</p></h1>
| Invalid Request Line 'Invalid HTTP request line: '''
| </body>
| </html>
| GetRequest:
| HTTP/1.0 200 OK
| Server: gunicorn
| Date: Sun, 22 Dec 2024 02:21:48 GMT
| Connection: close
| Content-Type: text/html; charset=utf-8
| Content-Length: 2946
| Vary: Cookie
| Set-Cookie: svCookie=-_GrbgUMaRrs_KzAshOPFe4OztUSHnx-Y38to7B2mbg; Expires=Wed, 22 Jan 2025 02:21:48 GMT; HttpOnly; Path=/
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Santa Vision</title>
| <!-- meta -->
| <meta name="description" content="">
| <meta name="author" content="">
| <meta name="viewport" content="width=device-width,initial-scale=1">
| <!-- styles -->
| <!-- CSS only -->
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
| <link rel="stylesheet" href="/static/css/styles.css">
| </head>
|_ <body>
9001/tcp open tor-orport?
| fingerprint-strings:
| JavaRMI, Radmin, SSLSessionReq, SSLv23SessionReq, TLSSessionReq, mongodb, tarantool:
| HTTP/1.0 403 Forbidden
| content-type: text/html
| content-length: 173
|_ <html><head><meta charset=utf-8 http-equiv="Content-Language" content="en"/><link rel="stylesheet" type="text/css" href="/error.css"/></head><body><h1>403</h1></body></html>
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port8000-TCP:V=7.94SVN%I=7%D=12/22%Time=676777BB%P=x86_64-pc-linux-gnu%
SF:r(GenericLines,11E,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x
SF:20close\r\nContent-Type:\x20text/html\r\nContent-Length:\x20193\r\n\r\n
SF:<html>\n\x20\x20<head>\n\x20\x20\x20\x20<title>Bad\x20Request</title>\n
SF:\x20\x20</head>\n\x20\x20<body>\n\x20\x20\x20\x20<h1><p>Bad\x20Request<
SF:/p></h1>\n\x20\x20\x20\x20Invalid\x20Request\x20Line\x20'Invalid\x
SF:20HTTP\x20request\x20line:\x20'''\n\x20\x20</body>\n</ht
SF:ml>\n")%r(GetRequest,CA6,"HTTP/1\.0\x20200\x20OK\r\nServer:\x20gunicorn
SF:\r\nDate:\x20Sun,\x2022\x20Dec\x202024\x2002:21:48\x20GMT\r\nConnection
SF::\x20close\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-L
SF:ength:\x202946\r\nVary:\x20Cookie\r\nSet-Cookie:\x20svCookie=-_GrbgUMaR
SF:rs_KzAshOPFe4OztUSHnx-Y38to7B2mbg;\x20Expires=Wed,\x2022\x20Jan\x202025
SF:\x2002:21:48\x20GMT;\x20HttpOnly;\x20Path=/\r\n\r\n<!DOCTYPE\x20html>\n
SF:<html\x20lang=\"en\">\n\x20\x20<head>\n\x20\x20\x20\x20<meta\x20charset
SF:=\"utf-8\">\n\x20\x20\x20\x20<title>Santa\x20Vision</title>\n\x20\x20\x
SF:20\x20<!--\x20meta\x20-->\n\x20\x20\x20\x20<meta\x20name=\"description\
SF:"\x20content=\"\">\n\x20\x20\x20\x20<meta\x20name=\"author\"\x20content
SF:=\"\">\n\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=d
SF:evice-width,initial-scale=1\">\n\x20\x20\x20\x20<!--\x20styles\x20-->\n
SF:\x20\x20\x20\x20<!--\x20CSS\x20only\x20-->\n\x20\x20\x20\x20<link\x20hr
SF:ef=\"https://cdn\.jsdelivr\.net/npm/bootstrap@5\.2\.0/dist/css/bootstra
SF:p\.min\.css\"\x20rel=\"stylesheet\"\x20integrity=\"sha384-gH2yIJqKdNHPE
SF:q0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx\"\x20crossorigin=\"
SF:anonymous\">\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20href=\"/st
SF:atic/css/styles\.css\">\n\x20\x20\x20\x20\n\x20\x20</head>\n\x20\x20<bo
SF:dy>\n\x20")%r(FourOhFourRequest,7CC,"HTTP/1\.0\x20404\x20NOT\x20FOUND\r
SF:\nServer:\x20gunicorn\r\nDate:\x20Sun,\x2022\x20Dec\x202024\x2002:21:53
SF:\x20GMT\r\nConnection:\x20close\r\nContent-Type:\x20text/html;\x20chars
SF:et=utf-8\r\nContent-Length:\x201820\r\nVary:\x20Cookie\r\n\r\n<!DOCTYPE
SF:\x20html>\n<html\x20lang=\"en\">\n\x20\x20<head>\n\x20\x20\x20\x20<meta
SF:\x20charset=\"utf-8\">\n\x20\x20\x20\x20<title>Santa\x20Vision</title>\
SF:n\x20\x20\x20\x20<!--\x20meta\x20-->\n\x20\x20\x20\x20<meta\x20name=\"d
SF:escription\"\x20content=\"\">\n\x20\x20\x20\x20<meta\x20name=\"author\"
SF:\x20content=\"\">\n\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20conten
SF:t=\"width=device-width,initial-scale=1\">\n\x20\x20\x20\x20<!--\x20styl
SF:es\x20-->\n\x20\x20\x20\x20<!--\x20CSS\x20only\x20-->\n\x20\x20\x20\x20
SF:<link\x20href=\"https://cdn\.jsdelivr\.net/npm/bootstrap@5\.2\.0/dist/c
SF:ss/bootstrap\.min\.css\"\x20rel=\"stylesheet\"\x20integrity=\"sha384-gH
SF:2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx\"\x20cro
SF:ssorigin=\"anonymous\">\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x2
SF:0href=\"/static/css/styles\.css\">\n\x20\x20\x20\x20\n\x20\x20</head>\n
SF:\x20\x20<body>\n\x20\x20\x20\x20<!--\x20Navigation\x20-->\n<header\x20c
SF:lass=\"p-3\x20mb-3\x20text-bg-dark\">\n\x20\x20<div\x20class=\"containe
SF:r\">\n\x20\x20\x20\x20<div\x20class=\"d-flex\x20flex-");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port9001-TCP:V=7.94SVN%I=7%D=12/22%Time=676777BC%P=x86_64-pc-linux-gnu%
SF:r(SSLSessionReq,F5,"HTTP/1\.0\x20403\x20Forbidden\r\ncontent-type:\x20t
SF:ext/html\r\ncontent-length:\x20173\r\n\r\n<html><head><meta\x20charset=
SF:utf-8\x20http-equiv=\"Content-Language\"\x20content=\"en\"/><link\x20re
SF:l=\"stylesheet\"\x20type=\"text/css\"\x20href=\"/error\.css\"/></head><
SF:body><h1>403</h1></body></html>")%r(TLSSessionReq,F5,"HTTP/1\.0\x20403\
SF:x20Forbidden\r\ncontent-type:\x20text/html\r\ncontent-length:\x20173\r\
SF:n\r\n<html><head><meta\x20charset=utf-8\x20http-equiv=\"Content-Languag
SF:e\"\x20content=\"en\"/><link\x20rel=\"stylesheet\"\x20type=\"text/css\"
SF:\x20href=\"/error\.css\"/></head><body><h1>403</h1></body></html>")%r(S
SF:SLv23SessionReq,F5,"HTTP/1\.0\x20403\x20Forbidden\r\ncontent-type:\x20t
SF:ext/html\r\ncontent-length:\x20173\r\n\r\n<html><head><meta\x20charset=
SF:utf-8\x20http-equiv=\"Content-Language\"\x20content=\"en\"/><link\x20re
SF:l=\"stylesheet\"\x20type=\"text/css\"\x20href=\"/error\.css\"/></head><
SF:body><h1>403</h1></body></html>")%r(JavaRMI,F5,"HTTP/1\.0\x20403\x20For
SF:bidden\r\ncontent-type:\x20text/html\r\ncontent-length:\x20173\r\n\r\n<
SF:html><head><meta\x20charset=utf-8\x20http-equiv=\"Content-Language\"\x2
SF:0content=\"en\"/><link\x20rel=\"stylesheet\"\x20type=\"text/css\"\x20hr
SF:ef=\"/error\.css\"/></head><body><h1>403</h1></body></html>")%r(Radmin,
SF:F5,"HTTP/1\.0\x20403\x20Forbidden\r\ncontent-type:\x20text/html\r\ncont
SF:ent-length:\x20173\r\n\r\n<html><head><meta\x20charset=utf-8\x20http-eq
SF:uiv=\"Content-Language\"\x20content=\"en\"/><link\x20rel=\"stylesheet\"
SF:\x20type=\"text/css\"\x20href=\"/error\.css\"/></head><body><h1>403</h1
SF:></body></html>")%r(mongodb,F5,"HTTP/1\.0\x20403\x20Forbidden\r\nconten
SF:t-type:\x20text/html\r\ncontent-length:\x20173\r\n\r\n<html><head><meta
SF:\x20charset=utf-8\x20http-equiv=\"Content-Language\"\x20content=\"en\"/
SF:><link\x20rel=\"stylesheet\"\x20type=\"text/css\"\x20href=\"/error\.css
SF:\"/></head><body><h1>403</h1></body></html>")%r(tarantool,F5,"HTTP/1\.0
SF:\x20403\x20Forbidden\r\ncontent-type:\x20text/html\r\ncontent-length:\x
SF:20173\r\n\r\n<html><head><meta\x20charset=utf-8\x20http-equiv=\"Content
SF:-Language\"\x20content=\"en\"/><link\x20rel=\"stylesheet\"\x20type=\"te
SF:xt/css\"\x20href=\"/error\.css\"/></head><body><h1>403</h1></body></htm
SF:l>");
Aggressive OS guesses: HP P2000 G3 NAS device (93%), Linux 2.6.32 (92%), Linux 2.6.32 - 3.1 (92%), Infomir MAG-250 set-top box (92%), Ubiquiti AirMax NanoStation WAP (Linux 2.6.32) (92%), Linux 3.7 (92%), Linux 5.0 (92%), Linux 5.0 - 5.4 (92%), Linux 5.1 (92%), Ubiquiti AirOS 5.5.9 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 7 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
...
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 152.56 seconds
Let’s check the http port 8000:
If you open the developer tools you can find the credentials in the comments:
So the solution for Santa Vision A is
elfanon
Let’s target Santa Vision B. If you login you see
The url is something like http://34.60.146.232:8000/auth?username=a&pwd=a&server=a&port=a.
If you intercept this with something like Burp Suite you get
If you add id parameter
So there the id parameter missing. In the url you can add something like &id=1
at the end of the url and you get:
If you click at the bottom right you see availables roles
- SiteDefaultPasswordRole
- SiteElfMonitorRole
- SiteAlabsterSAdminRole
- SiteWomblyCAdminRole
And if you click left you see available clients
- elfmonitor
- WomblyC
- AlabasterS
Another port opened is ssh, I tried just to login with the same user like in http, but a private key is needed:
Let’s recap what we have to focus for:
There is a button “Power On Monitors”
And a logout button
After a really long search, I found out that the credentials for the MQTT connection are located in the previously displayed clients and roles:
- *elfmonitor*
- WomblyC
- AlabasterS
- SiteDefaultPasswordRole
- *SiteElfMonitorRole*
- SiteAlabsterSAdminRole
- SiteWomblyCAdminRole
So the solution for Santa Vision B is:
elfmonitor
If you talk to Ribb Bonbowford after that:
This gives a new hint:
To power on the monitors let’s use the password found in the roles:
Connect As: elfmonitor
Password: SiteElfMonitorRole
Enter the IP from the Time Travel before in Camera Feed Server
. This is also the IP from the MQTT server.
For Camera Feed Port
look at the nmap output, it’s 9001
for the MQTT server.
You should now could read Monitors on. Connect to the broadcast feed
Let’s connect to northpolefeeds
as mentioned in the text to Santa Vision B:
The picture now shown are as follows:
So this seems to be advertising for the two combating parts. What’s written in the next challenge of Santa Vision?
Ok, then let’s do that!
For that proceed the same way as above, click to “Connect to broadcast feed” and
as value set frostbitfeed
as Broadcast feed:
This yields to output of frostbitfeed
whose messages look like this:
Frostbite is a serious condition that can cause permanent damage to the body and/or network
Frostbit is a leading cause of network downtime
Frostbite can be prevented by using a firewall and keeping your network secure
While good backups are important, they won't prevent frostbite
To prevent frostbite, you should wear appropriate clothing and cover exposed skin and ports
Be sure everyone knows the signs and symptoms of frostbite
Frostbite can occur in as little as 30 minutes in extreme cold - faster in flat networks
Additional messages available in santafeed
Error msg: Unauthorized access attempt. /api/v1/frostbitadmin/bot/<botuuid>/deactivate, authHeader: X-API-Key, status: Invalid Key, alert: Warning, recipient: Wombley
Do you conduct regular frostbite preparedness exercises?
Let's Encrypt cert for api.frostbit.app verified. at path /etc/nginx/certs/api.frostbit.app.key
This gives a hint to another feed in on of the messages: santafeed
.
Let’s look into that:
Gathered this is:
Santa is making his list.
Santa is checking his list.
Santa role: superadmin
WombleyC role: admin
AlabasterS role: admin
Sixteen elves launched operation: Idemcerybu
singleAdminMode=false
Santa role: superadmin
superAdminMode=true
Santa is on his way to the North Pole
If you look very carefully you can read Sixteen elves launched operation: Idemcerybu
.
So the secret operation asked in for Santa Vision C is
Idemcerybu
The next part of the challenge is:
Perhaps talk to Ribb Bonbowford again:
He says: “-send the right message, and Santa’s true spirit will return”. So we have to send something, which means in MQTT terms we have to publish something.