mirror of
https://github.com/securego/gosec.git
synced 2024-12-25 03:55:54 +00:00
Improve the TLS version checking
Signed-off-by: Cosmin Cojocar <cosmin.cojocar@gmx.ch>
This commit is contained in:
parent
ad1cb7e47e
commit
55d368f2e5
2 changed files with 68 additions and 15 deletions
63
rules/tls.go
63
rules/tls.go
|
@ -17,6 +17,7 @@
|
||||||
package rules
|
package rules
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
|
||||||
|
@ -25,10 +26,12 @@ import (
|
||||||
|
|
||||||
type insecureConfigTLS struct {
|
type insecureConfigTLS struct {
|
||||||
gosec.MetaData
|
gosec.MetaData
|
||||||
MinVersion int16
|
MinVersion int16
|
||||||
MaxVersion int16
|
MaxVersion int16
|
||||||
requiredType string
|
requiredType string
|
||||||
goodCiphers []string
|
goodCiphers []string
|
||||||
|
actualMinVersion int16
|
||||||
|
actualMaxVersion int16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *insecureConfigTLS) ID() string {
|
func (t *insecureConfigTLS) ID() string {
|
||||||
|
@ -45,7 +48,6 @@ func stringInSlice(a string, list []string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context) *gosec.Issue {
|
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context) *gosec.Issue {
|
||||||
|
|
||||||
if ciphers, ok := n.(*ast.CompositeLit); ok {
|
if ciphers, ok := n.(*ast.CompositeLit); ok {
|
||||||
for _, cipher := range ciphers.Elts {
|
for _, cipher := range ciphers.Elts {
|
||||||
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
||||||
|
@ -62,7 +64,6 @@ func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context)
|
||||||
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Context) *gosec.Issue {
|
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Context) *gosec.Issue {
|
||||||
if ident, ok := n.Key.(*ast.Ident); ok {
|
if ident, ok := n.Key.(*ast.Ident); ok {
|
||||||
switch ident.Name {
|
switch ident.Name {
|
||||||
|
|
||||||
case "InsecureSkipVerify":
|
case "InsecureSkipVerify":
|
||||||
if node, ok := n.Value.(*ast.Ident); ok {
|
if node, ok := n.Value.(*ast.Ident); ok {
|
||||||
if node.Name != "false" {
|
if node.Name != "false" {
|
||||||
|
@ -85,20 +86,24 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Cont
|
||||||
|
|
||||||
case "MinVersion":
|
case "MinVersion":
|
||||||
if ival, ierr := gosec.GetInt(n.Value); ierr == nil {
|
if ival, ierr := gosec.GetInt(n.Value); ierr == nil {
|
||||||
if (int16)(ival) < t.MinVersion {
|
t.actualMinVersion = (int16)(ival)
|
||||||
return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion too low.", gosec.High, gosec.High)
|
} else {
|
||||||
|
if se, ok := n.Value.(*ast.SelectorExpr); ok {
|
||||||
|
if pkg, ok := se.X.(*ast.Ident); ok && pkg.Name == "tls" {
|
||||||
|
t.actualMinVersion = t.mapVersion(se.Sel.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO(tk): symbol tab look up to get the actual value
|
|
||||||
return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion may be too low.", gosec.High, gosec.Low)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "MaxVersion":
|
case "MaxVersion":
|
||||||
if ival, ierr := gosec.GetInt(n.Value); ierr == nil {
|
if ival, ierr := gosec.GetInt(n.Value); ierr == nil {
|
||||||
if (int16)(ival) < t.MaxVersion {
|
t.actualMaxVersion = (int16)(ival)
|
||||||
return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion too low.", gosec.High, gosec.High)
|
} else {
|
||||||
|
if se, ok := n.Value.(*ast.SelectorExpr); ok {
|
||||||
|
if pkg, ok := se.X.(*ast.Ident); ok && pkg.Name == "tls" {
|
||||||
|
t.actualMaxVersion = t.mapVersion(se.Sel.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO(tk): symbol tab look up to get the actual value
|
|
||||||
return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion may be too low.", gosec.High, gosec.Low)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "CipherSuites":
|
case "CipherSuites":
|
||||||
|
@ -112,6 +117,35 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Cont
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *insecureConfigTLS) mapVersion(version string) int16 {
|
||||||
|
var v int16
|
||||||
|
switch version {
|
||||||
|
case "VersionTLS13":
|
||||||
|
v = tls.VersionTLS13
|
||||||
|
case "VersionTLS12":
|
||||||
|
v = tls.VersionTLS12
|
||||||
|
case "VersionTLS11":
|
||||||
|
v = tls.VersionTLS11
|
||||||
|
case "VersionTLS10":
|
||||||
|
v = tls.VersionTLS10
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *insecureConfigTLS) checkVersion(n ast.Node, c *gosec.Context) *gosec.Issue {
|
||||||
|
if t.actualMaxVersion == 0 && t.actualMinVersion >= t.MinVersion {
|
||||||
|
// no warning is generated since the min version is grater than the secure min version
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if t.actualMinVersion < t.MinVersion {
|
||||||
|
return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion too low.", gosec.High, gosec.High)
|
||||||
|
}
|
||||||
|
if t.actualMaxVersion < t.MaxVersion {
|
||||||
|
return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion too low.", gosec.High, gosec.High)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||||
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
|
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
|
||||||
actualType := c.Info.TypeOf(complit.Type)
|
actualType := c.Info.TypeOf(complit.Type)
|
||||||
|
@ -124,6 +158,7 @@ func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return t.checkVersion(complit, c), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -1887,7 +1887,25 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
}`}, 1, gosec.NewConfig()}}
|
}`}, 1, gosec.NewConfig()}, {[]string{`
|
||||||
|
// secure max version when min version is specified
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{MaxVersion: 0, MinVersion: tls.VersionTLS13},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
_, err := client.Get("https://golang.org/")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}, 0, gosec.NewConfig()}}
|
||||||
|
|
||||||
// SampleCodeG403 - weak key strength
|
// SampleCodeG403 - weak key strength
|
||||||
SampleCodeG403 = []CodeSample{
|
SampleCodeG403 = []CodeSample{
|
||||||
|
|
Loading…
Reference in a new issue