mirror of
https://github.com/securego/gosec.git
synced 2024-12-25 03:55:54 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
3713168816
22 changed files with 645 additions and 142 deletions
17
.travis.yml
17
.travis.yml
|
@ -1,14 +1,25 @@
|
||||||
language: go
|
language: go
|
||||||
before_script:
|
|
||||||
- go vet $(go list ./... | grep -v /vendor/)
|
|
||||||
go:
|
go:
|
||||||
- 1.5
|
- 1.7
|
||||||
|
- 1.8
|
||||||
|
- 1.9
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
- go get -u github.com/golang/lint/golint
|
||||||
- go get -v github.com/onsi/ginkgo/ginkgo
|
- go get -v github.com/onsi/ginkgo/ginkgo
|
||||||
- go get -v github.com/onsi/gomega
|
- go get -v github.com/onsi/gomega
|
||||||
|
- go get -v golang.org/x/crypto/ssh
|
||||||
|
- go get github.com/GoASTScanner/gas/cmd/gas/...
|
||||||
- go get -v -t ./...
|
- go get -v -t ./...
|
||||||
- export PATH=$PATH:$HOME/gopath/bin
|
- export PATH=$PATH:$HOME/gopath/bin
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- test -z "$(gofmt -s -l -w $(find . -type f -name '*.go' -not -path './vendor/*') | tee /dev/stderr)"
|
||||||
|
- test -z "$(golint . | tee /dev/stderr)"
|
||||||
|
- go vet $(go list ./... | grep -v /vendor/)
|
||||||
|
- gas ./...
|
||||||
|
|
||||||
script: ginkgo -r
|
script: ginkgo -r
|
||||||
|
|
||||||
|
|
19
Godeps/Godeps.json
generated
19
Godeps/Godeps.json
generated
|
@ -1,8 +1,20 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/GoASTScanner/gas",
|
"ImportPath": "github.com/GoASTScanner/gas",
|
||||||
"GoVersion": "go1.9",
|
"GoVersion": "go1.9",
|
||||||
"GodepVersion": "v79",
|
"GodepVersion": "v80",
|
||||||
|
"Packages": [
|
||||||
|
"./..."
|
||||||
|
],
|
||||||
"Deps": [
|
"Deps": [
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/kisielk/gotool",
|
||||||
|
"Rev": "0de1eaf82fa3f583ce21fde859f1e7e0c5e9b220"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/mozilla/tls-observatory/constants",
|
||||||
|
"Comment": "1.2.32-17-g17e0ce4b",
|
||||||
|
"Rev": "17e0ce4bfc46eae3d57acf13a2d7c7517655d493"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/nbutton23/zxcvbn-go",
|
"ImportPath": "github.com/nbutton23/zxcvbn-go",
|
||||||
"Rev": "a22cb81b2ecdde8b68e9ffb8824731cbf88e1de4"
|
"Rev": "a22cb81b2ecdde8b68e9ffb8824731cbf88e1de4"
|
||||||
|
@ -189,6 +201,11 @@
|
||||||
"Comment": "v1.2.0-2-gdcabb60",
|
"Comment": "v1.2.0-2-gdcabb60",
|
||||||
"Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02"
|
"Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/ryanuber/go-glob",
|
||||||
|
"Comment": "v0.1-4-g256dc44",
|
||||||
|
"Rev": "256dc444b735e061061cf46c809487313d5b0065"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/html",
|
"ImportPath": "golang.org/x/net/html",
|
||||||
"Rev": "8351a756f30f1297fe94bbf4b767ec589c6ea6d0"
|
"Rev": "8351a756f30f1297fe94bbf4b767ec589c6ea6d0"
|
||||||
|
|
21
README.md
21
README.md
|
@ -41,6 +41,7 @@ or to specify a set of rules to explicitly exclude using the '-exclude=' flag.
|
||||||
- G103: Audit the use of unsafe block
|
- G103: Audit the use of unsafe block
|
||||||
- G104: Audit errors not checked
|
- G104: Audit errors not checked
|
||||||
- G105: Audit the use of math/big.Int.Exp
|
- G105: Audit the use of math/big.Int.Exp
|
||||||
|
- G106: Audit the use of ssh.InsecureIgnoreHostKey
|
||||||
- G201: SQL query construction using format string
|
- G201: SQL query construction using format string
|
||||||
- G202: SQL query construction using string concatenation
|
- G202: SQL query construction using string concatenation
|
||||||
- G203: Use of unescaped data in HTML templates
|
- G203: Use of unescaped data in HTML templates
|
||||||
|
@ -104,7 +105,7 @@ $ gas -nosec=true ./...
|
||||||
|
|
||||||
### Output formats
|
### Output formats
|
||||||
|
|
||||||
Gas currently supports text, json and csv output formats. By default
|
Gas currently supports text, json, csv and JUnit XML output formats. By default
|
||||||
results will be reported to stdout, but can also be written to an output
|
results will be reported to stdout, but can also be written to an output
|
||||||
file. The output format is controlled by the '-fmt' flag, and the output file is controlled by the '-out' flag as follows:
|
file. The output format is controlled by the '-fmt' flag, and the output file is controlled by the '-out' flag as follows:
|
||||||
|
|
||||||
|
@ -113,3 +114,21 @@ file. The output format is controlled by the '-fmt' flag, and the output file is
|
||||||
$ gas -fmt=json -out=results.json *.go
|
$ gas -fmt=json -out=results.json *.go
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Generate TLS rule
|
||||||
|
|
||||||
|
The configuration of TLS rule can be generated from [Mozilla's TLS ciphers recommendation](https://statics.tls.security.mozilla.org/server-side-tls-conf.json).
|
||||||
|
|
||||||
|
|
||||||
|
First you need to install the generator tool:
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/GoASTScanner/gas/cmd/tlsconfig/...
|
||||||
|
```
|
||||||
|
|
||||||
|
You can invoke now the `go generate` in the root of the project:
|
||||||
|
|
||||||
|
```
|
||||||
|
go generate ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate the `rules/tls_config.go` file with will contain the current ciphers recommendation from Mozilla.
|
||||||
|
|
|
@ -102,7 +102,10 @@ func (gas *Analyzer) Process(packagePaths ...string) error {
|
||||||
AllowErrors: true,
|
AllowErrors: true,
|
||||||
}
|
}
|
||||||
for _, packagePath := range packagePaths {
|
for _, packagePath := range packagePaths {
|
||||||
abspath, _ := filepath.Abs(packagePath)
|
abspath, err := filepath.Abs(packagePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
gas.logger.Println("Searching directory:", abspath)
|
gas.logger.Println("Searching directory:", abspath)
|
||||||
|
|
||||||
basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment)
|
basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment)
|
||||||
|
|
|
@ -59,7 +59,7 @@ var (
|
||||||
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
|
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
|
||||||
|
|
||||||
// format output
|
// format output
|
||||||
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, csv, html, or text")
|
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, csv, junit-xml, html, or text")
|
||||||
|
|
||||||
// output file
|
// output file
|
||||||
flagOutput = flag.String("out", "", "Set output file for results")
|
flagOutput = flag.String("out", "", "Set output file for results")
|
||||||
|
@ -79,6 +79,9 @@ var (
|
||||||
// log to file or stderr
|
// log to file or stderr
|
||||||
flagLogfile = flag.String("log", "", "Log messages to file rather than stderr")
|
flagLogfile = flag.String("log", "", "Log messages to file rather than stderr")
|
||||||
|
|
||||||
|
// sort the issues by severity
|
||||||
|
flagSortIssues = flag.Bool("sort", true, "Sort issues by severity")
|
||||||
|
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -149,9 +152,15 @@ func saveOutput(filename, format string, issues []*gas.Issue, metrics *gas.Metri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer outfile.Close()
|
defer outfile.Close()
|
||||||
output.CreateReport(outfile, format, issues, metrics)
|
err = output.CreateReport(outfile, format, issues, metrics)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
output.CreateReport(os.Stdout, format, issues, metrics)
|
err := output.CreateReport(os.Stdout, format, issues, metrics)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -166,7 +175,7 @@ func main() {
|
||||||
|
|
||||||
// Ensure at least one file was specified
|
// Ensure at least one file was specified
|
||||||
if flag.NArg() == 0 {
|
if flag.NArg() == 0 {
|
||||||
fmt.Fprintf(os.Stderr, "\nError: FILE [FILE...] or './...' expected\n")
|
fmt.Fprintf(os.Stderr, "\nError: FILE [FILE...] or './...' expected\n") // #nosec
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
@ -225,13 +234,18 @@ func main() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort the issue by severity
|
||||||
|
if *flagSortIssues {
|
||||||
|
sortIssues(issues)
|
||||||
|
}
|
||||||
|
|
||||||
// Create output report
|
// Create output report
|
||||||
if err := saveOutput(*flagOutput, *flagFormat, issues, metrics); err != nil {
|
if err := saveOutput(*flagOutput, *flagFormat, issues, metrics); err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finialize logging
|
// Finialize logging
|
||||||
logWriter.Close()
|
logWriter.Close() // #nosec
|
||||||
|
|
||||||
// Do we have an issue? If so exit 1
|
// Do we have an issue? If so exit 1
|
||||||
if issuesFound {
|
if issuesFound {
|
||||||
|
|
20
cmd/gas/sort_issues.go
Normal file
20
cmd/gas/sort_issues.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/GoASTScanner/gas"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sortBySeverity []*gas.Issue
|
||||||
|
|
||||||
|
func (s sortBySeverity) Len() int { return len(s) }
|
||||||
|
|
||||||
|
func (s sortBySeverity) Less(i, j int) bool { return s[i].Severity > s[i].Severity }
|
||||||
|
|
||||||
|
func (s sortBySeverity) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
|
||||||
|
// sortIssues sorts the issues by severity in descending order
|
||||||
|
func sortIssues(issues []*gas.Issue) {
|
||||||
|
sort.Sort(sortBySeverity(issues))
|
||||||
|
}
|
13
cmd/tlsconfig/header_template.go
Normal file
13
cmd/tlsconfig/header_template.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "text/template"
|
||||||
|
|
||||||
|
var generatedHeaderTmpl = template.Must(template.New("generated").Parse(`
|
||||||
|
package {{.}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"github.com/GoASTScanner/gas"
|
||||||
|
)
|
||||||
|
`))
|
19
cmd/tlsconfig/rule_template.go
Normal file
19
cmd/tlsconfig/rule_template.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "text/template"
|
||||||
|
|
||||||
|
var generatedRuleTmpl = template.Must(template.New("generated").Parse(`
|
||||||
|
// New{{.Name}}TLSCheck creates a check for {{.Name}} TLS ciphers
|
||||||
|
// DO NOT EDIT - generated by tlsconfig tool
|
||||||
|
func New{{.Name}}TLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
|
return &insecureConfigTLS{
|
||||||
|
requiredType: "crypto/tls.Config",
|
||||||
|
MinVersion: {{ .MinVersion }},
|
||||||
|
MaxVersion: {{ .MaxVersion }},
|
||||||
|
goodCiphers: []string{
|
||||||
|
{{range $cipherName := .Ciphers }} "{{$cipherName}}",
|
||||||
|
{{end}}
|
||||||
|
},
|
||||||
|
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||||
|
}
|
||||||
|
`))
|
204
cmd/tlsconfig/tlsconfig.go
Normal file
204
cmd/tlsconfig/tlsconfig.go
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mozilla/tls-observatory/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
pkg = flag.String("pkg", "rules", "package name to be added to the output file")
|
||||||
|
outputFile = flag.String("outputFile", "tls_config.go", "name of the output file")
|
||||||
|
)
|
||||||
|
|
||||||
|
// TLSConfURL url where Mozilla publishes the TLS ciphers recommendations
|
||||||
|
const TLSConfURL = "https://statics.tls.security.mozilla.org/server-side-tls-conf.json"
|
||||||
|
|
||||||
|
// ServerSideTLSJson contains all the available configurations and the version of the current document.
|
||||||
|
type ServerSideTLSJson struct {
|
||||||
|
Configurations map[string]Configuration `json:"configurations"`
|
||||||
|
Version float64 `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration represents configurations levels declared by the Mozilla server-side-tls
|
||||||
|
// see https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
|
type Configuration struct {
|
||||||
|
OpenSSLCiphersuites string `json:"openssl_ciphersuites"`
|
||||||
|
Ciphersuites []string `json:"ciphersuites"`
|
||||||
|
TLSVersions []string `json:"tls_versions"`
|
||||||
|
TLSCurves []string `json:"tls_curves"`
|
||||||
|
CertificateTypes []string `json:"certificate_types"`
|
||||||
|
CertificateCurves []string `json:"certificate_curves"`
|
||||||
|
CertificateSignatures []string `json:"certificate_signatures"`
|
||||||
|
RsaKeySize float64 `json:"rsa_key_size"`
|
||||||
|
DHParamSize float64 `json:"dh_param_size"`
|
||||||
|
ECDHParamSize float64 `json:"ecdh_param_size"`
|
||||||
|
HstsMinAge float64 `json:"hsts_min_age"`
|
||||||
|
OldestClients []string `json:"oldest_clients"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type goCipherConfiguration struct {
|
||||||
|
Name string
|
||||||
|
Ciphers []string
|
||||||
|
MinVersion string
|
||||||
|
MaxVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
type goTLSConfiguration struct {
|
||||||
|
cipherConfigs []goCipherConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTLSConfFromURL retrieves the json containing the TLS configurations from the specified URL.
|
||||||
|
func getTLSConfFromURL(url string) (*ServerSideTLSJson, error) {
|
||||||
|
r, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
var sstls ServerSideTLSJson
|
||||||
|
err = json.NewDecoder(r.Body).Decode(&sstls)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sstls, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGoCipherConfig(name string, sstls ServerSideTLSJson) (goCipherConfiguration, error) {
|
||||||
|
cipherConf := goCipherConfiguration{Name: strings.Title(name)}
|
||||||
|
conf, ok := sstls.Configurations[name]
|
||||||
|
if !ok {
|
||||||
|
return cipherConf, fmt.Errorf("TLS configuration '%s' not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cipherName := range conf.Ciphersuites {
|
||||||
|
cipherSuite, ok := constants.CipherSuites[cipherName]
|
||||||
|
if !ok {
|
||||||
|
log.Printf("Warning: cannot map cipher '%s'\n", cipherName)
|
||||||
|
}
|
||||||
|
if len(cipherSuite.IANAName) > 0 {
|
||||||
|
cipherConf.Ciphers = append(cipherConf.Ciphers, cipherSuite.IANAName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
versions := mapTLSVersions(conf.TLSVersions)
|
||||||
|
if len(versions) > 0 {
|
||||||
|
cipherConf.MinVersion = fmt.Sprintf("0x%04x", versions[0])
|
||||||
|
cipherConf.MaxVersion = fmt.Sprintf("0x%04x", versions[len(versions)-1])
|
||||||
|
} else {
|
||||||
|
return cipherConf, fmt.Errorf("No TLS versions found for configuration '%s'", name)
|
||||||
|
}
|
||||||
|
return cipherConf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapTLSVersions(tlsVersions []string) []int {
|
||||||
|
var versions []int
|
||||||
|
for _, tlsVersion := range tlsVersions {
|
||||||
|
switch tlsVersion {
|
||||||
|
case "TLSv1.2":
|
||||||
|
versions = append(versions, tls.VersionTLS12)
|
||||||
|
case "TLSv1.1":
|
||||||
|
versions = append(versions, tls.VersionTLS11)
|
||||||
|
case "TLSv1":
|
||||||
|
versions = append(versions, tls.VersionTLS10)
|
||||||
|
case "SSLv3":
|
||||||
|
versions = append(versions, tls.VersionSSL30)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Ints(versions)
|
||||||
|
return versions
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGoTLSConf() (goTLSConfiguration, error) {
|
||||||
|
sstls, err := getTLSConfFromURL(TLSConfURL)
|
||||||
|
if err != nil || sstls == nil {
|
||||||
|
msg := fmt.Sprintf("Could not load the Server Side TLS configuration from Mozilla's website. Check the URL: %s. Error: %v\n",
|
||||||
|
TLSConfURL, err)
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfg := goTLSConfiguration{}
|
||||||
|
|
||||||
|
modern, err := getGoCipherConfig("modern", *sstls)
|
||||||
|
if err != nil {
|
||||||
|
return tlsConfg, err
|
||||||
|
}
|
||||||
|
tlsConfg.cipherConfigs = append(tlsConfg.cipherConfigs, modern)
|
||||||
|
|
||||||
|
intermediate, err := getGoCipherConfig("intermediate", *sstls)
|
||||||
|
if err != nil {
|
||||||
|
return tlsConfg, err
|
||||||
|
}
|
||||||
|
tlsConfg.cipherConfigs = append(tlsConfg.cipherConfigs, intermediate)
|
||||||
|
|
||||||
|
old, err := getGoCipherConfig("old", *sstls)
|
||||||
|
if err != nil {
|
||||||
|
return tlsConfg, err
|
||||||
|
}
|
||||||
|
tlsConfg.cipherConfigs = append(tlsConfg.cipherConfigs, old)
|
||||||
|
|
||||||
|
return tlsConfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCurrentDir() (string, error) {
|
||||||
|
dir := "."
|
||||||
|
if args := flag.Args(); len(args) == 1 {
|
||||||
|
dir = args[0]
|
||||||
|
} else if len(args) > 1 {
|
||||||
|
return "", errors.New("only one directory at a time")
|
||||||
|
}
|
||||||
|
dir, err := filepath.Abs(dir)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
dir, err := getCurrentDir()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
tlsConfig, err := getGoTLSConf()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err = generatedHeaderTmpl.Execute(&buf, *pkg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to generate the header: %v", err)
|
||||||
|
}
|
||||||
|
for _, cipherConfig := range tlsConfig.cipherConfigs {
|
||||||
|
err := generatedRuleTmpl.Execute(&buf, cipherConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to generated the cipher config: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src, err := format.Source(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("warnings: Failed to format the code: %v", err)
|
||||||
|
src = buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath := filepath.Join(dir, *outputFile)
|
||||||
|
if err := ioutil.WriteFile(outputPath, src, 0644); err != nil {
|
||||||
|
log.Fatalf("Writing output: %s", err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,30 +0,0 @@
|
||||||
package gas_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("ImportTracker", func() {
|
|
||||||
var (
|
|
||||||
source string
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
source = `// TODO(gm)`
|
|
||||||
})
|
|
||||||
Context("when I have a valid go package", func() {
|
|
||||||
It("should record all import specs", func() {
|
|
||||||
Expect(source).To(Equal(source))
|
|
||||||
Skip("Not implemented")
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should correctly track aliased package imports", func() {
|
|
||||||
Skip("Not implemented")
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should correctly track init only packages", func() {
|
|
||||||
Skip("Not implemented")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
2
issue.go
2
issue.go
|
@ -76,7 +76,7 @@ func codeSnippet(file *os.File, start int64, end int64, n ast.Node) (string, err
|
||||||
}
|
}
|
||||||
|
|
||||||
size := (int)(end - start) // Go bug, os.File.Read should return int64 ...
|
size := (int)(end - start) // Go bug, os.File.Read should return int64 ...
|
||||||
file.Seek(start, 0)
|
file.Seek(start, 0) // #nosec
|
||||||
|
|
||||||
buf := make([]byte, size)
|
buf := make([]byte, size)
|
||||||
if nread, err := file.Read(buf); err != nil || nread != size {
|
if nread, err := file.Read(buf); err != nil || nread != size {
|
||||||
|
|
|
@ -17,6 +17,7 @@ package output
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
htmlTemplate "html/template"
|
htmlTemplate "html/template"
|
||||||
"io"
|
"io"
|
||||||
plainTemplate "text/template"
|
plainTemplate "text/template"
|
||||||
|
@ -36,6 +37,9 @@ const (
|
||||||
|
|
||||||
// ReportCSV set the output format to csv
|
// ReportCSV set the output format to csv
|
||||||
ReportCSV // CSV format
|
ReportCSV // CSV format
|
||||||
|
|
||||||
|
// ReportJUnitXML set the output format to junit xml
|
||||||
|
ReportJUnitXML // JUnit XML format
|
||||||
)
|
)
|
||||||
|
|
||||||
var text = `Results:
|
var text = `Results:
|
||||||
|
@ -70,6 +74,8 @@ func CreateReport(w io.Writer, format string, issues []*gas.Issue, metrics *gas.
|
||||||
err = reportJSON(w, data)
|
err = reportJSON(w, data)
|
||||||
case "csv":
|
case "csv":
|
||||||
err = reportCSV(w, data)
|
err = reportCSV(w, data)
|
||||||
|
case "junit-xml":
|
||||||
|
err = reportJUnitXML(w, data)
|
||||||
case "html":
|
case "html":
|
||||||
err = reportFromHTMLTemplate(w, html, data)
|
err = reportFromHTMLTemplate(w, html, data)
|
||||||
case "text":
|
case "text":
|
||||||
|
@ -112,6 +118,25 @@ func reportCSV(w io.Writer, data *reportInfo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reportJUnitXML(w io.Writer, data *reportInfo) error {
|
||||||
|
groupedData := groupDataByRules(data)
|
||||||
|
junitXMLStruct := createJUnitXMLStruct(groupedData)
|
||||||
|
|
||||||
|
raw, err := xml.MarshalIndent(junitXMLStruct, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlHeader := []byte("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
|
||||||
|
raw = append(xmlHeader, raw...)
|
||||||
|
_, err = w.Write(raw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
|
func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
|
||||||
t, e := plainTemplate.New("gas").Parse(reportTemplate)
|
t, e := plainTemplate.New("gas").Parse(reportTemplate)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
|
74
output/junit_xml_format.go
Normal file
74
output/junit_xml_format.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package output
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
htmlLib "html"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/GoASTScanner/gas"
|
||||||
|
)
|
||||||
|
|
||||||
|
type junitXMLReport struct {
|
||||||
|
XMLName xml.Name `xml:"testsuites"`
|
||||||
|
Testsuites []testsuite `xml:"testsuite"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type testsuite struct {
|
||||||
|
XMLName xml.Name `xml:"testsuite"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Tests int `xml:"tests,attr"`
|
||||||
|
Testcases []testcase `xml:"testcase"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type testcase struct {
|
||||||
|
XMLName xml.Name `xml:"testcase"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Failure failure `xml:"failure"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type failure struct {
|
||||||
|
XMLName xml.Name `xml:"failure"`
|
||||||
|
Message string `xml:"message,attr"`
|
||||||
|
Text string `xml:",innerxml"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func generatePlaintext(issue *gas.Issue) string {
|
||||||
|
return "Results:\n" +
|
||||||
|
"[" + issue.File + ":" + issue.Line + "] - " +
|
||||||
|
issue.What + " (Confidence: " + strconv.Itoa(int(issue.Confidence)) +
|
||||||
|
", Severity: " + strconv.Itoa(int(issue.Severity)) + ")\n" + "> " + htmlLib.EscapeString(issue.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupDataByRules(data *reportInfo) map[string][]*gas.Issue {
|
||||||
|
groupedData := make(map[string][]*gas.Issue)
|
||||||
|
for _, issue := range data.Issues {
|
||||||
|
if _, ok := groupedData[issue.What]; ok {
|
||||||
|
groupedData[issue.What] = append(groupedData[issue.What], issue)
|
||||||
|
} else {
|
||||||
|
groupedData[issue.What] = []*gas.Issue{issue}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groupedData
|
||||||
|
}
|
||||||
|
|
||||||
|
func createJUnitXMLStruct(groupedData map[string][]*gas.Issue) junitXMLReport {
|
||||||
|
var xmlReport junitXMLReport
|
||||||
|
for what, issues := range groupedData {
|
||||||
|
testsuite := testsuite{
|
||||||
|
Name: what,
|
||||||
|
Tests: len(issues),
|
||||||
|
}
|
||||||
|
for _, issue := range issues {
|
||||||
|
testcase := testcase{
|
||||||
|
Name: issue.File,
|
||||||
|
Failure: failure{
|
||||||
|
Message: "Found 1 vulnerability. See stacktrace for details.",
|
||||||
|
Text: generatePlaintext(issue),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testsuite.Testcases = append(testsuite.Testcases, testcase)
|
||||||
|
}
|
||||||
|
xmlReport.Testsuites = append(xmlReport.Testsuites, testsuite)
|
||||||
|
}
|
||||||
|
return xmlReport
|
||||||
|
}
|
|
@ -77,7 +77,7 @@ func NewNoErrorCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
// black list instead.
|
// black list instead.
|
||||||
whitelist := gas.NewCallList()
|
whitelist := gas.NewCallList()
|
||||||
whitelist.AddAll("bytes.Buffer", "Write", "WriteByte", "WriteRune", "WriteString")
|
whitelist.AddAll("bytes.Buffer", "Write", "WriteByte", "WriteRune", "WriteString")
|
||||||
whitelist.AddAll("fmt", "Print", "Printf", "Println")
|
whitelist.AddAll("fmt", "Print", "Printf", "Println", "Fprint", "Fprintf", "Fprintln")
|
||||||
whitelist.Add("io.PipeWriter", "CloseWithError")
|
whitelist.Add("io.PipeWriter", "CloseWithError")
|
||||||
|
|
||||||
if configured, ok := conf["G104"]; ok {
|
if configured, ok := conf["G104"]; ok {
|
||||||
|
|
|
@ -75,7 +75,7 @@ func NewFilePerms(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
// NewMkdirPerms creates a rule to detect directory creation with more permissive than
|
// NewMkdirPerms creates a rule to detect directory creation with more permissive than
|
||||||
// configured permission mask.
|
// configured permission mask.
|
||||||
func NewMkdirPerms(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewMkdirPerms(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
mode := getConfiguredMode(conf, "G301", 0700)
|
mode := getConfiguredMode(conf, "G301", 0750)
|
||||||
return &filePermissions{
|
return &filePermissions{
|
||||||
mode: mode,
|
mode: mode,
|
||||||
pkg: "os",
|
pkg: "os",
|
||||||
|
|
|
@ -60,34 +60,35 @@ func NewRuleFilter(action bool, ruleIDs ...string) RuleFilter {
|
||||||
func Generate(filters ...RuleFilter) RuleList {
|
func Generate(filters ...RuleFilter) RuleList {
|
||||||
rules := map[string]RuleDefinition{
|
rules := map[string]RuleDefinition{
|
||||||
// misc
|
// misc
|
||||||
"G101": RuleDefinition{"Look for hardcoded credentials", NewHardcodedCredentials},
|
"G101": {"Look for hardcoded credentials", NewHardcodedCredentials},
|
||||||
"G102": RuleDefinition{"Bind to all interfaces", NewBindsToAllNetworkInterfaces},
|
"G102": {"Bind to all interfaces", NewBindsToAllNetworkInterfaces},
|
||||||
"G103": RuleDefinition{"Audit the use of unsafe block", NewUsingUnsafe},
|
"G103": {"Audit the use of unsafe block", NewUsingUnsafe},
|
||||||
"G104": RuleDefinition{"Audit errors not checked", NewNoErrorCheck},
|
"G104": {"Audit errors not checked", NewNoErrorCheck},
|
||||||
"G105": RuleDefinition{"Audit the use of big.Exp function", NewUsingBigExp},
|
"G105": {"Audit the use of big.Exp function", NewUsingBigExp},
|
||||||
|
"G106": {"Audit the use of ssh.InsecureIgnoreHostKey function", NewSSHHostKey},
|
||||||
|
|
||||||
// injection
|
// injection
|
||||||
"G201": RuleDefinition{"SQL query construction using format string", NewSQLStrFormat},
|
"G201": {"SQL query construction using format string", NewSQLStrFormat},
|
||||||
"G202": RuleDefinition{"SQL query construction using string concatenation", NewSQLStrConcat},
|
"G202": {"SQL query construction using string concatenation", NewSQLStrConcat},
|
||||||
"G203": RuleDefinition{"Use of unescaped data in HTML templates", NewTemplateCheck},
|
"G203": {"Use of unescaped data in HTML templates", NewTemplateCheck},
|
||||||
"G204": RuleDefinition{"Audit use of command execution", NewSubproc},
|
"G204": {"Audit use of command execution", NewSubproc},
|
||||||
|
|
||||||
// filesystem
|
// filesystem
|
||||||
"G301": RuleDefinition{"Poor file permissions used when creating a directory", NewMkdirPerms},
|
"G301": {"Poor file permissions used when creating a directory", NewMkdirPerms},
|
||||||
"G302": RuleDefinition{"Poor file permisions used when creation file or using chmod", NewFilePerms},
|
"G302": {"Poor file permisions used when creation file or using chmod", NewFilePerms},
|
||||||
"G303": RuleDefinition{"Creating tempfile using a predictable path", NewBadTempFile},
|
"G303": {"Creating tempfile using a predictable path", NewBadTempFile},
|
||||||
|
|
||||||
// crypto
|
// crypto
|
||||||
"G401": RuleDefinition{"Detect the usage of DES, RC4, or MD5", NewUsesWeakCryptography},
|
"G401": {"Detect the usage of DES, RC4, or MD5", NewUsesWeakCryptography},
|
||||||
"G402": RuleDefinition{"Look for bad TLS connection settings", NewIntermediateTLSCheck},
|
"G402": {"Look for bad TLS connection settings", NewIntermediateTLSCheck},
|
||||||
"G403": RuleDefinition{"Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength},
|
"G403": {"Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength},
|
||||||
"G404": RuleDefinition{"Insecure random number source (rand)", NewWeakRandCheck},
|
"G404": {"Insecure random number source (rand)", NewWeakRandCheck},
|
||||||
|
|
||||||
// blacklist
|
// blacklist
|
||||||
"G501": RuleDefinition{"Import blacklist: crypto/md5", NewBlacklistedImportMD5},
|
"G501": {"Import blacklist: crypto/md5", NewBlacklistedImportMD5},
|
||||||
"G502": RuleDefinition{"Import blacklist: crypto/des", NewBlacklistedImportDES},
|
"G502": {"Import blacklist: crypto/des", NewBlacklistedImportDES},
|
||||||
"G503": RuleDefinition{"Import blacklist: crypto/rc4", NewBlacklistedImportRC4},
|
"G503": {"Import blacklist: crypto/rc4", NewBlacklistedImportRC4},
|
||||||
"G504": RuleDefinition{"Import blacklist: net/http/cgi", NewBlacklistedImportCGI},
|
"G504": {"Import blacklist: net/http/cgi", NewBlacklistedImportCGI},
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule := range rules {
|
for rule := range rules {
|
||||||
|
|
|
@ -65,6 +65,10 @@ var _ = Describe("gas rules", func() {
|
||||||
runner("G105", testutils.SampleCodeG105)
|
runner("G105", testutils.SampleCodeG105)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should detect of ssh.InsecureIgnoreHostKey function", func() {
|
||||||
|
runner("G106", testutils.SampleCodeG106)
|
||||||
|
})
|
||||||
|
|
||||||
It("should detect sql injection via format strings", func() {
|
It("should detect sql injection via format strings", func() {
|
||||||
runner("G201", testutils.SampleCodeG201)
|
runner("G201", testutils.SampleCodeG201)
|
||||||
})
|
})
|
||||||
|
|
33
rules/ssh.go
Normal file
33
rules/ssh.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"github.com/GoASTScanner/gas"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sshHostKey struct {
|
||||||
|
gas.MetaData
|
||||||
|
pkg string
|
||||||
|
calls []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *sshHostKey) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||||
|
if _, matches := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||||
|
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSSHHostKey rule detects the use of insecure ssh HostKeyCallback.
|
||||||
|
func NewSSHHostKey(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
|
return &sshHostKey{
|
||||||
|
pkg: "golang.org/x/crypto/ssh",
|
||||||
|
calls: []string{"InsecureIgnoreHostKey"},
|
||||||
|
MetaData: gas.MetaData{
|
||||||
|
What: "Use of ssh InsecureIgnoreHostKey should be audited",
|
||||||
|
Severity: gas.Medium,
|
||||||
|
Confidence: gas.High,
|
||||||
|
},
|
||||||
|
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||||
|
}
|
88
rules/tls.go
88
rules/tls.go
|
@ -12,6 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:generate tlsconfig
|
||||||
|
|
||||||
package rules
|
package rules
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -106,86 +108,18 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Contex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||||
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil && c.Info.TypeOf(complit.Type).String() == t.requiredType {
|
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
|
||||||
for _, elt := range complit.Elts {
|
actualType := c.Info.TypeOf(complit.Type)
|
||||||
if kve, ok := elt.(*ast.KeyValueExpr); ok {
|
if actualType != nil && actualType.String() == t.requiredType {
|
||||||
issue := t.processTLSConfVal(kve, c)
|
for _, elt := range complit.Elts {
|
||||||
if issue != nil {
|
if kve, ok := elt.(*ast.KeyValueExpr); ok {
|
||||||
return issue, nil
|
issue := t.processTLSConfVal(kve, c)
|
||||||
|
if issue != nil {
|
||||||
|
return issue, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewModernTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
|
|
||||||
func NewModernTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
|
||||||
return &insecureConfigTLS{
|
|
||||||
requiredType: "crypto/tls.Config",
|
|
||||||
MinVersion: 0x0303, // TLS 1.2 only
|
|
||||||
MaxVersion: 0x0303,
|
|
||||||
goodCiphers: []string{
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
|
||||||
},
|
|
||||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewIntermediateTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
|
|
||||||
func NewIntermediateTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
|
||||||
return &insecureConfigTLS{
|
|
||||||
requiredType: "crypto/tls.Config",
|
|
||||||
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
|
|
||||||
MaxVersion: 0x0303,
|
|
||||||
goodCiphers: []string{
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
},
|
|
||||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCompatTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Old_compatibility_.28default.29
|
|
||||||
func NewCompatTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
|
||||||
return &insecureConfigTLS{
|
|
||||||
requiredType: "crypto/tls.Config",
|
|
||||||
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
|
|
||||||
MaxVersion: 0x0303,
|
|
||||||
goodCiphers: []string{
|
|
||||||
"TLS_RSA_WITH_RC4_128_SHA",
|
|
||||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
},
|
|
||||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
|
||||||
}
|
|
||||||
|
|
132
rules/tls_config.go
Normal file
132
rules/tls_config.go
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"github.com/GoASTScanner/gas"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewModernTLSCheck creates a check for Modern TLS ciphers
|
||||||
|
// DO NOT EDIT - generated by tlsconfig tool
|
||||||
|
func NewModernTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
|
return &insecureConfigTLS{
|
||||||
|
requiredType: "crypto/tls.Config",
|
||||||
|
MinVersion: 0x0303,
|
||||||
|
MaxVersion: 0x0303,
|
||||||
|
goodCiphers: []string{
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
},
|
||||||
|
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIntermediateTLSCheck creates a check for Intermediate TLS ciphers
|
||||||
|
// DO NOT EDIT - generated by tlsconfig tool
|
||||||
|
func NewIntermediateTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
|
return &insecureConfigTLS{
|
||||||
|
requiredType: "crypto/tls.Config",
|
||||||
|
MinVersion: 0x0301,
|
||||||
|
MaxVersion: 0x0303,
|
||||||
|
goodCiphers: []string{
|
||||||
|
"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_DHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
},
|
||||||
|
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOldTLSCheck creates a check for Old TLS ciphers
|
||||||
|
// DO NOT EDIT - generated by tlsconfig tool
|
||||||
|
func NewOldTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
|
return &insecureConfigTLS{
|
||||||
|
requiredType: "crypto/tls.Config",
|
||||||
|
MinVersion: 0x0300,
|
||||||
|
MaxVersion: 0x0303,
|
||||||
|
goodCiphers: []string{
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
||||||
|
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
|
||||||
|
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||||
|
"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
||||||
|
"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
||||||
|
"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||||
|
"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
|
||||||
|
"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
||||||
|
"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
||||||
|
"TLS_DHE_RSA_WITH_SEED_CBC_SHA",
|
||||||
|
"TLS_DHE_DSS_WITH_SEED_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_SEED_CBC_SHA",
|
||||||
|
},
|
||||||
|
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||||
|
}
|
|
@ -128,6 +128,7 @@ func (p *TestPackage) CreateContext(filename string) *gas.Context {
|
||||||
// Close will delete the package and all files in that directory
|
// Close will delete the package and all files in that directory
|
||||||
func (p *TestPackage) Close() {
|
func (p *TestPackage) Close() {
|
||||||
if p.ondisk {
|
if p.ondisk {
|
||||||
os.RemoveAll(p.Path)
|
err := os.RemoveAll(p.Path)
|
||||||
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,15 @@ func main() {
|
||||||
z = z.Exp(x, y, m)
|
z = z.Exp(x, y, m)
|
||||||
}`, 1}}
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG106 - ssh InsecureIgnoreHostKey
|
||||||
|
SampleCodeG106 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
_ = ssh.InsecureIgnoreHostKey()
|
||||||
|
}`, 1}}
|
||||||
// SampleCodeG201 - SQL injection via format string
|
// SampleCodeG201 - SQL injection via format string
|
||||||
SampleCodeG201 = []CodeSample{
|
SampleCodeG201 = []CodeSample{
|
||||||
{`
|
{`
|
||||||
|
|
Loading…
Reference in a new issue