go.lang.security.audit.crypto.ssl.ssl-v3-is-insecure

Verifed by r2c
Community Favorite
profile photo of semgrepsemgrep
Author
124,504
Download Count*

SSLv3 is insecure because it has known vulnerabilities. Starting with go1.14, SSLv3 will be removed. Instead, use 'tls.VersionTLS13'.

Run Locally

Run in CI

Defintion

rules:
  - id: ssl-v3-is-insecure
    message: SSLv3 is insecure because it has known vulnerabilities. Starting with
      go1.14, SSLv3 will be removed. Instead, use 'tls.VersionTLS13'.
    metadata:
      cwe:
        - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
      owasp:
        - A03:2017 - Sensitive Data Exposure
        - A02:2021 - Cryptographic Failures
      source-rule-url: https://github.com/securego/gosec/blob/master/rules/tls_config.go
      references:
        - https://golang.org/doc/go1.14#crypto/tls
        - https://www.us-cert.gov/ncas/alerts/TA14-290A
      category: security
      technology:
        - go
      confidence: HIGH
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cryptographic Issues
    languages:
      - go
    severity: WARNING
    fix-regex:
      regex: VersionSSL30
      replacement: VersionTLS13
    pattern: "tls.Config{..., MinVersion: $TLS.VersionSSL30, ...}"

Examples

ssl.go

package main

import (
	"crypto/tls"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
)

// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
type zeroSource struct{}

func (zeroSource) Read(b []byte) (n int, err error) {
	for i := range b {
		b[i] = 0
	}

	return len(b), nil
}

func main() {
	// Dummy test HTTP server for the example with insecure random so output is
	// reproducible.
	server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
	server.TLS = &tls.Config{
		Rand: zeroSource{}, // for example only; don't do this.
	}
	server.StartTLS()
	defer server.Close()

	// Typically the log would go to an open file:
	// w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	w := os.Stdout

	client := &http.Client{
		Transport: &http.Transport{
			// ruleid: ssl-v3-is-insecure
			TLSClientConfig: &tls.Config{
				KeyLogWriter:       w,
				MinVersion:         tls.VersionSSL30,
				Rand:               zeroSource{}, // for reproducible output; don't do this.
				InsecureSkipVerify: true,         // test server certificate is not trusted.
			},
		},
	}
	resp, err := client.Get(server.URL)
	if err != nil {
		log.Fatalf("Failed to get URL: %v", err)
	}
	resp.Body.Close()

	client_good := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				KeyLogWriter: w,
				// OK
				MinVersion:         tls.VersionTLS10,
				Rand:               zeroSource{}, // for reproducible output; don't do this.
				InsecureSkipVerify: true,         // test server certificate is not trusted.
			},
		},
	}
	resp, err := client.Get(server.URL)
	if err != nil {
		log.Fatalf("Failed to get URL: %v", err)
	}
	resp.Body.Close()
}