You are hereOpenVPN
OpenVPN
TunnelDroid
Some long time ago I made a call for help to get OpenVPN working on the Android platform. There were two places where work had to be done: porting openvpn and writing a GUI enabling you to start/stop/interact with tunnels.
It took some time but finally someone made the necessary patches to get openvpn running. It was then time for me to get into action and continue the work on a GUI wrapper.
The first releases supported only hardcoded usernames and passwords, but I finally released a new version supporting authentication prompts. If you want to install it simply search for TunnelDroid on the Market.
On the technical part this is how the app is structured:
- Main GUI Intent listing the configurations
- Second Intent to edit the configurations
- Service managing the openvpn binaries and the tunnel-inteligence
- Thread to stop openvpn after a timeout, this is necessary as otherwise openvpn will not stop try connecting
- Thread to interact with openvpn using a network socket and the openvpn management interface
- Intent displaying the connection logfile, logfile can be emailed by a simple click
- Status Bar Notification when the tunnel is up
Of course the code is released as open source and can be found on sourceforge.
Below you can see some screenshots.
Watchguard Fireware SSL-VPN Vulnerability
I talked a few times about this issue, but unfortunately I didn't get a response to my CVE number request. So here's the full thing:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Security Advisory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Severity: High
Title: Watchguard Fireware SSL-VPN MiTM Multiple Vulnerabilities
Date: November 29, 2008
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Project: WatchGuard Firewall SSL-VPN
* Version affected:
WatchGuard Fireware 10.0 up to 10.2.2
WatchGuard Mobile VPN with SSL 10.0 for Macintosh
WatchGuard Mobile VPN with SSL 10.0.2 for Macintosh
WatchGuard Mobile VPN with SSL 10.0 for Windows
* Discovered: April 06, 2008
* Reported : April 08, 2008
* Fixed : October 07, 2008 (only for Windows)
* Advisory : November 29, 2008
* Not Fixed : Mobile VPN with SSL for Macintosh
* Security risk: High Severity
* Vulnerability: MiTM Multiple Vulnerabilities with Abritrary Code Execution
* Discovered by: Christophe Vandeplas <christophe@vandeplas.com>
-------- SHORT DESCRIPTION --------
Due to bad design of the 'WatchGuard Mobile VPN with SSL Client'
it is vulnerable to a MiTM attack resulting in multiple consequences:
- Username and password gathering
- OpenVPN configuration poisoning
- Upload of malware on the victims machine
- Redirection to another VPN server
- Full transparent MiTM for the complete VPN tunnel
- Arbitrary code execution on the victims machine
This vulnerability should be classed as high severity.
-------- REMEDIATION --------
For Windows computers update ASAP your software.
Stop using the software on Macintosh computers until Watchguard
releases a fixed Macintosh version of the client.
-------- FULL DESCRIPTION --------
-- [ How the Watchguard Fireware SSL-VPN Works
The Watchguard SSL-VPN system consists of four parts:
- OpenVPN Client
- WatchGuard Mobile VPN with SSL GUI Client (or Watchguard GUI Client)
- OpenVPN Server
- Webserver where the client-configuration resides (port 4100)
The OpenVPN Client and Server take care of the full VPN tunnel. As
authentication the 'auth-user-pass', 'server-certificate' and
'client-cert' mechanisms are used. These are good security practices.
The Watchguard GUI takes care of two different tasks. It takes care
as management interface for entering the OpenVPN credentials and it
downloads the client configuration from the webserver on port 4100.
The webserver for the client-configuration runs on port 4100 and
uses SSL for encryption. The certificate is self signed.
-- [ The Flow:
The Watchguard GUI Client needs the Firebox IP, username and
password. When the user clicks on 'connect' the GUI Client connects
on the webserver on ip:4100 using SSL encryption where it downloads
the 'client.wgssl' file with the following HTTP GET:
GET /?action=sslvpn_download&username=testuser&password=testpass&filename=client.wgssl
A file called 'client.wgssl' is then downloaded on the machine.
This file is a TGZ and contains the following files:
MD5SUM - Checksums of the different files from the wgssl package
VERSION - File with version info from Watchguard
ca.crt - Certificate authority public key
client.crt - Client public key
client.ovpn - OpenVPN configuration file
client.pem - Private key for the client
The Watchguard GUI Client extracts the files and then starts up
OpenVPN with this configuration.
OpenVPN then takes care of setting up the VPN tunnel. When the
username and password are required it communicates with the
Watchguard GUI Client using the OpenVPN management interface.
The VPN tunnel is started.
-- [ The problem:
The problem resides in the way GUI Client downloads the configuration.
The webserver:4100 works with a self-signed certificate. The
validity of this certificate is never checked correctly.
The Client GUI does check the strings in the following fields:
Common Name (CN) = Fireware Web Server
Organization (O) = Watchguard
Organizational Unit (OU) = Fireware
These checks are insufficient. A full certificate check should be
performed using either the manually imported certificate before
connection or using an imported CA-cert.
This results in:
1) Anyone can generate a certificate with these values. An attacker
could run a webserver and impersonate the original SSL-VPN server.
2) The password is stored in clear-text in the GET method.
3) The checks on the content of the client.wgssl are almost nihil.
It is possible to completely replace the existing client
configuration and to add extra files in the configuration
directory of the client machine.
4) It is possible to redirect the client to another VPN server. As
we have complete control the full VPN tunnel could be MiTM-ed
without the user noticing this.
5) Combined with the 'up cmd' option of the OpenVPN configuration file
arbitrary code could be executed on the victims machine.
-------- PROOF OF CONCEPT --------
--[ Main Setup
Take an original 'client.wgssl' file, rename it to 'client.wgssl.tgz'
and extract it.
Change the 'remote' value to another IP (1.1.1.1) in the
'client.ovpn' file and recalculate the checksum.
Copy a 'malware.exe' in the same diractory. (this could be
childporn or a virus)
Compress all files again in a new .tgz package with the right
filename.
An Apache webserver has been configured to run on port 4100 using
the SSLEngine.
The SSL certificate was generated with the following values:
Common Name (CN) = Fireware Web Server
Organization (O) = Watchguard
Organizational Unit (OU) = Fireware
In the webroot of the webserver we uploaded a small script that
saves the parametes into a database and returns a client.wgssl file
as datastream.
-- [ Connect
Now open the Watchguard GUI Client and connect to the IP of the
webserver. (192.168.1.110)
The Client downloads the new 'client.wgssl' file and extracts it.
-- [ Results:
1) The Watchguard GUI accepts the fake certificate
2) When checking the logfile we see a successful download of
the configuration file:
192.168.1.120 - - [08/Apr/2008:19:06:14 +0200] "GET /?action=sslvpn_download&username=testuser&password=testpass&filename=client.wgssl HTTP/1.1" 200 12 "-" "-"
These usernames and passwords could be stored in a database using
a php script. (see PHP Sample Script)
3a) The client configuration is completely rewritten with our own
configuration file.
3b) Check the Watchguard GUI Client directory for the 'malware.exe'
file.
4a) Check the logging, you will notice that the client doesn't
connect to 192.168.1.110 but to 1.1.1.1
4b) Out of scope of this POC
5) Out of scope of this POC
-------- Technical SOLUTIONS for Watchguard --------
The WatchGuard Mobile VPN with SSL Client should correctly check the
validity of the SSL Certificate using the well-defined standards when
connecting to the configuration-website on port 4100.
The Watchguard firewall should enable the user to generate and upload
certificates and to link these certificates to the webservers.
An even better solution would be to run both OpenVPN and the
configuration-website on the same port and use the same certificates.
OpenVPN starting from version 2.1 supports a feature called
port-sharing where OpenVPN can share a port with a webserver or
other service.
-------- PHP Sample Script --------
<?php
// Do whatever we want with the variables
$user=$_GET['username'];
$pass=$_GET['password'];
// Return the client.wgssl configuration file
header("Content-Type: application/octet-stream");
header("content-disposition: attachment; filename=\"client.wgssl\"");
$file=file_get_contents("client.wgssl");
echo $file;
?>
-------- LINKS --------
- Watchguard Release Notes
https://www.watchguard.com/Download/Files/WSM/10_2_3/EN_ReleaseNotes_WSM...
- OpenVPN 2.1 Manual
http://openvpn.net/index.php/documentation/manuals/openvpn-21.html
Watchguard Fireware SSL-VPN Vulnerability
Six months ago I discovered a huge vulnerability in the Watchguard SSL-VPN implementation. The consequences are quite important as, if exploited correctly, it is possible to perform arbitrary code execution on the victims machine.
For six months now I've been in contact with 'someone' from the Watchguard security team. He has promised me many times a date when the fix will be released. I'm still waiting for it...
In his last mail he said the fix was committed to the beta-team and I was going to be added to the beta-testers-list so I could try it out and play around with it. I'm still waiting to be added...
- I informed them privately of two important vulnerabilities.
- I accepted to keep the details about the fixed problem confidential as courtesy.
- I keep waiting for 6 months with many beautiful promises about a fix and access to the beta.
- I don't ask any money for these reports.
For ethical reasons I will not publish the full disclosure without the fix. But next time I find a leak in their products I might start thinking about selling it to the highest bidder.
PS: This is not related to this other problem that has already been fixed.
Edit: Mark told me another way, that gives less a blackmailing-feeling. It's kindly requesting the company to make a donation to a charity before giving them the information about the vulnerability in private. I think I'll do that next time.
Edit 2: Watchguard released a new version v10.2.3 fixing this huge problem. Quote Release Notes: The Mobile VPN with SSL client and gateway now protect against "Man in the Middle" attacks. The Mobile VPN with SSL gateway generates a self-signed x.509 certificate when an IP address is assigned to the external interface of the Firebox. This certificate is presented by the gateway the first time a v10.2.3 client connects. Because the certificate is self-signed, a warning message about an “un-trusted” certificate is presented to the user the first time they connect to the Firebox. The user is given the option to confirm the certificate as trusted and save the certificate locally. Accepting the certificate as “trusted” allows the SSL client to warn the user if the certificate changes to alert the user of a possible Man in the Middle attack. [27304].
Port-sharing with OpenVPN
Just a short note to wake up people and tell them they can run OpenVPN on the same port as their Apache webserver.
Yes yes yes, this is possible thanks to the so called port sharing feature of OpenVPN 2.1. But not many people know about this great feature. It's time to promote it a little !
--port-share host port When run in TCP server mode, share the OpenVPN port with another application, such as an HTTPS server. If OpenVPN senses a connection to its port which is using a non-OpenVPN protocol, it will proxy the connection to the server at host:port. Currently only designed to work with HTTP/HTTPS, though it would be theoretically possible to extend to other protocols such as ssh. Not implemented on Windows.
OpenVPN with dynamic pkcs#11 ID.
You might have read my two posts concerning Belgian eID authentication with OpenVPN. ([1] and [2] .
There was a thing that bothered me: The pkcs11-id (eg: "Axalto/Belgium eID/6CFF2491AB111E14/BELPIC (Basic PIN)/02") that is hardcoded in the configuration file. To solve this issue I wrote a patch for OpenVPN (v2.1_rc7).
In short this is what I do:
- New pkcs11-match variable in the openvpn.conf. This is the substring of
the key-id you want to match. It works with a 'first match wins' principle.
- options.c => I add the variable and the checks, as it's either
pkcs11-id or pkcs11-match
- ssl.c => if pkcs11_match is set, do the checks and give error if
necessary. Store the key-id in options->pkcs11_id.
- pkcs11.c => I copy-pasted some code of the find-pkcs11-ids(),
refactored it and added a check for the substring.
This enables people to:
- deploy the same configuration on different computers
- log-in to the tunnel with different cards on the same machine.
(different users that share the same computer)
With eID's the key-id contains similar characteristics.
where 'BELPIC\x20\x28Basic\x20PIN\x29/02' is the end of the
Authentication key.
Unfortunately some don't see the advantage of including this in the tree as the cvs/svn already contains code for certificate selection. But this certificate selection needs an extra UI (graphical or whatever).
Database authorization for openVPN with eID
In my previous post I explained how to use your Belgian eID to login on your openVPN server.
I did use a simple hello-world script to check the authorization. The username (rijksregisternummer/numero du registre national) was hardcoded in a file.
This evening I finally quickly enhanced the script do perform database authorization:
Download the full script. Or see the relevant database part:if ($x509 =~ /\/serialNumber=([^\/]+)/) {
# Accept the connection if the X509 common name
# string matches the passed cn argument.
my $dbh = DBI->connect('DBI:mysql:sslvpn', 'sslvpn', 'sslvpn')
or die "Couldn't connect to database: " . DBI->errstr;
my $sth = $dbh->prepare("SELECT `id`, `name`, `firstname` FROM `users` WHERE id=$1")
or die "Couldn't prepare statement: " . $dbh->errstr;
my @data;
$sth->execute()
or die "Couldn't execute statement: " . $sth->errstr;
# Read the matching records and print them out
while (@data = $sth->fetchrow_array()) {
$id = $data[0];
$name = $data[1];
$firstname = $data[2];
#print "Database result: \t$id: $firstname $name\n";
}
# Authentication failed -- Either we could not parse
# the X509 subject string, or the common name in the
# subject string didn't match the passed cn argument.
if ($sth->rows == 0) {
print "TLS-VERIFY: EE - Unknown user: $x509\n";
$result=1;
}
# Authentication is OK
else {
print "TLS-VERIFY: OK - $id - '$firstname $name' logged in\n";
$result=0;
}
$sth->finish;
$dbh->disconnect;
}
The database:
CREATE TABLE `users` (
`id` varchar(11) NOT NULL,
`name` varchar(255) NOT NULL,
`firstname` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`),
KEY `id_2` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `users` (`id`, `name`, `firstname`) VALUES
('83021811535', 'Vandeplas', 'Christophe');
OpenVPN with Belgian eID
Edit: I added database authentication. Details see: here.
Some time ago Nicolas told us he played with the Belgian eID. In the past I also hacked the belpic code to compile it under Gentoo, but since I have my Mac I haven't really played with it except to use it as an online-auth for the Gov-sites.
For some weeks now I enabled SSL-VPN on my server using SSL Certificates with a self-signed authority. But just like Nicolas says :"Pretty cool stuff, if this'd work... Both VPN and SSH authentication will be done using my eID if this turns out well.".
So the plan is:
- Make a VPN tunnel using OpenVPN
- Identify my server using a certificate (self-signed or a CAcert one.)
- Identify the user using certificates from the Belgian eID / Digital Identity Card
- Authorize users based on their rijksregister-nummer/numéro de registre national
- Check the validity of the card using CRL or OCSP
The client will need OpenVPN 2.1 (still in RC atm). The server seems to work with the latest stable release (2.0.6 on my system).
Installing eID drivers
There are plenty of manuals to do this, or if you use a distro like ubuntu/debian/openSUSE/... there should be packages for it. For MacOS X there is an installer and this manual if you want to use it to logon on your system.
Just to be sure it works. You can check what keys are on your card with the pkcs15-tool --dump command.
Notice that we have two private keys. One for Authentication and one as Signature. You are not authorized (neverExtract) to download the private key from the card.
Private RSA Key [Authentication]
Usage : [0x4], sign
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
Private RSA Key [Signature]
Usage : [0x200], nonRepudiation
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
Extract info from the card
With the command openvpn --show-pkcs11-ids provider you can see the DN and serial of your keys. This info will be used later.
The provider is the shared library you get when compiling the beid driver. On a linux system it's a .so file, on a mac a .dylib and probably a .dll on Windows.
If you don't know where it is, check the 'Security Devices' of your Firefox as it might already be used there.
$ openvpn --show-pkcs11-ids /usr/local/lib/beid-pkcs11.bundle/Contents/MacOS/libbeidpkcs11.2.1.0.dylib
The following objects are available for use.
Each object shown below may be used as parameter to
--pkcs11-id option please remember to use single quote mark.
Certificate
DN: /C=BE/CN=Christophe Vandeplas (Authentication)/SN=Vandeplas/
GN=Christophe Marie-Luc/serialNumber=83021811535
Serial: 1000000000006F3CBE8C921BC713F8FD
Serialized id: Axalto/Belgium\x20eID/6CFF2491AB111E14/BELPIC\x20\x28Basic\x20PIN\x29/02
Certificate
DN: /C=BE/CN=Christophe Vandeplas (Signature)/SN=Vandeplas/
GN=Christophe Marie-Luc/serialNumber=83021811535
Serial: 1000000000005A011FBE437FC4363A3D
Serialized id: Axalto/Belgium\x20eID/6CFF2491AB111E14/BELPIC\x20\x28Basic\x20PIN\x29/03
Take the Serialized id from the Authentication certificate. (bold)
This ID will be used to tell OpenVPN what key he should read. But there is a small thing, you must replace all \x20 to a space the \x28 to a ( and \x29 to ).
The result is something like this: pkcs11-id "Axalto/Belgium eID/6CFF2491AB111E14/BELPIC (Basic PIN)/02"
The last things we must extract are the certificates of the Belgian government.
The command pkcs15-tool --list-certificates lists the certificates present on the smartcard. Two fields require our attention (bold):
- X.509 Certificate [CA]: The certificate authority that signed our key
- X.509 Certificate [Root]: The root certificate
$ pkcs15-tool --list-certificates
X.509 Certificate [Authentication]
Flags : 3
Authority: no
Path : 3f00df005038
ID : 02
X.509 Certificate [Signature]
Flags : 3
Authority: no
Path : 3f00df005039
ID : 03
X.509 Certificate [CA]
Flags : 3
Authority: yes
Path : 3f00df00503a
ID : 04
X.509 Certificate [Root]
Flags : 3
Authority: yes
Path : 3f00df00503b
ID : 06
We write down the IDs of both certificates: 04 and 05. These numbers are used to export the certificates to a pem file.
$ pkcs15-tool --read-certificate 04 > belgium.crt $ pkcs15-tool --read-certificate 06 >> belgium.crt
Current client/server configuration
Complete configurations with comments at the end of this article.client dev tun proto udp remote myserver.org 1194 resolv-retry infinite nobind user nobody group nobody persist-key persist-tun pkcs11-providers /usr/local/lib/beid-pkcs11.bundle/Contents/MacOS/libbeidpkcs11.2.1.0.dylib pkcs11-id "Axalto/Belgium eID/6CFF2491AB111E14/BELPIC (Basic PIN)/02" ca ca.crt ns-cert-type server comp-lzo verb 3
The ca.crt file contains the certificate of the Certificate Authority that signed the key of my server.
The server configuration:
port 1194 proto udp dev tun cert server.crt key server.key ca belgium.crt #tls-verify /etc/openvpn/auth-eid-check # TODO uncomment this later dh dh1024.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway" keepalive 10 120 comp-lzo user nobody group nogroup persist-key persist-tun status openvpn-status.log log openvpn.log verb 4 mute 20
Establishing the connection:
Server: /etc/init.d/openvpn start and client: openvpn --config openvpn.conf
I first didn't export both certificates in the same file (belgium.crt) and got the following error in my server logs:
Sun Feb 3 12:34:26 2008 us=556133 62.235.210.17:50545 VERIFY ERROR: depth=0, error=unable to get local issuer certificate: /C=BE/CN=Christophe_Vandeplas__Authentication_/SN=Vandeplas/GN=Christophe_ Marie-Luc/serialNumber=83021811535 Sun Feb 3 12:34:26 2008 us=556290 62.235.210.17:50545 TLS_ERROR: BIO read tls_read_plaintext error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned
A working situation should show:
Sun Feb 3 12:45:31 2008 us=101863 62.235.210.17:50609 VERIFY OK: depth=2, /C=BE/CN=Belgium_Root_CA Sun Feb 3 12:45:31 2008 us=102526 62.235.210.17:50609 VERIFY OK: depth=1, /C=BE/CN=Citizen_CA Sun Feb 3 12:45:31 2008 us=103299 62.235.210.17:50609 VERIFY OK: depth=0, /C=BE/CN=Christophe_ Vandeplas__Authentication_/SN=Vandeplas/GN=Christophe_Marie-Luc/serialNumber=83021811535 ... Sun Feb 3 12:45:33 2008 us=834295 62.235.210.17:50609 [Christophe_Vandeplas__Authentication_] Peer Connection Initiated with 62.235.210.17:50609 Sun Feb 3 12:45:33 2008 us=834410 Christophe_Vandeplas__Authentication_/62.235.210.17:50609 MULTI: Learn: 10.8.0.10 -> Christophe_Vandeplas__Authentication_/62.235.210.17:50609 Sun Feb 3 12:45:33 2008 us=834445 Christophe_Vandeplas__Authentication_/62.235.210.17:50609 MULTI: primary virtual IP for Christophe_Vandeplas__Authentication_/62.235.210.17:50609: 10.8.0.10
This works ! Yess.. This means everyone with an eID can login on the VPN.. hmm.. probably not something I/you want.
Authorization
The authentication part works fine. We are fully certain that the certificate is valid but everyone with an eID can login. Time to implement a little authorization. Isn't it?
Remember this line? tls-verify /etc/openvpn/auth-eid-check. Uncomment it.
When the authentication has been performed (but before the CRL check) the authorization is done by running the following script.
This script gets 2 parameters and should exit 0 if OK and exit 1 if unauthorized.
You should probably do some database-checking or put keys in an or secure file.
- The depth of the certificate-chain: 0 -> X
- The CommonName :
/C=BE/CN=Christophe Vandeplas (Authentication)/SN=Vandeplas/GN=Christophe Marie-Luc/serialNumber=83021811535
#!/usr/bin/perl
die "usage: auth-eid-check certificate_depth X509_NAME_oneline" if (@ARGV != 2);
($depth, $x509) = @ARGV;
$cn="83021811535"; # the key that is allowed
if ($depth == 0) { # only check the final/client certificate
if ($x509 =~ /\/serialNumber=([^\/]+)/) {
# check here the validity of the serialNumber, or something else
if ($cn eq $1) {
exit 0;
}
}
exit 1; # invalid user, should not be able to login
}
exit 0;
Validity of the certificate - CRL & OCSP
It looks like OCSP is not supported in OpenVPN. Even in 2005 people were asking for it, but I can't find a thing in the manuals or the internet.
You can try to use the CRL of Belgium. But the problem is this database is soooo big it's almost unusable. I didn't try it but it should work by adding the following lines in your server.conf configuration file.
crl-verify http://crl.eid.belgium.be/belgium.crl
Docs I used
http://openvpn.net/howto.html#pkcs11
http://openvpn.net/man-beta.html
http://michele.pupazzo.org/docs/smart-cards-openvpn.html
http://christophe.vandeplas.com/2008/02/08/database-authorization-openvpn-eid
Full configfiles
- Client configuration: openvpn.conf
- Server configuration: server.conf
- Authorization script (basic): auth-eid-check
- Authorization script (database): auth-eid-check.db and Info about the script and database structure.




