Objective

1545532045835

Terminal - Yule Log Analysis

Challenge

1546340089902I’ll find Pepper Minstix in the hallway headed to the back of the building, around the corner from the Speaker Unpreparedness Room:

Have you heard of password spraying?

It seems we’ve been victim.

We fear that they were successful in accessing one of our Elf Web Access accounts, but we don’t know which one.

Parsing through .evtx files can be tricky, but there’s a Python script that can help you convert it into XML for easier grep‘ing.

                                                                                
                             .;:cccckkxdc;.                                     
                         .o0xc;,,,,,XMMMMMkc:,.                                 
                       lXMMMX;,,,,,,XMMMMK,,coddcclOkxoc,.                      
                     lk:oNMMMX;,,,,,XMMWN00o:,,,,,:MMMMMMoc;'                   
                   .0l,,,,dNMMX;,,,,XNNWMMMk,,,,,,:MMMMMx,,,,:;.                
                  .K;,,,,,,,xWMX;,,;Kx:kWMMMk,,,,,:MMMM0,,,,,,,:k'              
                 .XklooooddolckWN:l0:,,,;kWMMO,,,,:MMMN;,,,,,cOWMMd             
               ;oooc;,,,cMMMMMMxkO0,,,,,,,:OMM0,,,:MMWc,,,,lKMMMMWKo            
            ;OMMWl,,,,,,cMMMMMO,,,:cc,,,,,,,:0M0,,:MMd,,,oXMMWKxc,,,c           
          cOdXMMMWl,,,,,cMMMMX,,,,,,,:xxo:,,,,cK0,:MO,;xNWKxc,,,,,,,:.          
        .0l,,,oNMMWl,,,,cMMMW:,,,,,,dXMWNMWXOdc;lxcX:xOxc,,,,,,,,,,,,:          
       ,0;,,,,,,dNMWo,,,cMMMl,,,,;xNMMMMW0kkkkkkddxdddxxxxxxxxxxxxxxxo          
      .Wl,,,,,,,,,dWMo,,cMMx,,,:OWMMW0xc,:c,,:dOkcK:kc:ok0NMMMMMMMMMMd          
      KMMWXOdl;,,,,;xWd,cM0,,l0MW0dc,,,,,,lkWWk:,OW,:XO:,,,;ldOXWMMMM'          
     'MMMMMMMMMN0ko:,;kdcN;o00dc,,,,,,,,,,,0x;,,oMW,,;XWk;,,,,,,,:okk           
     cNKKKKKKKKKKKKKKkoodxxdccccccccccccccco,,,:WMW,,,;XMWk;,,,,,,,l            
     :x,,,,,,,,,,,,,cdkoOldldOKWMMMMMMMMMMMx,,,XMMW,,,,;XMMWx,,,,;c             
     .K,,,,,,,,,cd0WKl,xN,oXo,,,:ok0NMMMMMMc,,OMMMW,,,,,;KMMMNd;l'              
      dl,,,,cx0WMM0c,,lMN,,oMXl,,,,,,;ldOX0',dMMMMW,,,,,,;KMMMK;                
       OoxKWMMMWk:,,,;NMN,,,lWMKc,,,,,,,,ldclWMMMMW,,,,,,:oOl.                  
        OMMMMNx;,,,,,KMMN,,,,lWMM0c,,,,,l. .,cdkO00ccc:;,.                      
         cWXo,,,,,,,kMMMN,,,,,cWMMM0:,c:                                        
          .Kc,,,,,,:MMMMN,,,,,,dMMMMWk'                                         
I am Pepper Minstix, and I'm looking for your help.
Bad guys have us tangled up in pepperminty kelp!
"Password spraying" is to blame for this our grinchly fate.
Should we blame our password policies which users hate?
Here you'll find a web log filled with failure and success.
One successful login there requires your redress.
Can you help us figure out which user was attacked?
Tell us who fell victim, and please handle this with tact...

  Submit the compromised webmail username to 
  runtoanswer to complete this challenge.

