Skip to main content

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

Explanation & Prevention

Training

Disabled TLS certificate verification

Option A: Enable Verification of certificates

  1. Go through the issues that GuardRails identified in the PR/MR

  2. 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},
  3. Test it

  4. 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.

  1. Go through the issues that GuardRails identified in the PR/MR.

  2. Locate the vulnerable pattern (example below):

        sshConfig = ssh.ClientConfig{
    User: "root",
    Auth: []ssh.AuthMethod{auth},
    HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
  3. 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,
    }
  4. Test it

  5. 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

Training

Category-specific references:

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:

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
  1. 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
    }
  2. 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
    }
  3. Test it

  4. 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.

  1. 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
    }
  2. 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
    }

  3. Test it

  4. 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:

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:

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.

  1. Identify the vulnerable patterns (example below):

      func main() {
    client := &http.Client{}
    client.Transport = &http.Transport{TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS10}}
    // ...
    }
  2. 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}}
    // ...
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴

Option B: Set TLS Min and Max Version to Secure Values

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Look for MinVersion and MaxVersion:

    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)
    }
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