Løsningen på PST sin jobbannonse-gåte

PST utlyste jobb med en diger digital gåte, for å finne riktige kandidater. Her er (forhåpentligvis) hele løsningen.

Politiets sikkerhetstjeneste (PST) la i desember ut en jobbannonse hvor de søkte en etter «nysgjerrig og løsningsorientert teknisk etterforsker innen digitale spor».

Jobbannonsen inkluderte et limerick, som var en gåte de ville at folk skulle løse. Jeg hørte ikke om annonsen før den var på forsida av mange aviser, med titler av typen «om du løser denne gåten, kan jobben bli din».

Hai-temaet 🦈

Nesten alle deler av mysteriet hadde et hai-tema. Bakgrunnen for det er en flau episode fra oktober 2018, hvor PST plutselig tweeta et bilde av en hai.

Det var det syv år gamle barnet til en av PSTs ansatte som kom borti dele-knappen mens han spilte Hungry Shark Evolution på fars iPad. Dette førte selvfølgelig til spekulasjoner om hvorvidt Twitter-kontoen var hacka.

(Det var ikke en iPad med noe klassifisert informasjon, men en iPad til å oppdatere Twitter hjemmefra (og Twitter-kontoen er stengt for direktebeskjeder).)

Steg 1: Limericken

Limericken i jobbannonsen var følgende:

En oktobermorgen fikk vi pulsen til å øke
var det en hackeR som hadde lykkes med forsøkeT
men en HAI I en TWeeT
er ikke særlig 1337.
løser du gåtEn bør dU vurdere å søke

Meningen til limericken i seg selv spiller ingen rolle, men det ligger et mønster i den:

En oktobermorgen fikk vi pulsen til å øke
var det en hackeR som hadde lykkes med forsøkeT
men en HAI I en TWeeT er ikke særlig 1337.
løser du gåtEn bør dU vurdere å søke

De store bokstavene utgjør ERTHAIITWTEU. Som du kanskje vet, er .eu et toppdomene, og du ser kanskje at det bare er ett punktum i limericken. Dette utgjør ERTHAIITWT.EU. Er du kjappere enn meg, ser du kanskje allerede at bokstavene kan omrokkeres til TWITTERHAI.

Omvei 1:
Jeg så ikke at bokstavene kunne omrokkeres, så jeg besøkte erthaiitwt.eu. Her får du opp en hangman som sier at rekkefølgen er feil.

Løsning 1:
Det riktige å gjøre var å besøke twitterhai.eu.

Steg 2: HTML-sida

twitterhai.eu viser et bilde av en hai, og gir et nytt dikt som ber deg se deg omkring. Jeg ville uansett tatt en titt på kildekoden, men jeg så også at det var et rart mellomrom i midten av ordet «være».

Det er et tegn på at det var noe rart i HTML-koden et sted:

📸: Roy Solberg
📸: Roy Solberg Vis mer

Ser du de snodige linjebruddene og hva den første kollonna utgjør? «Shark.html».

Omvei 2a:
Jeg pleier å se nærmere på robots.txt, og har til og med laga en fin robots.txt-bookmarklet for å enkelt åpne lenker fra nettopp den fila. Besøker du twitterhai.eu/robots.txt får du et nyttig hint som sier «Use the source, Luke!»

Omvei 2b:
Jeg er vant til filnavn med små bokstaver, så jeg gikk direkte til twitterhai.eu/shark.html. Der fikk jeg hintet «Case matters. Watch your characters».

Løsning 2:
Løsningen på steg 2 var å besøke twitterhai.eu/Shark.html.

📸: PST (Mye mulig dette blir første og siste bildebyline PST får på kode24, dessverre.)
📸: PST (Mye mulig dette blir første og siste bildebyline PST får på kode24, dessverre.) Vis mer

Steg 3: Bildet

Jeg antar at noen stoppa å lete mer da de fant twitterhai.eu/Shark.html, som gir deg tips om å skrive en god jobbsøknad. Men, det ligger en HTML-kommentar der om at de har flere gåter om du ser nøyere etter.