elf@96de907fd2fa:~$

Solution

Background on Password Spraying

Password spraying is a technique that has been adopted to attempt to gain account access in a brute force manner without triggering account lockouts that would be loud and potentially alert defenders to the attack. Instead of trying lots of passwords against a single account, password spraying involves selecting one (or a few) common passwords (such as “Winter2018”), and trying them against a lot of accounts. For more details, check out Beau Bullock’s KringleCon presentation Everything You Wanted to Know about Password Spraying.

Log Analysis

Given event logs, and a python script to dump them out as xml, I’ll first want to get a feel for what kinds of logs I have. I’ll do this with some bash piping. First, I’ll dump all the event XML, then grep just the lines with event id. The output will look like <EventID Qualifiers="">4826</EventID>. Then I’ll cut with a delimiter of > and then again with a delimiter of <, isolating the id. Then, I’ll use sort | uniq -c | sort -nr to sort the ids, then get a unique list of ids (-c to keep counts for each), and then sort again, with -nr for numeric sort, in reverse order (I’ve labeld the most command log number with their description):

elf@a6261e4e2207:~$ python evtx_dump.py ho-ho-no.evtx | grep EventID | cut -d'>' -f 2 | cu
t -d'<' -f1 | sort | uniq -c | sort -nr
    756 4624     <-- successful logon
    212 4625     <-- failed logon
    109 4769     <-- kerberos service ticket requested
    108 4776     <-- dc attempt to validate creds
     45 4768     <-- session reconnected to windows station
     34 4799     <-- security-enabled local group enumerated
     10 4688     <-- process created
      2 5059
      2 4904
      2 4738
      2 4724
      1 5033
      1 5024
      1 4902
      1 4826
      1 4647
      1 4608

I’ll check out one of the failed logons:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System><Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}"></Provider>
<EventID Qualifiers="">4625</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8010000000000000</Keywords>
<TimeCreated SystemTime="2018-09-10 13:03:34.660316"></TimeCreated>
<EventRecordID>239831</EventRecordID>
<Correlation ActivityID="{71a9b66f-4900-0001-a8b6-a9710049d401}" RelatedActivityID=""></Correlation>
<Execution ProcessID="664" ThreadID="852"></Execution>
<Channel>Security</Channel>
<Computer>WIN-KCON-EXCH16.EM.KRINGLECON.COM</Computer>
<Security UserID=""></Security>
</System>
<EventData><Data Name="SubjectUserSid">S-1-5-18</Data>
<Data Name="SubjectUserName">WIN-KCON-EXCH16$</Data>
<Data Name="SubjectDomainName">EM.KRINGLECON</Data>
<Data Name="SubjectLogonId">0x00000000000003e7</Data>
<Data Name="TargetUserSid">S-1-0-0</Data>
<Data Name="TargetUserName">adam.smith</Data>
<Data Name="TargetDomainName">EM.KRINGLECON</Data>
<Data Name="Status">0xc000006d</Data>
<Data Name="FailureReason">%%2313</Data>
<Data Name="SubStatus">0xc0000064</Data>
<Data Name="LogonType">8</Data>
<Data Name="LogonProcessName">Advapi  </Data>
<Data Name="AuthenticationPackageName">Negotiate</Data>
<Data Name="WorkstationName">WIN-KCON-EXCH16</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x00000000000019f0</Data>
<Data Name="ProcessName">C:\Windows\System32\inetsrv\w3wp.exe</Data>
<Data Name="IpAddress">172.31.254.101</Data>
<Data Name="IpPort">38341</Data>
</EventData>
</Event>

With an understanding of what one of these events looks like, I think it’s best to save off the two types of logs I’m most interested in to files so I don’t have to parse the entire log each time. I’ll use the -B and -A flags in grep to get the lines before and after the matched line. Based on the example above, I need 1 line before the event ID, and 36 lines after for both of these log types:

elf@a6261e4e2207:~$ python evtx_dump.py ho-ho-no.evtx | grep -B 1 -A 36 "4625</EventID>" > 4625s.xml  # unsuccessful
elf@aa90c1334668:~$ python evtx_dump.py ho-ho-no.evtx | grep -B 1 -A 36 "4624</EventID>" > 4624s.xml  # successful

Now, I’ll start with the failed logons, and check out their IpAddress, LogonType, and Username:

elf@aa90c1334668:~$ cat 4625s.xml | grep IpAddress | sort | uniq -c | sort -nr       
    211 <Data Name="IpAddress">172.31.254.101</Data>
      1 <Data Name="IpAddress">10.158.210.210</Data>

elf@aa90c1334668:~$ cat 4625s.xml | grep Type | sort | uniq -c | sort -nr
    212 <Data Name="LogonType">8</Data>

elf@aa90c1334668:~$ cat 4625s.xml | grep TargetUserName | sort | uniq -c | sort -nr | head
      2 <Data Name="TargetUserName">sparkle.redberry</Data>
      1 <Data Name="TargetUserName">wunorse.openslae</Data>
      1 <Data Name="TargetUserName">vinod.kumar</Data>
      1 <Data Name="TargetUserName">vijay.kumar</Data>
      1 <Data Name="TargetUserName">tyler.smith</Data>
      1 <Data Name="TargetUserName">tom.smith</Data>
      1 <Data Name="TargetUserName">tim.smith</Data>
      1 <Data Name="TargetUserName">test.user</Data>
      1 <Data Name="TargetUserName">suresh.kumar</Data>
      1 <Data Name="TargetUserName">sunil.kumar</Data>

elf@aa90c1334668:~$ cat 4625s.xml | grep TargetUserName | sort | uniq -c | sort -nr |wc -l
211  # 211 different lines means each event from a different user

So all but one of the failed logons come from the IP Address 172.31.254.101. All the failures are type 8, which is Network Cleartext, typically associated with logging into IIS with “Basic Auth”. Each failed attempt is for a different user, with two from sparkle.redberry.

Next I’ll look for events that look like that in the successful logons by grepping for that IP Address and grabbing the rest of any logs with -A and -B. Then from each full log, I’ll grep out the lines I’m interested in seeing for each log using the -e option, which allows for grep to match on any number of options given with -e:

elf@aa90c1334668:~$ cat 4624s.xml | grep -B 33 -A 4 172.31.254.101 | grep -e TargetUserName -e IpAddress -e LogonType -e TimeCreated
<TimeCreated SystemTime="2018-09-10 13:05:03.702278"></TimeCreated>
<Data Name="TargetUserName">minty.candycane</Data>
<Data Name="LogonType">8</Data>
<Data Name="IpAddress">172.31.254.101</Data>
<TimeCreated SystemTime="2018-09-10 13:07:02.556292"></TimeCreated>
<Data Name="TargetUserName">minty.candycane</Data>
<Data Name="LogonType">8</Data>
<Data Name="IpAddress">172.31.254.101</Data>

So it looks like there were two successful logons as minty.candycane from that suspect IP. That’s the answer I’m looking for!

