• NC3CTF2017 – Opgave 4 – Tys Tys

    Lavet af undertegnede

    Fredag morgen kl. 7 mødte professor Tournesol ind på laboratoriet, hvor han arbejdede. Bag arbejdsbordet med softice-centrifugen fandt han en stærkt blødende professor Lennardo. Lennardo var såret, og gerningsmanden var flygtet. Før Lennardo udåndede, nåede han at remse en hemmelig cifferkode op: 3,2,0,4,2,2,5,0,6,7,10,9,11,2,1,11,0,7,10,6,10,8,9,0,6,7,10,9,11,2,1,11. Og med sit livs sidste kræftanstrengelser pegede han mod skuffe 3, hvor et USB-medie lå gemt. I skuffen lå ligeledes en seddel med teksten: “Jeg har for en sikkerhedsskyld nullet programmet.”

    På USB-mediet fandt Tournesol et program, og programmet gemte på en besked(flaget), der kunne redde verdenen!

    Anvendt software: gdb

    Indledende tog jeg et kig på filen med file. En stripped 64-bit linux binær ELF(program) fil.

    Eksekverer vi filen får vi 32 “_” tegn printet til terminalen. Kigger vi på opgaveteksten ser vi, at der i den hemmelige cifferkode er 32 tal. Så allerede her kan vi begynde at gætte os til hvad programmet måske gør.

    Lad os starte programmet i GDB og eftersom vi ved, at programmet printer de 32 “_”‘er til skærmen kan vi jo sætte et catchpoint på netop dette syscall. Et printf syscall har under 64bit Linux nummeret “1”.

    Lidt om syscalls:

    Når et program skal eksekverer et syscall, f.eks. sys_write(printf) vil det før kaldet sætte visse CPU-registre op. F.eks. vil selve syscall nummeret(1) bliver flyttet til rax/eax via “mov eax, 0x1”. Hvilket output(stdout 1) bliver flyttet til rdi/edi via “mov edi, 0x1”, hvad der printes bliver sat i esi/rsi via “mov esi, msg”, osv.

    Når vi eksekverer programmet i GDB stopper det ved første catchpoint. Her kan vi se, at programmet vil printe “_” 32 gange(rsi/esi) til stdout(rdi/edi) og at syscall nummeret bliver sat med “mov eax,0x1”.

    Tager vi et kig i stacken ved vores catchpoint kan vi se noget data der ser lidt anderledes ud: “_L3WNDPRATEZ_L3WNDPRATEZ”.

    Vi kan ligeledes se et loop i assemblykoden før syscall. Så måske denne tekst skal køres op imod vores cifferkode? Hvis vi antager at programmet af ukendte årsager har placeret teksten to gange efter hinanden i stacken kan vi nøjes med halvdelen af teksten: “L3WNDPRATEZ”. I cifferkoden kan vi se tal mellem 0 og 11(12 forskellige) hvilket også er antallet af tegn i vores tekst i stacken. Så et “0” er lig med tekst[0] = “”, “1” bliver tekst[1]=”L”, osv.

    Med denne viden kan vi finde frem til flag: W3_N33D_PRETZ3LZ_REPEAT_PRETZ3LZ

  • Penetration testing jobs i Danmark

    Når man som jeg ønsker at få en fod indendørs i penetration testing branchen kan det godt være svært at danne et overblik over potentielle jobs. Jeg har derfor forsøgt at lave en liste over hvilke firmaer der til tider har haft jobopslag eller som jeg har hørt har/har haft stillinger indenfor penetration testing. Visse af firmaerne er jeg dog ikke 100% på. Jeg har forsøgt at udelukke de firmaer der har haft IT-sikkerhedsstillinger der har været blandet penetration testing og drift.

    Firma Firma type Annoncer(tidligere)
    Deloitte Konsulent/Revision 1
    PwC Konsulent/Revision Ikke længere online
    FE Militær Hackerakademi uddannelse+job i 2016/2017
    Improsec Pentestfirma/Konsulent 1
    CSIS IT-firma/Konsulent Ikke set online
    Zacco Konsulent/Revision/IP-Law 1
    F-secure AV/IT-firma/Konsulent 1
    SECU IT-firma/Konsulent Ikke set online
    Boutique Consultancy(?) Ukendt 1
    BDO Konsulent/Revision Ikke længere online
    NielcoIT Konsulent/IT-firma Ikke set online
    FortConsult Konsulent/IT-firma Ikke set online
    Dubex Konsulent/IT-firma Ikke set online
    KPMG Konsulent/Revision Ikke set online
    NetSection Security Konsulent/IT-firma Ikke set online
    Banshie Konsulent/IT-firma Ikke set online
    Langkjaer Cyber Defence Konsulent/IT-firma Ikke set online
    TDC Group Security ISP LinkedIn recruiters
    Prueba Cybersecurity Konsulent/IT-firma Ikke set online

    Smid mig en link eller PM på twitter hvis du mener der skal tilføjes noget til listen.

    Edits: FortConsult(4/4/18) / Dubex(20/4/18) / KPMG(24/4/18) / NetSection Security(25/4/18) / Banshie(15/5/18) / Langkjaer Cyber Defence(24/5/18) / TDC Group Security(6/2/19) / Prueba Cybersecurity(6/2/19)

  • OSCP-certificering, et par noter

    OSCP-certificeringen er en certificering i offensiv IT-sikkerhed, penetration testing, hacking, red team eller hvad man nu ellers vil kalde det. Certificeringen udbydes af Offensive Security, som også udgiver Kali Linux der er defacto standarden indenfor IT-sikkerhedsorienterede Linux Distributioner. Der findes ingen reelle alternativer til certificeringerne hos Offensive Security. Der findes dog SANS GPEN(hvis du vil spilde mange penge på noget dårligere) og CEH/Certified Ethical Hacker. Den sidste har jeg ikke den store tiltro til med dens multiple choice og manglende hands-on. Så hvorfor overhovedet spilde tiden med den?

    Update: 24/10-18 – Jeg har hørt gode ting om eLearnSecuritys certificeringer, især PTX. Så check dem ud.

    Offensive Security tilbyder også andre certificeringer, heriblandt OSCE(Offensive Security Certified Expert) og OSEE(Offensive Security Exploitation Expert). OSCE er skridtet op fra OSCP og fokuserer stort set udelukkende på debugging, fuzzing, BOF og udvikling af egne exploits. OSEE er endnu et skridt op ad stigen fra OSCE, er meget sjælden og skulle være særdeles svær.

    En OSCP-certificering består af to dele. PWK-netværket og selve OSCP-eksamen.

    PWK-lab: Et lukket netværk man tilgår via en VPN. Netværket består af omkring 55 boxes(med et par gengangere) spredt ud på 4 forskellige netværk: Public, IT, Admin og Developer. Alle boxe kan kompromitteres. Nogle af dem og IT/Admin/Developer-netværkene kan kun kompromitteres via andre boxe. Dette er netværkets største styrke og noget f.eks. HackTheBox.eu ikke har. Hvis man ønsker at forbedre sine chance til eksamen kan man udfærdige en rapport over mindst 10 af kompromiteringer fra PWK samt øvelserne fra PWK-bogen.

    OSCP-eksamen: Foregår over 2 x 24 timer. De første 24 timer får du adgang til et mindre antal boxe. Hver maskine har en kort beskrivelse med point angivelse. Indenfor de 24 timer skal man opnå så mange lowpriv- og root-shells at ens point antal kommer over 70 points. Når de 24 timer er gået mister man adgangen til netværket. Nye 24 timer starter så hvor man skal nå at skrive en rapport med dokumentation for sit arbejde. Ingen dokumentation = Ingen point.

    Ved start på PWK-perioden får man tilsendt PDF-bogen “Penetration Testing with Kali Linux” og en lang række videoer med samme øvelser som i bogen. Bogen er på små 400 sider og kan læses på 1-2 dage hvis man har lidt erfaring med pentesting. I bogen er ligeledes et stort antal øvelser som skal udføres og dokumenteres hvis man ønsker de førnævnte 5 ekstra point. Øvelserne tager 2-3 dage hvis man har lidt erfaring med pentesting(ved hvordan sql-injection, BOF osv. virker). Personligt så jeg aldrig selv videoerne.

    Gør dig selv en tjeneste. Go big med dine skærme. Alt andet er frustrerende.

    Gør dig selv en tjeneste. Go big med dine skærme. Alt andet er frustrerende.

    Når man tilmelder sig PWK+OSCP skal man vælge hvor lang tid man ønsker at træne på PWK-netværket. Jeg valgte selv den kortest mulige tid hvilket er 30 dage. På det pågældende tidspunkt lå jeg på en plads 36 på top28000 på pentesting/CTF-siden HackTheBox.eu. Jeg følte mig derfor klar fagligt. Jeg havde desuden 2 ugers restferie og 2 ugers afspadsering. Så i de 4 uger brugte jeg 12 timer om dagen stort set hver dag indtil det hang mig ud af halsen. Da de 30 dage var gået havde jeg root på omkring 90% af alle mål. Jeg valgte en dato for eksamen ca. 30 dage senere. Jeg troede jeg havde brug for tid til at samle mine noter og finpudse det sidste, men det var ikke så nødvendigt. Så godt råd: Sæt ikke eksamen for langt fra PWK-perioden, men mindre du slet ikke føler dig klar(forlæng i stedet for din PWK-adgang).

    Da dagen for eksamen kom var jeg klar. Indledende var der lidt en følelse af kaos: Hvilken af boxene skal man angribe først? Men efter 2 timer havde jeg lowpriv shell på et par boxe. Efter 12 timer og ca. kl. midnat havde jeg shell-adgang på samtlige boxe og nok point til at bestå med en god margin. Det blev fejret med 5 timers søvn. Næste morgen begyndte jeg på rapporten således den kunne sendes afsted sammen med PWK-rapporten kl. 12 på dag 2.

    Gode råd:

    → Træn hos HackThebox.eu. Se og tag noter til samtlige af Ippsecs vidoer.

    → Jeg valgte 30 dages PWK. 60 dage ville være mere passende, især hvis man ikke har mulighed for at studere på fuldtid.

    → Husk postexploit-enumeration på PWK-maskinerne ellers skal du roote dem igen.

    → Lokker en box med en nem angrebsvinkel uden at det virker, KAN det var et forsøg på at blænde dig fra en anden vinkel.

    → Træn Windows privesc + exploits.

    → Er du i tvivl om du er klar? Kig på din placering på HackTheBox. Er du i top100 er du også klar til at starte på PWK+OSCP.

    → Vær ikke bange for at bruge metasploit på PWK-netværket. Men prøv bagefter en manuel exploitation af samme box.

    → Nmap. Nmap. Nmap. Og Nmap med scripts.

    → Det er slet ikke så svært som mange gør det til. Med en fornuftig forberedelse går det rimeligt nemt.

    Next up! OSCE i 2018/2019. Og at finde et job.

  • NC3CTF2017 – Opgave 2 – Klikkety Klack

    Lavet af undertegnede

    Klokken var lidt i 5, da malware-artisten Freddie “Kvik” Sølv sad ved sin computer og lagde sidste hånd på sit mesterværk: en malware der skulle inficere samtlige af verdenens IoT-toastbrødristere og derved gøre morgenen virkelig nederen for alle. Pludselig blev døren sparket op, og politiets særlige brunchenhed myldrede ind og anholdte Freddie. På Freddies computer fandt politiet en særlig fil, der fik stor betydning for efterforskningen, der i sidste ende fik Freddie dømt til fængsel og grød uden sukker til at drysse på. Hvad viste denne fil, som var så vigtig for efterforskningen?

    Anvendt software: wireshark, netcat, objdump

    Indledende starter man med en pcap-fil der er en packet capture fil indeholdende data fra et USB-device.

    Ved at åbne filen i Wireshark kan man ved gennemgang af dataen se, at det stammer fra et USB-keyboard. Vi skal derfor prøve at genskabe hvad der er blevet indtastet. Der findes programmer og scripts der kan gøre dette, men lad gøre det manuelt.

    En dataframe fra et USB-keyboard er indrettet således, at de sidste 8 bytes indeholder den indtastede data. Nærmere bestemt vil den første byte angive en modifier tast, f.eks. ALT, CTRL, SHIFT, osv. Den tredje byte vil angive hvilken tast der er trykket. Hvis man f.eks. ser i denne c-kildekode vil man kunne se hvilke byteværdier der betyder hvilke taster. Så en dataframe bestående af: 00:00:09:00:00:00:00:00 vil betyde at “f”-tasten er anvendt. Derimod vil en dataframe bestående af: 02:00:09:00:00:00:00:00 betyde at “f”-tasten samt venstre shift er anvendt, så det giver “F”.

    For at få et bedre overblik kan man anvende t-shark til kun at vise de relevante dataframes(usb.capdata) fra filen. Herefter kan man enten gennemgå hver dataframe manuelt, eller man kan skrive et hurtigt og simpelt script, ala if “00:00:09” then f. Man skal huske at tage højde for BACKSPACE.

    Man vil således ende med tekststrengen: Jeg har lige testet min toastermalware og ingen antivirus detecterede den! Fedt man. Den har sha 256 42c3d3ba5c099106fc21ab53908495d5ef2ff9fcaa890b1c7ef4386bc0893f2f

    Da vi ved at vores anholdte har lavet en malware og at en sha256 værdi bliver nævnt, kunne vi jo tjekke om den anholdte har testet sin malware imod virustotal.com. Og det havde han! Under kommentarsiden kan man se, at brugeren “OpSecKing” nævner at malwaren sender teksten “HELLO” til en IP-adresse via port 9999.

    Så lad os sende teksten HELLO til IP-adressen. Dette kan man bl.a. gøre med netcat. Serveren svare tilbage med et link. Og ved besøg til siden får vi et link til et lille linuxprogram.

    Når programmet “g” bliver kørt spytter det en tekst ud samt et link. Dette link ændre sig dog hvert sekund og er ikke fortløbende. Med programmet objdump kan vi se hvilke library-calls programmet foretager sig. Af interessande calls er srand, time og rand. Disse funktioner gør følgende:

    srand: The C library function void srand(unsigned int seed) seeds the random number generator used by the function rand.

    rand: The C library function int rand(void) returns a pseudo-random number in the range of 0 to RAND_MAX.

    time: The C library function time_t time(time_t *seconds) returns the time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds. If seconds is not NULL, the return value is also stored in variable seconds.

    Så måske srand seeder rand’s random generator via time der henter den aktuelle unixtime ud? I programmet nævnes et tidspunkt som omsat til unixtime bliver 654052332. Hvad hvis vi kunne tvinge programmets time-call til at bruge dette tidspunkt? Heldigvis er det nemt.

    Med LD_PRELOAD tvinger vi vores program til at bruge andre libraries end de normale. Så hvis vi skaber en time funktion med ovenstående kode i C og kompilere den med følgende kommando: gcc -fpic -shared -o time.so time.c får vi et nyt library. Dette tvinger vi så programmet til at bruge med LD_PRELOAD hvorefter vi får et nyt link. Og besøge vi dette link får vi det korrekte flag.

  • HackTheBox.eu – Jail

    Created by n0decaf

    Software used: nmap, gdb, netcat

    As always, nmap first.

    One http-server running on the standard port, a NFS-server and one weird unknown service running on port 7411. Lets take a look at the http-server first.

    Running dirbuster against the http-server gave the folder “jailuser” and the subfolder “dev”. In this folder a binary, a shellscript and some C sourcecode was found. The shellscript compiled the sourcecode and ran it as a service. The sourcecode was the following:

    #include <stdio.h>
    #include <stdlib.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <unistd.h>
    #include <time.h>
    
    int debugmode;
    int handle(int sock);
    int auth(char *username, char *password);
    
    int auth(char *username, char *password) {
    	char userpass[16];
    	char *response;
    	if (debugmode == 1) {
    		printf("Debug: userpass buffer @ %p\n", userpass);
    		fflush(stdout);
    	}
    	if (strcmp(username, "admin") != 0) return 0;
    	strcpy(userpass, password);
    	if (strcmp(userpass, "1974jailbreak!") == 0) {
    		return 1;
    	} else {
    		printf("Incorrect username and/or password.\n");
    		return 0;
    	}
    	return 0;
    }
    
    int handle(int sock) {
    int n;
    int gotuser = 0;
    int gotpass = 0;
    char buffer[1024];
    char strchr[2] = "\n\x00";
    char *token;
    char username[256];
    char password[256];
    debugmode = 0;
    memset(buffer, 0, 256);
    dup2(sock, STDOUT_FILENO);
    dup2(sock, STDERR_FILENO);
    printf("OK Ready. Send USER command.\n");
    fflush(stdout);
    
    while(1) {
    	n = read(sock, buffer, 1024);
    	if (n < 0) {
    		perror("ERROR reading from socket");
    	return 0;
    	}
    	token = strtok(buffer, strchr);
    	while (token != NULL) {
    		if (gotuser == 1 && gotpass == 1) {
    		break;
    	}
    	if (strncmp(token, "USER ", 5) == 0) {
    		strncpy(username, token+5, sizeof(username));
    		gotuser=1;
    		if (gotpass == 0) {
    			printf("OK Send PASS command.\n");
    			fflush(stdout);
    		}
    	} else if (strncmp(token, "PASS ", 5) == 0) {
    		strncpy(password, token+5, sizeof(password));
    		gotpass=1;
    		if (gotuser == 0) {
    			printf("OK Send USER command.\n");
    			fflush(stdout);
    		}
    	} else if (strncmp(token, "DEBUG", 5) == 0) {
    		if (debugmode == 0) {
    			debugmode = 1;
    			printf("OK DEBUG mode on.\n");
    			fflush(stdout);
    		} else if (debugmode == 1) {
    			debugmode = 0;
    			printf("OK DEBUG mode off.\n");
    			fflush(stdout);
    		}
    	}
    	token = strtok(NULL, strchr);
    }
    if (gotuser == 1 && gotpass == 1) {
    break;
    }
    }
    if (auth(username, password)) {
    printf("OK Authentication success. Send command.\n");
    fflush(stdout);
    n = read(sock, buffer, 1024);
    if (n < 0) {
    perror("Socket read error");
    return 0;
    }
    if (strncmp(buffer, "OPEN", 4) == 0) {
    printf("OK Jail doors opened.");
    fflush(stdout);
    } else if (strncmp(buffer, "CLOSE", 5) == 0) {
    printf("OK Jail doors closed.");
    fflush(stdout);
    } else {
    printf("ERR Invalid command.\n");
    fflush(stdout);
    return 1;
    }
    } else {
    printf("ERR Authentication failed.\n");
    fflush(stdout);
    return 0;
    }
    return 0;
    }
    
    int main(int argc, char *argv[]) {
    int sockfd;
    int newsockfd;
    int port;
    int clientlen;
    char buffer[256];
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int n;
    int pid;
    int sockyes;
    sockyes = 1;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
    perror("Socket error");
    exit(1);
    }
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockyes, sizeof(int)) == -1) {
    perror("Setsockopt error");
    exit(1);
    }
    memset((char*)&server_addr, 0, sizeof(server_addr));
    port = 7411;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);
    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
    perror("Bind error");
    exit(1);
    }
    listen(sockfd, 200);
    clientlen = sizeof(client_addr);
    while (1) {
    newsockfd = accept(sockfd, (struct sockaddr*)&client_addr, &clientlen);
    if (newsockfd < 0) {
    perror("Accept error");
    exit(1);
    }
    pid = fork();
    if (pid < 0) {
    perror("Fork error");
    exit(1);
    }
    if (pid == 0) {
    close(sockfd);
    exit(handle(newsockfd));
    } else {
    close(newsockfd);
    }
    }
    }

    Looking at the code, the code at line 21 seem vulnable to buffer overflow since there was no boundary checks.

    Check the filetypes showed that the binary was compiled on a 32bit machine.

    Connecting to the service showed the userpass buffer location at 0xffffd610. This leak of information was enough to write the following exploit using pwntools.

    The exploit in python. A padding of 28 chars was choosen and the EIP-address was set to 0xffffd638. A NOP-slide of 100 to ensure a reasonable big margin to hit. I tested a lot of different shellcodes that didn’t work, but after some help I was provided with a working one, which were a reuse-socket shellcode.

    Running the exploit gave me a shell as the user “nobody”. Browsering around showed, that a user called “frank” had the only userdirectory in /home.

    Browsering around som more I found two interesting folders with interesting user rights in /var. /var/adm owned by the user adm and /var/nfsshare owned by frank. The nfsshare folder I remembered from looking at the NFS-service. NFS is an old technology that in some situation has some massive security flaws. Since the user frank on Jail is uid 1000, I can create a user on my workstation with same uid, mount the share and write to the folder as frank. This will create a opportunity to upload a binary to /var/nfsshare, give that file setuid rights for all users(including “nobody”). This can potentially give any user the same rights as frank.

    First I mounted the nfsshare folder to a local folder.

    To retrieve the user-flag I created a small program in C which changed its effective setuid to 1000(frank) and then read and printed the user-flag file. I then compiled it with gcc user.c -o user

    Afterwards I created the user frank which automatically were given a uid of 1000. I could then copy my program(user) to the mounted folder as frank. Furthermore I gave setuid rights for all users so the user “nobody” could run the program as the user frank.

    Running it gave me the user flag! But to go further we need to escalate from “nobody” to frank. One way is to write my publickey for ssh to /home/frank.ssh/authorized_keys

    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdlib.h>
    int main()
    {
    	remove("/home/frank/.ssh/authorized_keys");
    	char str[500] = "the public key";
    	FILE *fptr;
    	fptr = fopen("/home/frank/.ssh/authorized_keys", "w");
    	fprintf(fptr,"%s", str);
    	fclose(fptr);
    	return 0;
    }

    I wrote the above program in C and again uploaded it to /var/nfsshare, set permissions and executed it with “nobody”.

    And then there were no problems ssh’ing directly to Jail as frank.

    Checking for sudo rights for the user frank I saw that he is allowed to run rvim(a restricted version of Vim) as the user adm. I then remembered that the folder /var/adm was owned by adm. Could be interesting to use vim/rvim’s filebrowser to view the files in that folder.

    Running sudo -u adm /usr/bin/rvim /var/www/html/jailuser/dev/jail.c and then using the builtin filebrowser with :e /var/adm/ gave me access to the folder as the user “adm”. In the folder the files keys.rar(password protected, saved by opening it and typing :w /tmp/keys.rar), the textfile note.txt and in the folder “.local” another textfile called “.frank” was found.

    “note.txt” contained a short description.

    In the /var/adm/.keys/.local/ there file “.frank” was found. It contained what looked like a simple substition cipher which could be solved by using quipqiup.com. So I ended up with the following sentence: “Hahaha! Nobody will quess my new password! Only a few lucky souls have Escaped from Alcatraz alive like I did!!”

    Since I visited Alcatraz a couple of months ago the first part, “Morris”, of the password was easy to guess. I could have bruteforced the rest, but a single guess got as “Morris1962!”. Using that with unrar extracted a public RSA-key.

    Looking at the publickey showed that it was pretty short and therefore maybe could be cracked using rsactftool. And that turned out to be true. So by rsactftool I was able to create a private key and use it to login as root and grab the root flag. Finally!