Bug 1385286 - OpenConnect appears to bypass CA Certificate checks in some cases
Summary: OpenConnect appears to bypass CA Certificate checks in some cases
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: NetworkManager-openconnect
Version: 25
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: David Woodhouse
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-10-15 21:37 UTC by Volker Sobek
Modified: 2016-12-14 11:56 UTC (History)
4 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2016-12-14 11:56:16 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Volker Sobek 2016-10-15 21:37:54 UTC
Description of problem:

Connecting to VPN continues despite failure in server certificate verification.

Version-Release number of selected component (if applicable):
openconnect-7.07-2.fc25.x86_64
NetworkManager-openconnect-1.2.3-0.20160606git5009f9.fc25.x86_64
NetworkManager-openconnect-gnome-1.2.3-0.20160606git5009f9.fc25.x86_64


How reproducible:
Always


Steps to Reproduce:
1. Connect to an openconnect VPN configured from gnome-control-center with a given .pem certificate file
2. Look at the journalctl log
3. You will see something like:
Oct 15 22:37:56 hp openconnect[5171]: Connected to xxx.xxx.xxx.xxx
Oct 15 22:37:56 hp openconnect[5171]: SSL negotiation with xxx.xxx.xxx.xxx
Oct 15 22:37:56 hp openconnect[5171]: Server certificate verify failed: signer not found
Oct 15 22:37:56 hp openconnect[5171]: Connected to HTTPS on xxx.xxx.xxx.xxx
Oct 15 22:37:56 hp openconnect[5171]: Got CONNECT response: HTTP/1.1 200 OK
Oct 15 22:37:56 hp openconnect[5171]: CSTP connected. DPD 30, Keepalive 20
Oct 15 22:37:56 hp openconnect[5171]: Connected as xxx.xxx.xxx.xxx, using SSL
Oct 15 22:37:56 hp openconnect[5171]: Established DTLS connection (using GnuTLS). Ciphersuite (DTLS0.9)-(RSA)-(AES-256-CBC)-(SHA1).

Actual results:
The connection succeeds, even though the certificate has not been verified.

Expected results:
The connection should not be established and the user should be informed if certificate verification failed.


Additional info:
$ ps ax|grep [o]penconnect
 6178 ?        Sl     0:00 /usr/libexec/nm-openconnect-service --bus-name org.freedesktop.NetworkManager.openconnect.Connection_4
 6197 ?        S      0:00 /usr/sbin/openconnect --servercert sha1:05d2d0a805bc00f88e7de9f011b3ad99cab3d1ae --syslog --cookie-on-stdin --script /usr/libexec/nm-openconnect-service-openconnect-helper --interface vpn0 xxx.xxx.xxx.xxx:443

Comment 1 Volker Sobek 2016-10-15 21:49:43 UTC
To be more specific, the certificate file I set was the 'CA Certificate' option in the VPN openconnect creation dialog. I only set the gateway and the Certificate. The rest was unset/default values. Here is the NM system-connections file:

[connection]
id=xxx extern
uuid=0b3e5dd4-bfff-4ec6-8104-38d9602ecc57
type=vpn
autoconnect=false
permissions=user:weld:;
secondaries=
timestamp=1476390878

[vpn]
authtype=password
autoconnect-flags=0
cacert=/home/xxx/Downloads/deutsche-telekom-root-ca-2.pem
certsigs-flags=0
cookie-flags=2
enable_csd_trojan=no
gateway=xxx.de
gateway-flags=2
gwcert-flags=2
lasthost-flags=0
pem_passphrase_fsid=no
stoken_source=disabled
xmlconfig-flags=0
service-type=org.freedesktop.NetworkManager.openconnect

[vpn-secrets]
form:main:username=xxx
lasthost=xxx.de
save_passwords=yes

[ipv4]
dns-search=
method=auto