elf@aa90c1334668:~$ ./runtoanswer 
Loading, please wait......
Whose account was successfully accessed by the attacker's password spray? minty.candycane
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMkl0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMXO0NMxl0MXOONMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMxlllooldollo0MMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMW0OKWMMNKkollldOKWMMNKOKMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMXollox0NMMMxlOMMMXOdllldWMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMWXOdlllokKxlk0xollox0NMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMNkkXMMMMMMMMMMMWKkollllllldkKWMMMMMMMMMMM0kOWMMMMMMMMMMMM
MMMMMMWKXMMMkllxMMMMMMMMMMMMMMMXOold0NMMMMMMMMMMMMMMMollKMMWKKWMMMMMM
MMMMMMdllKMMkllxMMMMMMMMMMMMN0KNMxl0MN00WMMMMMMMMMMMMollKMMOllkMMMMMM
Mkox0XollKMMkllxMMMMMMMMMMMMxllldoldolllOMMMMMMMMMMMMollKMMkllxXOdl0M
MMN0dllll0MMkllxMMMMMMMMMMMMMN0xolllokKWMMMMMMMMMMMMMollKMMkllllx0NMM
MW0xolllolxOxllxMMNxdOMMMMMWMMMMWxlOMMMMWWMMMMWkdkWMMollOOdlolllokKMM
M0lldkKWMNklllldNMKlloMMMNolok0NMxl0MX0xolxMMMXlllNMXolllo0NMNKkoloXM
MMWWMMWXOdlllokdldxlloWMMXllllllooloollllllWMMXlllxolxxolllx0NMMMNWMM
MMMN0kolllx0NMMW0ollll0NMKlloN0kolllokKKlllWMXklllldKMMWXOdlllokKWMMM
MMOllldOKWMMMMkollox0OdldxlloMMMMxlOMMMNlllxoox0Oxlllo0MMMMWKkolllKMM
MMW0KNMMMMMMMMKkOXWMMMW0olllo0NMMxl0MWXklllldXMMMMWKkkXMMMMMMMMX0KWMM
MMMMMMMMMMMMMMMMMMMW0xollox0Odlokdlxxoox00xlllokKWMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMWollllOWMMMMNklllloOWMMMMNxllllxMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMN0xlllokK0xookdlxxookK0xollokKWMMMMMMMMMMMMMMMMMMM
MMWKKWMMMMMMMMKk0XMMMMW0ollloOXMMxl0MWKklllldKWMMMWXOOXMMMMMMMMNKKMMM
MMkllldOXWMMMMklllok00xoodlloMMMMxlOMMMNlllxook00xollo0MMMMWKkdlllKMM
MMMN0xollox0NMMW0ollllONMKlloNKkollldOKKlllWMXklllldKWMMX0xlllok0NMMM
MMWWMMWKkollldkxlodlloWMMXllllllooloollllllWMMXlllxooxkollldOXMMMWMMM
M0lldOXWMNklllldNMKlloMMMNolox0XMxl0WXOxlldMMMXlllNMXolllo0WMWKkdloXM
MW0xlllodldOxllxMMNxdOMMMMMNMMMMMxlOMMMMWNMMMMWxdxWMMollkkoldlllokKWM
MMN0xllll0MMkllxMMMMMMMMMMMMMNKkolllokKWMMMMMMMMMMMMMollKMMkllllkKWMM
MkldOXollKMMkllxMMMMMMMMMMMMxlllooloolll0MMMMMMMMMMMMollKMMkllxKkol0M
MWWMMMdllKMMkllxMMMMMMMMMMMMXO0XMxl0WXOONMMMMMMMMMMMMollKMMOllkMMMWMM
MMMMMMNKKMMMkllxMMMMMMMMMMMMMMMN0oldKWMMMMMMMMMMMMMMMollKMMWKKWMMMMMM
MMMMMMMMMMMMXkxXMMMMMMMMMMMWKkollllllldOXMMMMMMMMMMMM0xkWMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMX0xlllok0xlk0xollox0NMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMXollldOXMMMxlOMMWXOdllldWMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMW0OKWMMWKkollldOXWMMN0kKMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMklllooloollo0MMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMXOOXMxl0WKOONMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMkl0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
Silly Minty Candycane, well this is what she gets.
"Winter2018" isn't for The Internets.
Passwords formed with season-year are on the hackers' list.
Maybe we should look at guidance published by the NIST?
Congratulations!

Answer: minty.candycane

Achievment:

1546433738888

Hints

On solving, Pepper tells me the following, and unlocks two hints:

