PST - Gåte i jobbannonse

FYI

This post is written in norwegian!

TL;DR The Norwegian Police Security Service published a job posting including a challenge that potential candidates for the job could solve. You would end up with a "code word" you could include in your job application "proving" you solved the challenge.

This is a writeup of how I solved this challenge.

Writeup

Dette er gåten vi får oppgitt i jobbannonsen fra PST. Og som er starten på en rekke steg for å komme frem til en endelig løsning.

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

Det første man legger merke til er at enkelte bokstaver er i uppercase, mens andre er lowercase.
Samler vi alle bokstaver som er uppercase ender vi opp med følgende string:

ERTHAIITWTEU

Etter å ha forsøkt flere kombinasjoner kom jeg frem til følgende URL: TWITTERHAI.EU

Laster vi ned dette bilde og sjekker filtypen finner vi følgende comment: "/haitech_secure.html"

root@kali:~/Desktop/pst# 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

Om vi følger denne URL-en kommer vi frem til følgende nettside:

Undersøker man kildekoden finner man ut at koden for å logge inn er skrevet i javascript:

var input_field = document.getElementById("password");
input_field.addEventListener("keyup", function(event){
  event.preventDefault();
  if(event.keyCode === 13){
    login();
  }
})

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);

  const client = new XMLHttpRequest();
  const url='?t=' + timestamp.toString() + "&pwd=" + password;
  client.open("GET", url);
  client.send(); 
  //not done yet.
  

  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å!";
    alert(cleartext);
  }
  else{
    console.log("Guru meditation:", decrypt(ciphertext, password));
    document.getElementById("instruction").innerHTML = "Beklager, feil passord. Prø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 eneste man trenger å fokusere på er hvordan funksjonen login() sjekker bokstav-for-bokstav om du har skrevet riktig passord:

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 )

Første bokstaven må tilsvare decimal-verdi 8*8+8 som er 72, andre bokstav må tilsvare decimal-verdi (9^2) - 29 osv.
Etter å ha gått gjennom linje-for-linje ender man opp med følgende verdier:

72
52
109
109
3
114
72
52
105

Konverterer man alle tall bortsett fra det 5. tallet (det 5. tegnet i passordet du oppgir blir sammenlignet med tallet 3) til ASCII ender man opp med følgende passord: H4mm3rH4i

Caesar synes at du skal turen hit: uggc://gjvggreunv.grpu/unv_gurer.ugzy

So... Teksten er obfuskert med Caesar cipher - også kalt rot-13.
Etter å ha "dekryptert" teksten ender vi opp med denne URLen: http://twitterhai.tech/hai_there.html

Går man til twitter.com/twitt3rhai blir man møtt med dette:

66 tweets totalt, 65 som tilsynelatende inneholder tilfeldige haisorter?? Wtf.

Her ble jeg stående fast en stund, og prøvde ganske mye forskjellige før jeg faktisk leste hva som sto i den nyeste tweeten.

#justdoit, or make your ROBOTS do it. Transfer teXt to an ediTor

Så, etter å ha gjort hva som står i tweeten; crawlet twitter-kontoen og fått teksten over til Atom blir jeg møtt med følgende string etter å ha zoomet ut:

Sjekker man robots.txt på http://twitterhai.tech/ finner man dette:

User-agent: *
Disallow: /min_hemmelige_mappe/

Og i mappen /min_hemmelige_mappe finner vi følgende:

Etter å ha lastet ned filen må man finne ut hvilken filtype dette egentlig er:

root@kali:~/Desktop/pst# file haimat 
haimat: pcap-ng capture file - version 1.0

La oss åpne filen i Wireshark og se hva vi finner av informasjon.

Det aller første jeg gjorde her var å se om capture-fila hadde fanget opp noen filer som hadde blitt overført.

Well shit.

Om man forsøker å unzippe secret_data.zip får man beskjed om å taste inn et passord.

root@kali:~/Desktop/pst# unzip secret_data.zip 
Archive:  secret_data.zip
[secret_data.zip] insignificant_shark.png password: 
   skipping: insignificant_shark.png  incorrect password

Og analyserer man wireshark-fila litt mer nøye ser man også at det blir nevnt at vi allerede har passordet vi trenger...??

Hva med å teste stringen vi fikk ut fra alle tweetsene fra twitter-kontoen vi oppdaget tidligere (HAI1337)?

root@kali:~/Desktop/pst# unzip secret_data.zip 
Archive:  secret_data.zip
[secret_data.zip] insignificant_shark.png password: 
  inflating: insignificant_shark.png  
root@kali:~/Desktop/pst# ls
haimat  insignificant_shark.png  secret_data.zip

Well, hello there...

Åpner vi denne fila blir vi møtt med denne fine haien:

