Like før jul twittret PST denne kryptisk meldingen:

Twitterutfordring fra @PSTnorge
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 https://pst.no/jobb/#Jobb

Kamelbokstaver og anagram

Det er ganske åpenbart at det er et eller annet med de store bokstavene som er spredt tilsynelatende vilkårlig i teksten sammen med et eneste punktum: ERTHAIITWT.EU ser ut som et domene.

På denne nettsiden får vi vite at bokstavene før toppdomenet .eu er i feil rekkefølge.

http://erthaiitwt.eu/hangman.html

Om vi stokker om på anagrammet med innholdet i meldingen i bakhodet kommer vi frem til at det er et anagram for twitterhai.eu. En morsom detalj i whois-informasjonen for domenet er at abuse-kontakt er agnet007@1337.no (sic!).

Nettsiden twitterhai.eu

Kildehai og EXIF

En titt på kildekoden viser at teksten har unaturlige linjeskift.

<html>
<title>Hai, there!</title>
<body>
<h2>Velkommen!</h2>
<img width="480" src="1337_shrk.jpg" alt="Hungry_Shark"><br>


S&aring; 
hyggelig &aring; se 
at du har funnet fram<br>Velkommen skal du v&aelig;
re til v&aring;r lille dam<br><br>Se deg litt rundt og se hva du 
kan finne
.<br> Hvem vet 
hva som skjuler seg dypt her inne<br><br>N&aring; har du sjansen 
til &aring; vise hva du kan<br>hvis du blir 
med ut p&aring; 
litt dypere vann.<br>


</body>
</html>

Første bokstav på hver linje blir Shark.html.

http://twitterhai.eu/Shark.html inneholder tips om hvordan man skriver en god jobbsøknad.

Haitips om hvordan man skriver en god jobbsøknad

På tross av de gode rådene er dette et blindspor.

Ser vi nærmere på haibildet finner vi en kommentar i EXIF-dataene med URL-en /haitech_secure.html.

EXIF-data for bildet 1337_shrk.jpg

Passordverifisering på klientsiden er dårlig praksis

twitterhai.eu/haitech_secure.html finner vi en innloggingsside.

Kildekoden viser at passordet verifiseres i javascript på klientsiden, altså i browseren til den som besøker siden. Dette er scriptet som validerer passordet og returnerer en melding:

function login(){
	//Need to handle this server side in the future. This will probably keep the skiddies out for now...
	ciphertext = "C1UIHlIAaEcQJlEeTVIGaFAcaEcGDF9SPFVJPEEfCF1SIF0dchRnGFQVKw5GZ1MHG1QVOlEcJkJDCkECPRscJkIyCkYALUZHPVMXFA==";

	cleartext = "";
	password = document.getElementById("password").value;
	timestamp = Math.floor(Date.now()/10);

	if(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 ){
		cleartext = decrypt(ciphertext, password);
		const client = new XMLHttpRequest();
		const url='?t=' + timestamp.toString() + "&pwd=" + password;
		client.open("GET", "?success");
		client.send(); 
		document.getElementById("instruction").innerHTML = "Kult! Du er r&aring;!";
		alert(cleartext);
	}
	else{
		console.log("Guru meditation:", decrypt(ciphertext, password));
		document.getElementById("instruction").innerHTML = "Beklager, feil passord. Pr&oslash;v igjen!";
	}
}

function decrypt(ciphertext, password){
	ciphertext_bytes = atob(ciphertext);
	for(i = 0; i < ciphertext_bytes.length; i++){
		cleartext += String.fromCharCode(ciphertext_bytes.charCodeAt(i) ^ password.charCodeAt(i % password.length));
	}

	return cleartext;
}

Det sjekker bokstav for bokstav i passordet som sjekkes mot en ASCII-karakter oppgitt i desimalformat. Det er en smal sak å justere litt på scriptet og printe ut passordet.

var password = []
password[0] = 8*8+8 
password[1] = Math.pow(9,2) - 29 
password[2] = Math.pow(10, 2) + Math.pow(3, 2) 
password[3] = password[2] 
password[4] = 3 
password[5] = 7*17-5 
password[6] = password[0] 
password[7] = password[1]
password[8] = 0x69
console.log(password)

0: 72
1: 52
2: 109
3: 109
4: 3
5: 114
6: 72
7: 52
8: 105
length: 9

password.forEach(function(Element){ console.log(String.fromCharCode(Element)) ; })
H
4
m
m
3
r
H
4
i

Passordet er altså H4mm3rH4i. Dette gir oss en dialogboks med meldingen

Caesar synes at du skal ta turen hit:
uggc://gjvggreunv.grpu/unv_gurer.ugzy
Dialogboks ved riktig passord

Cæsarchiffer

Cæsarchiffer er en gammel klassiker. Det går ut på å forskyve bokstavene i alfabetet. Ut i fra strukturen på strengen kan man gå ut i fra at «uggc» skal være «http». Altså er bokstavene forskjøvet 13 plasser nedover i alfabetet, såkalt ROT13.

En kjapp runde med kommandolinjeverktøyet tr fikser biffen.

$ echo "uggc://gjvggreunv.grpu/unv_gurer.ugzy" | tr '[a-z]' '[n-za-m]'
http://twitterhai.tech/hai_there.html
twitterhai.tech/hai_there.html

Roboter, pcap og tekst i tomrom

Nettsiden peker oss videre til twitter-kontoen @twitt3rhai. Nyeste tweet er "#justdoit, or make your ROBOTS do it. Transfer teXt to an ediTor". Når vi sjekker ut robots.txt finner vi dette:

User-agent: *
Disallow: /min_hemmelige_mappe/

I mappen min_hemmelige_mappe ligger filen haimat.

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

I Wireshark ser vi en maskin (som trolig kjører Debian 9 basert på at den kommuniserer med http://ftp.uio.no/debian/dists/stretch-updates/InRelease) hente ned filen secret_data.zip fra RFC1918-adressen 192.168.230.129. Wireshark gjør det lett å hente ut denne med Export HTTP Objects (File → Export Objects → HTTP).

Liste over filer som kan hentes ut ved hjelp av Export HTTP object

Det viser seg at zip-filen krever et passord for å pakke ut den ene filen som ligger i arkivet, insignificant_shark.png.

La oss gå tilbake til Twitter-kontoen. Det er mange titalls tweets og flere av dem har unaturlige mellomrom mellom ordene. Siste melding oppfordrer oss til å legge inn teksten i en tekstredigeringsprogram, men med så mange tweets er ikke det praktisk å gjøre manuelt.

Med Python-programmet twarc henter vi ned tweets i json-format og henter ut selve twittermeldingene ved hjelp av jq.

$ twarc timeline twitt3rhai | jq '.full_text' > twitt3rhai_tweets.txt
Alle tweets fra @twitt3rhai

Vi ser at strengen HAI1337 skrives i mellomrommene.

Når vi bruker HAI1337 som passord på zip-filen får vi ut bildefilen insignificant_shark.png.

Mer eller mindre signifikante bits

På haien står det skrevet LSB i runer. Sammen med filnavnet insignificant_shark.png er det naturlig å anta at det har med Least Significant Bit å gjøre, som er en vanlig steganografimetode.

Et nyttig verktøy til dette er Steganography Toolkit som gir deg et shell med en rekke nyttige verktøy ferdig installert.

docker run -it --rm -v $(pwd)/data:/data dominicbreuker/stego-toolkit /bin/bash

Det generelle verktøyet stegoveritas er fint å begynne med.

root@7852ecc8e175:/data# stegoveritas.py insignificant_shark.png 
Type:   Portable network graphics
Mode:   RGB

Checking Meta Data

Size                     : 1575x851
Bit Depth                : 8
Color Type               : RGB
Compression Used         : Deflate
Filter Method            : Adaptive Filtering
Interlace Method         : No Interlace
Checking for trailing data
Running image filters
Attempting to brute force LSB items

(…)

Ut av dette genereres en rekke bilder hvor blant annet de tre fargekanalene RGB, gjennomsiktighet (alpha) og ulik oppskarping blir justert på bildet. Da oppdager vi en QR-kode på haien.

Hai med QR-kode

QR-koden består av tekststrengen "You thought we would hide anything of SIGNIFICANCE? Not the LEAST..."

Så det er ikke least significant bit. Hva med most significant bit?

Verktøyet zsteg er også bra på png-steganografi.

URL skjult med steganografi

Der dukker det opp en URL på et nytt domene, http://twitterhai.tech/u_are_th3_winrar.jpg.

Winrar, winrar, chicken dinner!

$ ls -lah u_are_th3_winrar.jpg
-rw-rw-r-- 1 fredrik fredrik 8.6M Dec  3 13:24 u_are_th3_winrar.jpg

Det virker ikke helt riktig at et lite JPEG-bilde har en størrelse på drøye 8,5 megabyte, og filnavnet hinter om at det er et RAR-arkiv inne i bildet (pun intended).

Filer starter, og som regel slutter, med noen spesielle verdier. I en filsignaturtabell kan vi se at JPEG starter med hex-verdiene FF D8 og slutter med FF D9.

Start på JPEG - FF D8

Filen starter på FF D8 som den skal, men når vi søker etter FF D9 ser vi at det langt i fra er slutten av filen.

Slutt på JPEG - FF D9

De neste hex-verdiene er 52 61 72 21 1A 07 01 00, som vi i tabellen kan se er filhodet for RAR v5.

RAR-filen begynner på offset 0x1035E som er desimaltallet 66398. Ved hjelp av verktøyet dd kan vi skrive dataene fra denne plassen og ut til en ny fil og pakke ut denne med unrar.

$ dd if=u_are_th3_winrar.jpg bs=1 skip=66398 of=u_are_th3_winrar.rar
8914231+0 records in
8914231+0 records out
8914231 bytes (8.9 MB, 8.5 MiB) copied, 17.5981 s, 507 kB/s

$ unrar e u_are_th3_winrar.rar

Extracting from u_are_th3_winrar.rar

Extracting  gratulerer.txt                                            OK
Extracting  gratulerer.gif                                            OK
All OK

Da får vi ut et tekstdokument og en animert gif av Jay Gatsby som skåler gratulerende.

Tekstdokumentet gratulerer oss med å ha løst oppgavene og gir oss et kodeord vi kan bruke for å bevise at vi har løst oppgavene.

Gratulerer, du har løst de oppgavene vi hadde i denne omgang.·

Hvis du har lyst på reelle utfordringer og å løse oppgaver som kan bidra til å utgjøre en forskjell så håper vi at du tar deg tid til å søke.

Bruk gjerne kodeordet SHARKNADO i søknaden din, så vi vet at du har fullført challengen!

Vi ser frem til å høre fra deg!

(Her har du 4500 ord med Lorem Ipsum dummytext)

Lorem ipsum dolor sit amet (…)

Gratulasjonsbilde