Well, that explains the odd activity in Minty’s account. Thanks for your help!

All of the Kringle Castle employees have these cool cards with QR codes on them that give us access to restricted areas.

Unfortunately, the badge-scan-o-matic said my account was disabled when I tried scanning my badge.

I really needed access so I tried scanning several QR codes I made from my phone but the scanner kept saying “User Not Found”.

I researched a SQL database error from scanning a QR code with special characters in it and found it may contain an injection vulnerability.

I was going to try some variations I found on OWASP but decided to stop so I don’t tick-off Alabaster.

1546433858712

1546433904858

Both these hints point to the next objective, which involves performing a SQL Injection attack through a barcode reader.

Badge Manipulation

Interaction with the Reader

Another door with an access panel:

1546464932817

The Badge Scan-O-Matic 4000 reader has two inputs, the badge scanner (via camera) or usb (via file upload):

1545532345739

In most cases, I’ll test both the camera and the file upload to see if there’s any difference. To get the camera, I found the easiest thing was to create the image, save it in Dropbox, and then open it on my phone and hold it up to my webcam. I could also upload the same file via file upload.

To create QR-Codes, I used the site recommended by Pepper Minstix. It takes text and returns a QR code image as .png, which is what the reader accepts.

Alabaster’s QR Code

The first thing I did was to look at Alabaster’s QR code. Using a reader app or zxing.org, I can see that data is: oRfjg5uGHmbduj2m. The data appears to be base64 encoded, but decoding didn’t produce anything that seems useful.

Pretty sure that it wasn’t going to open the door, I presented Alabaster’s badge to the reader, which confirmed the account was disabled.

This indicates that I’m going to have to not only find a valid query that returns an account, but one that returns an account that is enabled.

SQL Errors

Next I tried to test for SQL-Injection. I set my QR-code to have the value ', and submitted.

EXCEPTION AT (LINE 96 "USER_INFO = QUERY("SELECT FIRST_NAME,LAST_NAME,ENABLED FROM EMPLOYEES WHERE AUTHORIZED = 1 AND UID = '{}' LIMIT 1".FORMAT(UID))"): (1064, U'YOU HAVE AN ERROR IN YOUR SQL SYNTAX; CHECK THE MANUAL THAT CORRESPONDS TO YOUR MARIADB SERVER VERSION FOR THE RIGHT SYNTAX TO USE NEAR '' LIMIT 1' AT LINE 1")

This is great. Now I have the exact query that’s being run with my input substituted for {}:

SELECT FIRST_NAME,LAST_NAME,ENABLED FROM EMPLOYEES WHERE AUTHORIZED = 1 AND UID = '{}' LIMIT 1

SQL Injection

I could try sending ' OR '1' = '1. This would make the query be:

SELECT FIRST_NAME,LAST_NAME,ENABLED FROM EMPLOYEES WHERE AUTHORIZED = 1 AND UID = '' OR '1' = '1' LIMIT 1

However, in SQL, AND resolves before OR, so this will return true for all users, and then grab the first one, which means I could get an unauthorized user, which doesn’t get me through the door. In fact, that is the case; I get the same message I got with Alabaster’s badge.

Since what I care about is finding an enabled user, I’ll enter ' OR ENABLED = '1. That makes the query that will run:

SELECT FIRST_NAME,LAST_NAME,ENABLED FROM EMPLOYEES WHERE AUTHORIZED = 1 AND UID = '' OR ENABLED = '1' LIMIT 1

So the first part, AUTHORIZED = 1 and UID ='', will return no rows. However, the part after the OR, ENABLED = '1', will return all the enabled users, and then LIMIT 1 will give me the first, which is all I need.

It works (shown using the camera input by displaying the qrcode on my phone to my webcam because that’s neat, through file upload also works just the same):

USER ACCESS GRANTED - CONTROL NUMBER 19880715

Answer: 19880715

This earned two more achievements:

1546434784771

1546434797318