Det første jeg testet var om det var skjult noe i metadataen til fila, men her fant jeg ingenting.
Jeg åpnet deretter fila i et bilderedigeringsprogram i håp om at jeg kunne avdekke noe ved å justere levels, brightness, contrast osv.

Scanner man denne QR-koden får man følgende beskjed:

You thought we would hide anything of SIGNIFICANCE? Not the LEAST...

Well, screw you too!

På tide å undersøke de tre tegnene i tegningen. Det var ganske åpenbart at dette var runeskrift.

På bildet står det altså "LSB"... Least Significant Bit?

I steganography er dette en kjent teknikk for å gjemme data i f.eks. bilder.
Om vi endrer de siste bitsene for en farge i et bilde kan vi ersatte disse med vår egen data uten at det påvirker bilde i noen grad som kan oppdages av mennesker, og dermed skjule data.

Og selvfølgelig finnes det verktøy for å hente ut data gjemt ved hjelp av LSB steganography.
zsteg er et fantastisk verktøy for akkurat dette!

root@kali:~/Desktop/pst# zsteg insignificant_shark.png 
imagedata           .. text: "@@@aaaNNN"
b1,rgb,lsb,xy       .. text: "http://twitterhai.tech/u_are_th3_winrar.jpg"
b3,bgr,msb,xy       .. file: MPEG ADTS, layer I, v2,  96 kbps, Monaural
b4,g,msb,xy         .. file: MPEG ADTS, layer I, v2, 112 kbps, JntStereo```

Går man til denne nettsiden får man servert følgende bilde:

Tyder på at vi endelig nærmer oss slutten!

Begynner med å sjekke metadata, men fant ingenting av spesiell interesse:

root@kali:~/Desktop/pst# exiftool u_are_th3_winrar.jpg 
ExifTool Version Number         : 11.13
File Name                       : u_are_th3_winrar.jpg
Directory                       : .
File Size                       : 8.6 MB
File Modification Date/Time     : 2018:12:03 13:24:04+01:00
File Access Date/Time           : 2019:01:08 22:14:54+01:00
File Inode Change Date/Time     : 2019:01:08 22:14:54+01:00
File Permissions                : rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : inches
X Resolution                    : 96
Y Resolution                    : 96
Exif Byte Order                 : Big-endian (Motorola, MM)
Orientation                     : Horizontal (normal)
Comment                         : CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 82.
Image Width                     : 664
Image Height                    : 636
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 664x636
Megapixels                      : 0.422

Det som derimot er merkelig er at fila er på 8.6 MB, men selve bildet er på 664x636px.
Filstørrelsen er litt i overkant stor for et så lite bilde, så her er det definitivt noe som er gjemt i bildet.

Hva med å bruke binwalk for å sjekke om det ligger ekstra data i bildet?

Binwalk is a simple linux tool for analysing binary files for embeded files and executable code. It is mostly used to extract the content of firmware images.

Som nevnt over er dette et verktøy som hovedsaklig blir brukt til reverse engineering/analyse av firmware, men det kan også brukes i dette tilfellet.

La oss se om binwalk finner noe:

root@kali:~/Desktop/pst# binwalk u_are_th3_winrar.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
30            0x1E            TIFF image data, big-endian, offset of first image directory: 8
66398         0x1035E         RAR archive data, version 5.x
2552386       0x26F242        Certificate in DER format (x509 v3), header length: 4, sequence length: 30088

Oh my... La oss hente ut alt som ligger gjemt her!

root@kali:~/Desktop/pst# binwalk --extract u_are_th3_winrar.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
30            0x1E            TIFF image data, big-endian, offset of first image directory: 8
66398         0x1035E         RAR archive data, version 5.x
2552386       0x26F242        Certificate in DER format (x509 v3), header length: 4, sequence length: 30088

root@kali:~/Desktop/pst# ls
haimat  insignificant_shark.png  secret_data.zip  u_are_th3_winrar.jpg  _u_are_th3_winrar.jpg.extracted
root@kali:~/Desktop/pst# cd _u_are_th3_winrar.jpg.extracted/
root@kali:~/Desktop/pst/_u_are_th3_winrar.jpg.extracted# ls -la
total 17504
drwxr-xr-x 2 root root    4096 Jan  8 22:22 .
drwxr-xr-x 3 root root    4096 Jan  8 22:22 ..
-rw-r--r-- 1 root root 8914231 Jan  8 22:22 1035E.rar
-rw-r--r-- 1 root root 8966091 Dec  3 10:27 gratulerer.gif
-rw-r--r-- 1 root root   29615 Nov 30 10:05 gratulerer.txt

Og printer vi ut den første delen av gratulerer.txt får vi følgende beskjed:

root@kali:~/Desktop/pst/_u_are_th3_winrar.jpg.extracted# head -n 12 gratulerer.txt
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)

[...]
comments powered by Disqus