Merge pull request from GHSA-cxfm-8j5v-5qr2

Add TLS server certificate validation to ElasticsearchWriter, GelfWriter, InfluxdbWriter and Influxdb2Writer (v2)
This commit is contained in:
Noah Hilverling 2021-08-19 13:52:29 +02:00 committed by GitHub
commit 9cafabcc9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 12 deletions

View File

@ -9,7 +9,18 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
## 2.13.1 (2021-08-19)
Version 2.13.1 fixes two issues indroduced with the 2.13.0 release.
The main focus of this version is a security vulnerability in the TLS certificate verification of our metrics writers ElasticsearchWriter, GelfWriter, InfluxdbWriter and Influxdb2Writer.
Version 2.13.1 also fixes two issues indroduced with the 2.13.0 release.
### Security
* Add TLS server certificate validation to ElasticsearchWriter, GelfWriter, InfluxdbWriter and Influxdb2Writer ([GHSA-cxfm-8j5v-5qr2](https://github.com/Icinga/icinga2/security/advisories/GHSA-cxfm-8j5v-5qr2))
Depending on your setup, manual intervention beyond installing the new versions
may be required, so please read the more detailed information in the
[release blog post](https://icinga.com/blog/2021/08/19/icinga-2-13-1-security-release//)
carefully
### Bugfixes

View File

@ -1238,6 +1238,7 @@ Configuration Attributes:
username | String | **Optional.** Basic auth username if Elasticsearch is hidden behind an HTTP proxy.
password | String | **Optional.** Basic auth password if Elasticsearch is hidden behind an HTTP proxy.
enable\_tls | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`. Requires an HTTP proxy.
insecure\_noverify | Boolean | **Optional.** Disable TLS peer verification.
ca\_path | String | **Optional.** Path to CA certificate to validate the remote host. Requires `enable_tls` set to `true`.
cert\_path | String | **Optional.** Path to host certificate to present to the remote host for mutual verification. Requires `enable_tls` set to `true`.
key\_path | String | **Optional.** Path to host key to accompany the cert\_path. Requires `enable_tls` set to `true`.
@ -1325,6 +1326,7 @@ Configuration Attributes:
enable\_send\_perfdata | Boolean | **Optional.** Enable performance data for 'CHECK RESULT' events.
enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
enable\_tls | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`.
insecure\_noverify | Boolean | **Optional.** Disable TLS peer verification.
ca\_path | String | **Optional.** Path to CA certificate to validate the remote host. Requires `enable_tls` set to `true`.
cert\_path | String | **Optional.** Path to host certificate to present to the remote host for mutual verification. Requires `enable_tls` set to `true`.
key\_path | String | **Optional.** Path to host key to accompany the cert\_path. Requires `enable_tls` set to `true`.
@ -1662,6 +1664,7 @@ Configuration Attributes:
password | String | **Optional.** InfluxDB user password. Defaults to `none`.
basic\_auth | Dictionary | **Optional.** Username and password for HTTP basic authentication.
ssl\_enable | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`.
ssl\_insecure\_noverify | Boolean | **Optional.** Disable TLS peer verification.
ssl\_ca\_cert | String | **Optional.** Path to CA certificate to validate the remote host.
ssl\_cert | String | **Optional.** Path to host certificate to present to the remote host for mutual verification.
ssl\_key | String | **Optional.** Path to host key to accompany the ssl\_cert.
@ -1724,6 +1727,7 @@ Configuration Attributes:
bucket | String | **Required.** InfluxDB bucket name.
auth\_token | String | **Required.** InfluxDB authentication token.
ssl\_enable | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`.
ssl\_insecure\_noverify | Boolean | **Optional.** Disable TLS peer verification.
ssl\_ca\_cert | String | **Optional.** Path to CA certificate to validate the remote host.
ssl\_cert | String | **Optional.** Path to host certificate to present to the remote host for mutual verification.
ssl\_key | String | **Optional.** Path to host key to accompany the ssl\_cert.

View File

@ -37,6 +37,10 @@ void UnbufferedAsioTlsStream::BeforeHandshake(handshake_type type)
{
namespace ssl = boost::asio::ssl;
if (!m_Hostname.IsEmpty()) {
X509_VERIFY_PARAM_set1_host(SSL_get0_param(native_handle()), m_Hostname.CStr(), m_Hostname.GetLength());
}
set_verify_mode(ssl::verify_peer | ssl::verify_client_once);
set_verify_callback([this](bool preverified, ssl::verify_context& ctx) {

View File

@ -274,13 +274,6 @@ void RedisConnection::Connect(asio::yield_context& yc)
auto connectTimeout (MakeTimeout(conn));
Defer cancelTimeout ([&connectTimeout]() { connectTimeout->Cancel(); });
if (!m_Insecure) {
auto native (tlsConn.native_handle());
X509_VERIFY_PARAM_set1_host(SSL_get0_param(native), m_Host.CStr(), 0);
SSL_set_verify(native, SSL_VERIFY_PEER, NULL);
}
icinga::Connect(conn->lowest_layer(), m_Host, Convert::ToString(m_Port), yc);
tlsConn.async_handshake(tlsConn.client, yc);

View File

@ -632,6 +632,18 @@ OptionalTlsStream ElasticsearchWriter::Connect()
<< "TLS handshake with host '" << GetHost() << "' on port " << GetPort() << " failed.";
throw;
}
if (!GetInsecureNoverify()) {
if (!tlsStream.GetPeerCertificate()) {
BOOST_THROW_EXCEPTION(std::runtime_error("Elasticsearch didn't present any TLS certificate."));
}
if (!tlsStream.IsVerifyOK()) {
BOOST_THROW_EXCEPTION(std::runtime_error(
"TLS certificate validation failed: " + std::string(tlsStream.GetVerifyError())
));
}
}
}
return std::move(stream);

View File

@ -29,6 +29,9 @@ class ElasticsearchWriter : ConfigObject
[config] bool enable_tls {
default {{{ return false; }}}
};
[config] bool insecure_noverify {
default {{{ return false; }}}
};
[config] String ca_path;
[config] String cert_path;
[config] String key_path;

View File

@ -135,10 +135,8 @@ void GelfWriter::AssertOnWorkQueue()
void GelfWriter::ExceptionHandler(boost::exception_ptr exp)
{
Log(LogCritical, "GelfWriter", "Exception during Graylog Gelf operation: Verify that your backend is operational!");
Log(LogDebug, "GelfWriter")
<< "Exception during Graylog Gelf operation: " << DiagnosticInformation(std::move(exp));
Log(LogCritical, "GelfWriter") << "Exception during Graylog Gelf operation: " << DiagnosticInformation(exp, false);
Log(LogDebug, "GelfWriter") << "Exception during Graylog Gelf operation: " << DiagnosticInformation(exp, true);
DisconnectInternal();
}
@ -206,6 +204,18 @@ void GelfWriter::ReconnectInternal()
<< "TLS handshake with host '" << GetHost() << " failed.'";
throw;
}
if (!GetInsecureNoverify()) {
if (!tlsStream.GetPeerCertificate()) {
BOOST_THROW_EXCEPTION(std::runtime_error("Graylog Gelf didn't present any TLS certificate."));
}
if (!tlsStream.IsVerifyOK()) {
BOOST_THROW_EXCEPTION(std::runtime_error(
"TLS certificate validation failed: " + std::string(tlsStream.GetVerifyError())
));
}
}
}
SetConnected(true);

View File

@ -34,6 +34,9 @@ class GelfWriter : ConfigObject
[config] bool enable_tls {
default {{{ return false; }}}
};
[config] bool insecure_noverify {
default {{{ return false; }}}
};
[config] String ca_path;
[config] String cert_path;
[config] String key_path;

View File

@ -187,6 +187,18 @@ OptionalTlsStream InfluxdbCommonWriter::Connect()
<< "TLS handshake with host '" << GetHost() << "' failed.";
throw;
}
if (!GetSslInsecureNoverify()) {
if (!tlsStream.GetPeerCertificate()) {
BOOST_THROW_EXCEPTION(std::runtime_error("InfluxDB didn't present any TLS certificate."));
}
if (!tlsStream.IsVerifyOK()) {
BOOST_THROW_EXCEPTION(std::runtime_error(
"TLS certificate validation failed: " + std::string(tlsStream.GetVerifyError())
));
}
}
}
return std::move(stream);

View File

@ -18,6 +18,9 @@ abstract class InfluxdbCommonWriter : ConfigObject
[config] bool ssl_enable {
default {{{ return false; }}}
};
[config] bool ssl_insecure_noverify {
default {{{ return false; }}}
};
[config] String ssl_ca_cert {
default {{{ return ""; }}}
};