Jeg kunne ikke se noen andre spor eller retninger enn bildet fra steg 2. Det som gjorde dette vanskelig for meg, var at verktøyet jeg brukte for å se på Exif metadata ikke avslørte noe. Ettersom jeg forstår det, skjulte ikke løsningen seg i Exif, men i en JPEG-fil-kommentar.

Det finnes verktøy der ute som gir deg mye mer enn bare Exif, og bruker du et Unix-system kan du bruke varianter av file-kommandoen for å finne det du leter etter:

file 1337_shrk.jpg

1337_shrk.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 72x72, segment length 16, 
Exif Standard: [TIFF image data, big-endian, direntries=3, PhotometricIntepretation=RGB, orientation=upper-left], 
comment: "/haitech_secure.html", baseline, precision 8, 851x514, frames 3

Løsning 3:
Løsningen på steg 3 var å besøke twitterhai.eu/haitech_secure.html.

Steg 4: Javascript-et

twitterhai.eu/haitech_secure.html inneholdt noe generell tekst med «tips» for å søke en jobb. Men viktigere: Et passordfelt og en login-knapp.

Kildekoden avslørte en klientside-validering av passordet, som først verifiserte passordet og så brukte passordet som en nøkkel til å dechiffrere en ciphertext.

Javascript-et som gjorde den faktiske verifiseringen så slik ut:

password.charCodeAt(0) == 8 * 8 + 8 && 
password.charCodeAt(1) == Math.pow(9, 2) - 29 && 
password.charCodeAt(2) == Math.pow(10, 2) + Math.pow(3, 2) && 
password.charCodeAt(3) == password.charCodeAt(2) && 
password.substring(4, 5) == 3 && 
password.charCodeAt(5) == 7 * 17 - 5 && 
password.charCodeAt(6) == password.charCodeAt(0) && 
password.charCodeAt(7) == password.charCodeAt(1) && 
password.charCodeAt(8) == 0x69

Passordet var åpenbart ni karakterer langt, og man trengte bare å kalkulere hver karakter. Jeg bare kopierte og limte inn, og brukte dette kjappe Javascript-et i konsollen for å skrive ut passordet og kjøre login-funksjonen, som ga meg et varsel med neste hint:

var password = [];
password[password.length] = 8 * 8 + 8;
password[password.length] = Math.pow(9, 2) - 29;
password[password.length] = Math.pow(10, 2) + Math.pow(3, 2);
password[password.length] = password[password.length - 1];
password[password.length] = '3'.charCodeAt(0);
password[password.length] = 7 * 17 - 5;
password[password.length] = password[0];
password[password.length] = password[1];
password[password.length] = 0x69
for (var i = 0; i < password.length; i++) {
    password[i] = String.fromCharCode(password[i]);
}
password = password.join('');
document.getElementById("password").value = password;
console.log(password);
login();

Løsning 4:
Passordet man trengte var H4mm3rH4i (hammerhai).

Steg 5: Caesar-chifferet

Varselboksen viste teksten «Caesar synes at du skal ta turen hit: uggc://gjvggreunv.grpu/unv_gurer.ugzy». Ved å bare se bort fra den siste delen, var det ganske åpenbart at dette var en «Caesar cipher», som måtte være http://ettellerannet.html.

Det er mange steder man kan løse slike koder, men et kjapp Javascript gjorde også susen:

var cipher = 'uggc://gjvggreunv.grpu/unv_gurer.ugzy';
var shift = cipher.charCodeAt(0) - 'h'.charCodeAt(); // Char we suspect to know
var charDistance = 'a'.charCodeAt();
var cleartext = '';
for (var i = 0; i < cipher.length; i++) {
    var charCode = cipher.charCodeAt(i) - charDistance;
    if (charCode >= 0 && charCode <= 25) { // a-z
        cleartext += String.fromCharCode((((charCode + shift) % 26) + charDistance));
    } else {
        cleartext += cipher[i];
    }
}
console.log(shift, charDistance, cleartext);

