5 SSL Security
Using SSL (in this particular case based on the OpenSSL
implementation) to connect to SSL services (e.g., an https://
address) easily gives a false sense of security. This section explains
some of the pitfalls.1We do not
claim to be complete, just to start warning you if security is important
to you. Please make sure you understand (Open)SSL before relying on it..
As stated in the introduction, SSL aims at solving two issues: tapping
information from the wire by means of encryption and make sure that you
are talking to the right address.
Encryption is generally well arranged as long as you ensure that the
underlying SSL library has all known security patches installed and you
use an encryption that is not known to be weak. The Windows version of
SWI-Prolog ships with its own binary of the OpenSSL library. Ensure this
is up-to-date. Most other systems ship with the OpenSSL library and
SWI-Prolog uses the system version. This applies for the binaries we
distribute for MacOSX and Linux, as well as official Linux packages.
Check the origin and version of the OpenSSL libraries if SWI-Prolog was
compiled from source. The OpenSSL library version as reported by
SSLeay_version() is available in the Prolog flag
ssl_library_version
as illustrated below on Ubuntu 14.04.
?- [library(ssl)]. ?- current_prolog_flag(ssl_library_version, X). X = 'OpenSSL 1.0.1f 6 Jan 2014'.
Whether you are talking to the right address is a complicated issue. The core of the validation is that the server provides a certificate that identifies the server. This certificate is digitally signed by another certificate, and ultimately by a root certificate. (There may be additional links in this chain as well, or there may just be one certificate signed by itself) Verifying the peer implies:
- Verifying the chain or digital signatures until a trusted root certificate is found, taking care that the chain does not contain any invalid certificates, such as certificates which have expired, are not yet valid, have altered or forged signatures, are valid for the purposes of SSL (and in the case of an issuer, issuing child certificates)
- Verifying that the signer of a certificate did not revoke the signed certificate.
- Verifying that the host we connected to is indeed the host claimed in the certificate.
The default https client plugin (library(http/http_ssl_plugin)
)
registers the system trusted root certificate with OpenSSL. This is
achieved using the option
cacert_file(system(root_certificates))
of ssl_context/3.
The verification is left to OpenSSL. To the best of our knowledge, the
current (1.0) version of OpenSSL only implements step (1) of the
verification process outlined above. This implies that an attacker that
can control DNS mapping (host name to IP) or routing (IP to physical
machine) can fake to be a secure host as long as they manage to obtain a
certificate that is signed from a recognised authority. Version 1.0.2
supports hostname checking, and will not validate a certificate chain if
the leaf certificate does not match the hostname. 'Match' here is not a
simple string comparison; certificates are allowed (subject to many
rules) to have wildcards in their SubjectAltName field. Care must also
be taken to ensure that the name we are checking against does not
contain embedded NULLs. If SWI-Prolog is compiled against a version of
OpenSSL that does NOT have hostname checking (ie 1.0.0 or earlier), it
will attempt to do the validation itself. This is not guaranteed to be
perfect, and it only supports a small subset of allowed wildcards. If
security is important, use OpenSSL 1.0.2 or higher.
After validation, the predicate ssl_peer_certificate/2 can be used to obtain the peer certificate and inspect its properties.