[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto

Comment 2 David Woodhouse 2016-10-15 21:58:28 UTC
OpenConnect works in two phases — first there's the authentication, which runs in the user's session and uses any client certificates, interacts with the user (and/or password agent) for filling in the auth forms, *and* prompts the user for permission to accept any invalid certificates.

If the user *does* accept an invalid certificate, that'll be remembered and the user won't be prompted again. (Perhaps it *should* show a warning every time in future?)

Once we're talking to the final server (after and load-balancing redirects, etc.), we go to the second phase. This is spawned from the NetworkManager service, and runs as a separate (unprivileged) user. It can no longer *ask* the real meat user for permission to accept certificates. 

But that's OK, one of the pieces of information we pass into the second phase is the hash of the *actual* certificate that was presented by that final server we were talking to in the authentication phase. That's what the --servercert argument is, on the command line you shows.

The point in the --servercert option is to allow only that one certificate and no other — the normal trusted CAs are irrelevant. So what it does in the openconnect application is *remove* all the system trusted CAs before trying to establish the connection. That makes *sure* it gets a callback to validate the cert... and it compares it with the one that was specified.

So you will *always* see that 'signer not found' message in the logs, even for certificates which are entirely valid. But that in itself isn't a problem.

If the certificate really *is* invalid, you should have been prompted during the authentication phase (when the NM auth-dialog popped up) to accept it. (And remember, that acceptance is stored for future connections, so you might not have been asked *today*).

Comment 3 Volker Sobek 2016-10-15 22:46:12 UTC
Thank you for your fast response. So I created a new connection (to the same server) using a .pem file which I changed one character, to see if it would made it fail. Here is the new connection:

# cat /etc/NetworkManager/system-connections/openconnect-test 
[connection]
id=openconnect-test
uuid=6d172f03-f445-4d36-b061-a75aa112124f
type=vpn
autoconnect=false
permissions=user:weld:;
secondaries=

[vpn]
authtype=password
autoconnect-flags=0
cacert=/home/weld/Downloads/deutsche-telekom-root-ca-2.with-error.pem
certsigs-flags=0
cookie-flags=2
enable_csd_trojan=no
gateway=xxx-vpn.de
gateway-flags=2
gwcert-flags=2
lasthost-flags=0
pem_passphrase_fsid=no
stoken_source=disabled
xmlconfig-flags=0
service-type=org.freedesktop.NetworkManager.openconnect

[ipv4]
dns-search=
method=auto

[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto

And here is what happened:
# nmcli --ask c up openconnect-test 
POST https://xxx.de/
Connected to xxx.xxx.xxx.xxx:443
SSL negotiation with xxx.de
Connected to HTTPS on xxx.de
XML POST enabled
Please enter your username and password.
Username:xxx
Password:
POST https://xxx.de/

I could connect successfully. Here is my 'fake' pem file:

# cat deutsche-telekom-root-ca-2.with-error.pem 
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
3qvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
Cm26OWMohpLzGITY+9HPBVZkVw==
-----END CERTIFICATE-----

Comment 4 Volker Sobek 2016-10-15 22:57:09 UTC
ps ax|grep [o]penconn
 4481 ?        Sl     0:00 /usr/libexec/nm-openconnect-service --bus-name org.freedesktop.NetworkManager.openconnect.Connection_7
 4504 ?        S      0:00 /usr/sbin/openconnect --servercert sha1:05d2d0a805bc00f88e7de9f011b3ad99cab3d1ae --syslog --cookie-on-stdin --script /usr/libexec/nm-openconnect-service-openconnect-helper --interface vpn0 xxx.xxx.xxx.xxx

(The sha1 hash is still the same, maybe that's why it didn't ask?)

Comment 5 Volker Sobek 2016-10-15 23:07:55 UTC
So apparently, as you explained, once you successfully connected to a server, the hash of the server certificate is remembered. After that it seems like NM/OpenConnect bypasses checking with the given .pem file even for new connections to known servers.

Comment 6 David Woodhouse 2016-10-16 16:18:29 UTC
Please show the actual IP address. It's a VPN server; it'll be getting probes *all* the time and hiding it from this bug serves no purpose except to make it harder to help you.

Comment 7 David Woodhouse 2016-10-16 16:20:35 UTC
I suspect the server probably has a certificate which is valid *regardless* of the cafile configuration (which you should never really need; why isn't that Telekom CA just installed system-wide with update-ca-trust anyway? Perhaps it already is?)

What happens if you just use openconnect on the command line, pointed at that server? Does it accept the cert?

Comment 8 Volker Sobek 2016-10-16 20:52:13 UTC
(In reply to David Woodhouse from comment #7)
> I suspect the server probably has a certificate which is valid *regardless*
> of the cafile configuration (which you should never really need; why isn't
> that Telekom CA just installed system-wide with update-ca-trust anyway?
> Perhaps it already is?)
Yes, it is installed by default in /etc/ssl/certs/ca-bundle.crt in fedora. I just wanted to specify it explicitly as a separate file via the GUI to be sure it only checks against this one.
> 
> What happens if you just use openconnect on the command line, pointed at
> that server? Does it accept the cert?

Connecting using OpenConnect directly yields the expected (correct) results: if I specify a defective CA file with --cafile, I get a warning, if I specify a correct .pem file, it works correctly.

# openconnect --cafile deutsche-telekom-root-ca-2.DEFECTIVE.pem unibn-vpn.uni-bonn.de
POST https://unibn-vpn.uni-bonn.de/
Connected to 131.220.224.202:443
SSL negotiation with unibn-vpn.uni-bonn.de
Server certificate verify failed: signature verification failed

Certificate from VPN server "unibn-vpn.uni-bonn.de" failed verification.
Reason: signature verification failed
Enter 'yes' to accept, 'no' to abort; anything else to view: ^Cfgets (stdin): Interrupted system call

[root@hp]# openconnect --cafile deutsche-telekom-root-ca-2.pem unibn-vpn.uni-bonn.de
POST https://unibn-vpn.uni-bonn.de/
Connected to 131.220.224.202:443
SSL negotiation with unibn-vpn.uni-bonn.de
Connected to HTTPS on unibn-vpn.uni-bonn.de
XML POST enabled
Please enter your username and password.
Username:

So the problem is that that using NM the CA file check is skipped once you have been successfully connected before, even if you specify a new CA file in the openconnect dialog, and even so if you create a *new* VPN connection.

Comment 9 Volker Sobek 2016-10-16 21:03:37 UTC
(In reply to Volker Sobek from comment #8)
> So the problem is that that using NM the CA file check is skipped once you
> have been successfully connected before, even if you specify a new CA file
> in the openconnect dialog, and even so if you create a *new* VPN connection.

Right now I tested the UI again, and after changing the CA file to the defective one, and reconnecting, I saw the UI error message about failed verification for the first time. I tried a couple of more times now, and it always shows a warning. Not sure why it suddenly works, I'll try to find the cause once I have time again!

Comment 10 David Woodhouse 2016-10-17 15:57:57 UTC
Ah, I think I see the problem. The cafile option doesn't *only* check against that one — I believe it's used in *addition* to the system trust. So when you loaded the malformed file and expected it to fail, it still worked because you have the required certs in the system trust database.

Not sure why it behaved as you expected from the command line... had you *removed* them from the system trust for that test?

Comment 11 David Woodhouse 2016-10-17 15:59:35 UTC
FWIW that server verifies for me without installing any additional (relevant) CAs.

Comment 12 David Woodhouse 2016-12-14 11:56:16 UTC
(In reply to Volker Sobek from comment #8)
> Yes, it is installed by default in /etc/ssl/certs/ca-bundle.crt in fedora. I
> just wanted to specify it explicitly as a separate file via the GUI to be
> sure it only checks against this one.

So you're protecting against the attack where someone manages to get a validly signed cert (by one of the various CAs trusted by the system, like Verisign) for
'unibn-vpn.uni-bonn.de'.

To be honest, I suspect you have better things to worry about if that can happen — because that attacker can have validly signed certs for far more interesting things, like your online banking. But OK, let's accept that's what you want.

Note that you still don't have this — the cafile option *adds* trusted CAs, and doesn't stop it from trusting what's already in the system trust database. On the command line you can use --no-system-trust but there's no support for that option in the NetworkManager configuration. You could file a separate RFE for that, perhaps, but for now I think we can close this bug?

Please don't hesitate to re-open if I'm missing something or you still have problems.


Note You need to log in before you can comment on or make changes to this bug.