Løsning 5:
Resultatet ble twitterhai.tech/hai_there.html.

Steg 6: ASCII-kunst og hemmelig mappe

twitterhai.tech/hai_there.html fortalte deg bare at du kunne følge Twitter brukeren twitt3rhai. Deres siste tweet var teksten «#justdoit, or make your ROBOTS do it. Transfer teXt to an ediTor».

Jeg antar dette var et dobbelt hint; enda en tur til robots.txt, og sende resten av Twitter-meldingene til en editor. robots.txt viste til stien /min_hemmelige_mappe/.

Det var 65 andre Twitter-meldinger der, med hai- og fiskerelaterte ord. Det så ut som en slags chiffer, og det beste var å bare kopiere inn alle til en editor:

Tigerhai HvithaiHammerhaiHvalhai Oksehai Domenehai Brugde
Brugde DomenehaiTigerhaiHvithai Hvalhai Hammerhai Oksehai
HammerhaiJaws   Fish   Hvalhai Oksehai Domenehai Tigerhai
HvithaiHaiene   Tail   Tigerhai DomenehaiBrugde Hammerhai
HåbrannBrugde   Fins   HammerhaiBrugde HvithaiHvalhaiJaws
HvithaiHammer          Domenehai Tigerhai Oksehai Hvalhai
DomenehaiJaws   Mako   HåbrannHvithai HvalhaiTigerhaiMako
BrugdeOksehai   Apex   Tigerhai HvalhaiDomenehaiHammerhai
HvithaiBrugde   Jaws   HammerhaiOksehai BrugdeTigerhaiHai
Brugde HvalhaiHvithaiDomenehai Oksehai Tigerhai Hammerhai
TigerhaiHvithaiOksehai BrugdeHammerhaiHvalhaiDomenehaiHai
HvithaiHvalhai   BrugdeOksehaiDomenehai HammerhaiTigerhai
HvithaiSjøen   H   TigerhaiOksehai DomenehaiHvalhaiBrugde
Hammerhaien   Hai   Domenehai HvalhaiBrugdeHvithaiOksehai
HvithaiHai           DomenehaiHvalhai Hammerhai Oksehaien
HvithaiHai   Havet   Oksehai TigerhaiHvalhaiDomenehaiApex
OksehaiHai   Sjøen   HvalhaiBrugde HvithaiHammerhaiBrugde
BrugdeJaws   Finne   Brugde HvithaiHvalhaiTigerhai Haiene
HammerhaiDomenehaiBrugdeOksehaiTigerhai HvalhaiHvithaiHai
HvalhaiBrugdeTigerhaiHammerhaiHvithai Oksehai Domenehaien
Domenehaier           OksehaiHvithai HammerhaiHvalhai Hai
OksehaiTigerhai   HvalhaiDomenehaiHammerhai BrugdeHvithai
DomenehaiBrugde   TigerhaiHammerhai HvithaiHvalhaiOksehai
BrugdeHvithaien   HammerhaiDomenehaiHvalhai Tigerhai Mako
TigerhaiHvalhai   BrugdeDomenehaiHvithai OksehaiHammerhai
BrugdeOksehaien   HammerhaiHvalhaiDomenehai HvithaiBrugde
HvithaiJaws           HaiHvalhaiHammerhai BrugdeDomenehai
DomenehaiTigerhaiHammerhaiHvithaiBrugdeOksehai HvalhaiHai
TigerhaiHvithaiBrugdeHvalhaiOksehai Domenehai Hammerhaien
BrugdeTigerhaiHammerhai   DomenehaiHvalhai OksehaiHvithai
DomenehaiOksehaiSjøen     HammerhaiHvalhaiTigerhaiHåbrann
Hammerhai HvithaiBrugde   OksehaiHvalhai BrugdeTigerhaien
HvithaiBrugdeOksehaiHai   TigerhaiDomenehai HvalhaiBrugde
HvalhaiOksehaiDomenehai   TigerhaiBrugde HammerhaiHvithai
Tigerhai HvithaiOksehai   HammerhaiDomenehaiBrugdeHvalhai
HvithaiOksehaiBrugde         Hammerhai Tigerhai Domenehai
HvalhaiHammerhaiHvithaiBrugdeTigerhai OksehaiDomenehaiHai
DomenehaiHvithaiBrugdeTigerhaiHammerhai Hvalhai Oksehaien
OksehaiBrugdeBrugde         Hvithai DomenehaiTigerhaiApex
HvalhaiHvithaiJaws   Haier   DomenehaiHammerhaiTigerhaien
TigerhaiBrugdeOksehaiSjøen   Domenehai HvalhaiHammerhaien
DomenehaiHammerhaiHavet     BrugdeOksehai HvithaiTigerhai
HvalhaiHammerhaiHvithaiHai   Brugde Oksehaien Domenehaien
DomenehaiBrugdeHai   Havet   Hammerhai Hvalhai Tigerhaien
HvalhaiOksehaiBrugde        BrugdeDomenehaiTigerhaiBrugde
Hvithai DomenehaiBrugdeHammerhaiTigerhaiHvalhai Oksehaien
HvalhaiBrugdeHvithaiDomenehaiOksehai Tigerhai Hammerhaien
BrugdeHvithaiBrugde         HammerhaiTigerhaiHvalhaiSjøen
Domenehai Tigerhai   Sjøen   HvithaiHammerhai Brugde Jaws
OksehaiBrugdeHvalhaiHvitha   Domenehai Tigerhai Hammerhai
TigerhaiHammerhaiHavet     HvalhaiHvithai BrugdeDomenehai
TigerhaiDomenehaiHammerhai   Hvalhai HvithaiOksehaiBrugde
HvithaiDomenehaien   Finne   HammerhaiHvalhaiBrugdeBrugde
BrugdeOksehaiBrugden        Hammerhai Hvithai Domenehaien
HvithaiBrugde TigerhaiOksehaiDomenehaiHammerhai Hvalhaien
DomenehaiHammerhaiOksehaiHvithaiHvalhai Brugde Tigerhaien
HammerhaiTigerhai           DomenehaiHvithaiBrugdeHvalhai
HvalhaiBrugdeHvit   Haier   OksehaiTigerhai Domenehai Hai
OksehaiBrugdeHvithaiJaws   HavetDomenehai TigerhaiHvalhai
DomenehaiHvithaiHåbrann   Hammerhai Brugde OksehaiHvalhai
DomenehaiHvalhaiBrugde   OksehaiBrugdeHammerhai Hvithaien
DomenehaiTigerhaiApex   Hammerhai Hvithai Hvalhai Oksehai
OksehaiHammerhaiJaws   DomenehaiTigerhaiBrugdeHvalhaiJaws
Hvalhai HvithaiTigerhaiDomenehaiBrugdeHammerhai Oksehaien
Håbrann TigerhaiOksehaiHvithaiBrugdeHvalhaiHammerhaiHavet

