go.grpc.security.grpc-server-insecure-connection.grpc-server-insecure-connection

Verifed by r2c
Community Favorite
profile photo of semgrepsemgrep
Author
178,438
Download Count*

Found an insecure gRPC server without 'grpc.Creds()' or options with credentials. This allows for a connection without encryption to this server. A malicious attacker could tamper with the gRPC message, which could compromise the machine. Include credentials derived from an SSL certificate in order to create a secure gRPC connection. You can create credentials using 'credentials.NewServerTLSFromFile("cert.pem", "cert.key")'.

Run Locally

Run in CI

Defintion

rules:
  - id: grpc-server-insecure-connection
    metadata:
      cwe:
        - "CWE-300: Channel Accessible by Non-Endpoint"
      references:
        - https://blog.gopheracademy.com/advent-2019/go-grps-and-tls/#connection-without-encryption
      category: security
      technology:
        - grpc
      confidence: HIGH
      owasp:
        - A07:2021 - Identification and Authentication Failures
      subcategory:
        - audit
      likelihood: LOW
      impact: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Other
    message: Found an insecure gRPC server without 'grpc.Creds()' or options with
      credentials. This allows for a connection without encryption to this
      server. A malicious attacker could tamper with the gRPC message, which
      could compromise the machine. Include credentials derived from an SSL
      certificate in order to create a secure gRPC connection. You can create
      credentials using 'credentials.NewServerTLSFromFile("cert.pem",
      "cert.key")'.
    languages:
      - go
    severity: ERROR
    mode: taint
    pattern-sinks:
      - requires: OPTIONS and not CREDS
        pattern: grpc.NewServer($OPT, ...)
      - requires: EMPTY_CONSTRUCTOR
        pattern: grpc.NewServer()
    pattern-sources:
      - label: OPTIONS
        pattern: grpc.ServerOption{ ... }
      - label: CREDS
        pattern: grpc.Creds(...)
      - label: EMPTY_CONSTRUCTOR
        pattern: grpc.NewServer()

Examples

grpc-server-insecure-connection.go

package insecuregrpc

import (
	"crypto/x509"
	"log"
	"net/http"
	"net/http/httptest"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// cf. https://blog.gopheracademy.com/advent-2019/go-grps-and-tls/#connection-without-encryption
func unsafe() {
	// Server
	// ruleid:grpc-server-insecure-connection
	s := grpc.NewServer()
	// ... register gRPC services ...
	if err = s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

func safe() {
	// Server
	// ok:grpc-server-insecure-connection
	s := grpc.NewServer(grpc.Creds(credentials.NewClientTLSFromCert(x509.NewCertPool(), "")))
	// ... register gRPC services ...
	if err = s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

// False Positive test
// cf. https://github.com/daghan/invoicer-chapter2/blob/4c5b00408a4aeece86d98ad3ef1c88e610053dfc/vendor/golang.org/x/net/websocket/websocket_test.go#L129
func startServer() {
	http.Handle("/echo", Handler(echoServer))
	http.Handle("/count", Handler(countServer))
	http.Handle("/ctrldata", Handler(ctrlAndDataServer))
	subproto := Server{
		Handshake: subProtocolHandshake,
		Handler:   Handler(subProtoServer),
	}
	http.Handle("/subproto", subproto)
	// ok:grpc-server-insecure-connection
	server := httptest.NewServer(nil)
	serverAddr = server.Listener.Addr().String()
	log.Print("Test WebSocket server listening on ", serverAddr)
}

// False Positive test - options have grpc.Creds
func startServerWithOpts() {
	options := []grpc.ServerOption{
		grpc.Creds(credentials.NewClientTLSFromCert(pool, addr)),
	}
	// ok:grpc-server-insecure-connection
	grpcServer := grpc.NewServer(options...)
	_ = grpcServer
}

// False Positive test - options have grpc.Creds, credentials in a variable
func startServerCredsVar() {
	creds := credentials.NewClientTLSFromCert(xpool, xaddr)
	options := []grpc.ServerOption{
		grpc.Creds(creds),
		grpc.UnaryInterceptor(auth.GRPCInterceptor),
	}
	// ok:grpc-server-insecure-connection
	grpcServer := grpc.NewServer(options...)
	_ = grpcServer
}

func startServerWithOtherCreds() {
    creds := credentials.NewTLS(tlsConfig)
	logger := penglog.GlobalLogger()
	logInterceptor := penggrpc.NewAccessLogInterceptor(&logger, grpcLogFields)
	opts := []grpc.ServerOption{
		grpc.Creds(creds),
		grpc.ChainUnaryInterceptor(
			logInterceptor.UnaryServerInterceptor,
			auth.GRPCInterceptor,
		),
		grpc.MaxRecvMsgSize(maxRecvMsgSize),
	}
	// ok:grpc-server-insecure-connection
	grpcServer := grpc.NewServer(opts)
	_ = grpcServer
}