Insecure Network Communication
Fixing Certificate Validation
About Certificate Validation
What is Improper Certificate Validation?
Improper certificate validation refers to a security vulnerability where a system fails to properly verify the authenticity of a digital certificate presented by a remote party during a communication. This can lead to the acceptance of forged or malicious certificates, allowing attackers to perform various attacks such as man-in-the-middle attacks or impersonation attacks.
Proper certificate validation is crucial for maintaining the security of SSL/TLS encrypted communication and ensuring the confidentiality, integrity, and authenticity of data exchanged over the network.
Check out these videos for a high-level explanation:
Weak certificate validation
Improper certificate pinning
What is the impact of Improper Certificate Validation?
Improper certificate validation can lead to a range of security threats, including:
- Man-in-the-middle attacks: Attackers can intercept communication between two parties and read or modify the data exchanged between them.
- Data breaches: Attackers can gain unauthorized access to sensitive information or sensitive systems, leading to data breaches.
- Malware distribution: Attackers can use fake digital certificates to distribute malicious software or infect systems with malware.
Overall, improper certificate validation can undermine the security of encrypted communication and compromise the confidentiality, integrity, and authenticity of data exchanged over the network.
How to prevent Improper Certificate Validation?
To prevent improper certificate validation, it is important to follow security best practices, such as:
- Use trusted certificate authorities: Only trust digital certificates issued by well-known and trusted certificate authorities.
- Verify certificate chains: Verify that the certificate presented by the remote party is valid and issued by a trusted certificate authority. Verify the entire certificate chain, including intermediate certificates.
- Check certificate revocation status: Check the revocation status of the certificate presented by the remote party to ensure that it has not been revoked.
- Use certificate pinning: Implement certificate pinning to ensure that the communication only occurs with the exact certificate or certificate authority specified.
- Keep software up to date: Keep software and security protocols up to date, as new vulnerabilities and security patches are regularly released.
Overall, proper certificate validation is crucial for maintaining the security of encrypted communication, and following these best practices can help prevent improper certificate validation and mitigate related security risks.
References
Taxonomies
- OWASP Top 10 - A07 Identification and Authentication Failures
- CWE-295: Improper Certificate Validation
Explanation & Prevention
- OWASP: Transport Layer Protection Cheat Sheet
- OWASP: Certificate and Public Key Pinning
- WASC-04: Insufficient Transport Layer Protection
- The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software
- OpenSSL Hostname Validation documentation
Related CVEs
Training
Disabled TLS certificate verification
Option A: Enable Verification of certificates
Go through the issues that GuardRails identified in the PR/MR
Replace
InsecureSkipVerify: true
:package main
import (
"crypto/tls"
"fmt"
"net/http"
)
func main() {
tr := &http.Transport{
// This is the insecure setting, it should be set to false.
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
_, err := client.Get("https://golang.org/")
if err != nil {
fmt.Println(err)
}
}with
InsecureSkipVerify: false
:// Ensure that you have a valid certificate
// Free certificates at available at https://letsencrypt.org/
TLSClientConfig: &tls.Config{InsecureSkipVerify: false},Test it
Ship it 🚢 and relax 🌴
Enable SSH Host Key Verification (crypto/ssh)
Using ssh.InsecureIgnoreHostKey()
in an SSH configuration would allow malicious actors to intercept communication between the SSH client and the SSH server.
Option A: Only allow Known Hosts
Knowing hosts before accepting an SSH connection will prevent an attacker from impersonating an actor.
Go through the issues that GuardRails identified in the PR/MR.
Locate the vulnerable pattern (example below):
sshConfig = ssh.ClientConfig{
User: "root",
Auth: []ssh.AuthMethod{auth},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}Replace the vulnerable pattern with
knownhosts
(example below):import "golang.org/x/crypto/ssh/knownhosts"
knownHostCallback, err := knownhosts.New("~/.ssh/known_hosts")
if err != nil {
panic(err)
}
sshConfig = ssh.ClientConfig{
User: "root",
Auth: []ssh.AuthMethod{auth},
HostKeyCallback: knownHostCallback,
}Test it
Ship it 🚢 and relax 🌴
Securing TLS configuration
About Insecure TLS Configuration
What is insecure TLS configuration?
Insecure TLS (Transport Layer Security) configuration refers to the use of weak or vulnerable cryptographic algorithms or protocols in the configuration of TLS on a system or application.
TLS is used to secure communication channels between clients and servers. Insecure TLS configuration can lead to a range of security vulnerabilities.
Check out these videos for a high-level explanation:
Weak Algorithms
Weak Cipher Suites
What is the impact of insecure TLS configuration?
Insecure TLS (Transport Layer Security) configuration can have significant impacts on the security and privacy of communication channels between clients and servers.
Here are some of the potential impacts:
- Man-in-the-middle (MITM) attacks: Weak or outdated cryptographic algorithms can be exploited by attackers to intercept and modify data in transit between a client and server. This can enable attackers to steal sensitive data or manipulate communication channels to launch other attacks.
- Information disclosure: Insecure TLS configuration can allow attackers to gain access to sensitive data, such as login credentials or personal information, transmitted between the client and server. This can lead to data breaches or compromise of sensitive information.
How to prevent insecure TLS configuration?
To prevent insecure TLS (Transport Layer Security) configuration, several measures can be taken, including:
- Use strong cryptographic algorithms and protocols: Use strong cryptographic algorithms and protocols, such as TLS 1.2 or higher, and disable outdated or weak algorithms, such as SSLv2 and SSLv3. This can help prevent attackers from exploiting vulnerabilities in the encryption and authentication processes.
- Use appropriate key sizes: Use appropriate key sizes to ensure that the cryptographic keys used in the TLS communication are strong enough to resist attacks. Key sizes of 2048 bits or higher are recommended.
- Regularly update software and systems: Regularly update software and systems to ensure that the latest security patches are applied and known vulnerabilities are addressed.
References
Taxonomies
Explanation & Prevention
- OWASP: Transport Layer Protection Cheat Sheet
- WASC-04: Insufficient Transport Layer Protection
- POODLE (CVE Details)
- BEAST (CVE Details)
- CRIME (CVE Details)
- FREAK (CVE Details)
- BREACH (CVE Details)
- LOGJAM (CVE Details)
Related CVEs
Training
Category-specific references:
- Golang Perfect TLS Settings
- Checkmarx - Go - Web Application Secure Coding Practices: TLS Configuration
Insecure TLS Cipher
When communicating with TLS, both the client and server can choose which cipher suites they want to use.
A cipher suite represents the methods that a server and
client will use to exchange keys, authenticate or sign
messages, encrypt messages, and hash messages. For example,
the cipher TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256
uses the
following:
- Key Exchange =
ECDHE
: Ephemeral Elliptic Curve Diffie Hellman - Authentication =
PSK
: Pre-Shared Key Authentication - Bulk Encryption Cipher =
AES-128
: 128-bit AES - Cipher Mode =
GCM
: Galois/Counter Mode (GCM) - Hash/MAC =
SHA256
: SHA-256
However, not all ciphers that are listed in the TLS spec are secure, and should not be used in applications where security is necessary.
For example, the TLS_RSA_WITH_RC4_128_SHA
cipher is
insecure because RC4 has been proven to be broken.
Ciphers that use CBC
as their cipher mode are
vulnerable to several attacks, and are considered
insecure. Golang's crypto/tls
package has implemented some
counter-measures/mitigations for these attacks, but only for
CBC
mode with SHA-1
hashes. However, these mitigations
are not comprehensive and might still be exploitable.
Note that the other CBC
ciphers that do not have
mitigations in place are more insecure, and are categorized
as such by a different rule.
Rule-specific references:
- IETF RFC On Known TLS Attacks (Note: maybe be outdated)
- Golang
crypto/tls
Source - List of Cipher Suites, and their Security
- Lucky13 Overview
- POODLE Overview (CVE Details)
- BEAST Overview (CVE Details)
- CRIME Overview (CVE Details)
- FREAK Overview (CVE Details)
- BREACH Overview (CVE Details)
- LOGJAM Overview (CVE Details)
Option A: Use a secure TLS Cipher
The best option for protection against exploits/vulnerabilities is to change the TLS ciphers you are using.
For maximum security, you should use the following list of ciphers:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
Note that if you need backward compatibility with TLS 1.0 or 1.1, you could include the following ciphers. However, even though Golang hame some mitigations in place, we highly recommend against using them as they are fragile, and could potentially be exploited against attacks such as Lucky13.
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Identify the vulnerable patterns (example below):
func GenClient() *http.Client {
client := &http.Client{}
cipherSuites := []uint16{tls.TLS_RSA_WITH_RC4_128_SHA, /* ... */}
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{CipherSuites: cipherSuites[:]}
}
return client
}Replace the vulnerable patterns (example below):
func GenClient() *http.Client {
client := &http.Client{}
cipherSuites := []uint16 {
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
}
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{CipherSuites: cipherSuites}
}
return client
}Test it
Ship it 🚢 and relax 🌴
Usage of a Cipher with no Forward Secrecy
When using TLS, you must choose a set of cipher suites that you are willing to communicate with. However, not all of these ciphers provide forward secrecy.
If a cipher suite has forward secrecy, that gives assurances that session keys will not be compromised even if long-term secrets used in the session key exchange are compromised.
Not having forward secrecy means that if any long-term secrets (usually a server's private key) are leaked, then all conversations whose key exchange depended on the long-term secret can be decrypted.
Rule-specific references:
Option A: Use a Cipher that has Forward Secrecy
This option entails removing support for ciphers that don't have forward secrecy, such as most ciphers that use RSA for authentication.
Locate the vulnerable patterns (example below):
func GenClient() *http.Client {
client := &http.Client{}
cipherSuites :=
[]uint16{tls.TLS_RSA_WITH_AES_128_GCM_SHA256, /* ... */}
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{CipherSuites: cipherSuites}
}
return client
}Replace the vulnerable patterns (example below):
func GenClient() *http.Client {
client := &http.Client{}
cipherSuites :=
[]uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256
}
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{CipherSuites: cipherSuites}
}
return client
}Test it
Ship it 🚢 and relax 🌴
TLS 1.0 and 1.1 are Insecure/Deprecated
Using TLS versions 1.0 and 1.1 can potentially be insecure, especially if you are the client. There are multiple attacks against TLS versions 1.0, and 1.1 including:
- POODLE (CVE Details)
- BEAST (CVE Details)
- CRIME (CVE Details)
- FREAK (CVE Details)
- BREACH (CVE Details)
- LOGJAM (CVE Details)
There are mitigations against some of the exploits listed above, but it cannot be verified that both users on either side of the TLS connection have deployed such mitigations.
Due to the above, and due to the large number of vulnerabilities that target these TLS versions, it is highly recommended that you upgrade your connection to at least TLS 1.2.
The situations in which you would want to continue using TLS 1.0/1.1 are few and far between. An example where you would want to continue support for TLS 1.0/1.1 would be communicating with old software or a server over a private network.
Rule-specific references:
- Microsoft's TLS 1.0 Solution
- IETF Deprecation RFC
- Wikipedia - Overview of the Security of TLS
- Shodan TLS Version Usage Report
- Golang Issue on Deprecating TLS 1.0/1.1
- Various articles on TLS Security
- SSL Labs Best Practices
- Golang's
crypto/tls
docs - IETF TLS Attack Summary RFC (Note that a review is needed on this RFC)
- ciphersuite.info
Option A: Upgrade your TLS Version
The best solution to this vulnerability is to not use TLS 1.0/1.1, and either upgrade to TLS 1.2 or higher.
Identify the vulnerable patterns (example below):
func main() {
client := &http.Client{}
client.Transport = &http.Transport{TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS10}}
// ...
}Update the vulnerable pattern to not use an insecure TLS version (example below):
func main() {
client := &http.Client{}
client.Transport = &http.Transport{TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS10}}
// ...
}Test it
Ship it 🚢 and relax 🌴
Option B: Set TLS Min and Max Version to Secure Values
Go through the issues that GuardRails identified in the PR/MR
Look for
MinVersion
andMaxVersion
:package main
import (
"crypto/tls"
"fmt"
"net/http"
)
func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
// These are the insecure lines
MinVersion: 0,
MinVersion: 0},
}
client := &http.Client{Transport: tr}
_, err := client.Get("https://golang.org/")
if err != nil {
fmt.Println(err)
}
}and replace them with the correct values:
package main
import (
"crypto/tls"
"fmt"
"net/http"
)
func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
// Remove MaxVersion, because the following line is sufficient.
MinVersion: tls.VersionTLS12
},
}
client := &http.Client{Transport: tr}
_, err := client.Get("https://golang.org/")
if err != nil {
fmt.Println(err)
}
}Test it
Ship it 🚢 and relax 🌴