Løsning 6:
Det var to ting å hente her. For det første adressen til http://twitterhai.tech/min_hemmelige_mappe/, samt ordet HAI1337 som gjemte seg i alle Twitter-meldingene.

📸: Roy Solberg
📸: Roy Solberg Vis mer

Steg 7: Wireshark-dumpen

Den nevnte URL-en http://twitterhai.tech/min_hemmelige_mappe/ var adressa til en mappe som inneholdt en fil kalt «haimat», og det var jommen haimat.

Igjen var file-kommandoen en kjapp måte å bestemme filtypen:

file haimat
haimat: pcap-ng capture file - version 1.0

En pcap-ng capture-fil inneholder en dump av pakker, fanget fra et nettverk, og ses typisk fra det gode, gamle pakkeanalyse-verktøyet Wireshark.

Jeg er ingen ekspert i Wireshark, men jeg har brukt det av og til for å lytte til nettverkstrafikk. Jeg brukte det masse da jeg bygget appen min for HDL Buspro-smarthjem, for å se hvordan de forskjellige komponentene snakket sammen.

Heldigvis hadde denne dumpen bare rundt 400 pakker. Det kan helt sikkert være at jeg overså noe, men jeg fant to ting. Det første var en nettleser som besøkte rota av en server, og fikk tilbake følgende HTML:

<html>
<head>
    <title>Sharky Secret Distributor</title>
</head>
<body>
    Her er dataene dine. Passordet har du allerede... <a href="/secret_data.zip">secret_data.zip</a>
</body>
</html>

Sida sa altså «Her er dataene dine. Passordet har du allerede...», og lenka til en ZIP-fil.

Den andre interessante tingen var responsen fra kallet for den faktiske ZIP-fila. Wireshark lar deg enkelt lagre filer som har blitt overført over nettet.

Løsning 7:
Løsningen var å hente ut ZIP-fila.

Steg 8: ZIP-fila

Når man prøvde å pakke ut ZIP-fila, ble man bedt om et passordet for fila insignificant_shark.png.

Løsning 8:
Som hintet sa, hadde vi allerede passordet. Jada; passordet var HAI1337.

📸: Roy Solberg / PST
📸: Roy Solberg / PST Vis mer

Steg 9: Runer og steganografi

Selvfølgelig var bildet av en hai. Den hadde det som så ut som runer på sida, og ser man på en tabell over runealfabetet finner man de tre runene, som oversettes til LSB.

Hva kan LSB bety i konteksten til et bilde? Least significant bit. Det passer også til filnavnet insignificant_shark.png. Steganografi er kunsten å skjule filer, beskjeder, bilder eller video i en annen fil, beskjed, bilde eller video. Og det finnes mange verktøy på nett for å se etter skjulte beskjeder i bilder.

Omvei 9:
Om du dekodet bildet feil fikk du opp en QR-kode, som ga den nyttige teksten «You thought we would hide anything of SIGNIFICANCE? Not the LEAST....».

Løsning 9:
Dekoder du bildet, ved å se på LSB, får du URL-en twitterhai.tech/u_are_th3_winrar.jpg.

Steg 10: WinRAR

Bildet twitterhai.tech/u_are_th3_winrar.jpg har teksten «Do we we have a winner?».

Men gåten kan ikke ende med et spørsmål. Så hva skal vi se etter? URL-en sier «winrar», ikke «winner». Og det enkle bildet tar hele 9 megabyte. Det er mulig å gjemme filer i slutten av bilder, og WinRAR er et arkiveringsverktøy for ZIP- og RAR-filer.

Løsning 10:
Løsningen var å bruke for eksempel WinRAR til å pakke ut fila «gratulerer.txt» og «gratulerer.gif» fra bilde-fila.

Vi har en vinner

Det ville ikke overraske meg om det var enda et nivå av gåter og løsninger skjult et sted, men hvem vet.

Fila gratulerer.txt inneholdt en hilsen som sa at alle gåtene nå var løst, inkludert et (hairelatert, såklart) kodeord som kunne brukes for å bevise at man hadde klart hele utfordringen. gratulerer.gif var en GIF fra filmen The Great Gatsby.

«Beviser alt dette at du er klar for å jobbe med digital etterforskning?»

Så beviser alt dette at du er klar for å jobbe med digital etterforskning for et nasjonalt sikkerhetsorgan? Ikke i seg selv, selvfølgelig. Men jeg antar at det er en god start for søkere. Å løse alle bitene viser at man har grunnleggende forståelse for et vidt spekter av temaer, som litt koding, litt grunnleggende kryptografi, litt nettverk og noe generell smarthet.

Søkte du på jobben etter 8. januar måtte du forvente noen ekstra spørsmål om løsningen, da noen løste den på Reddit, og løsningen ligger på Github. 😀 Selv ville jeg vente med å publisere dette til etter søknadsfristen.

Å gi utfordringer som denne hjelper å spre ordet om ledige stillinger, spesielt når den ender opp på så mange avisforsider. Så jeg håper PST fikk noen gode kandidater!