Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge experimental / refactor #146

Merged
merged 26 commits into from
Jan 5, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9b08174
Process via packages instead of files
gcmurphy Apr 25, 2017
8df48f9
Fix to reporting to use output formats
gcmurphy Apr 26, 2017
cacf21f
Restructure to focus on lib rather than cli
gcmurphy Apr 26, 2017
bf78d02
Restructure and introduce a standalone config
gcmurphy Apr 28, 2017
50bbc53
Isolate import tracking functionality
gcmurphy May 10, 2017
5160048
Move rule definitions into own file
gcmurphy May 10, 2017
65b18da
Hack to address circular dependency in rulelist
gcmurphy May 10, 2017
026fe4c
Simplify analyzer and command line interface
gcmurphy May 10, 2017
f4b705a
Use glide to manage vendored dependencies
gcmurphy May 10, 2017
6943f9e
Major rework of codebase
gcmurphy Jul 19, 2017
3caf7c3
Add test cases
gcmurphy Sep 16, 2017
9c959ca
Issue.Line is already a string
lanzafame Oct 1, 2017
5a11336
remove commited binary
lanzafame Oct 1, 2017
27b2fd9
Merge pull request #136 from lanzafame/experimental
gcmurphy Oct 4, 2017
67dc432
use godep instead of glide
gcmurphy Dec 13, 2017
d4311c9
make it clear that these tests have not been implemented yet
gcmurphy Dec 13, 2017
02901b9
actually skip tests until implementation exists
gcmurphy Dec 13, 2017
e3b6fd9
update readme to provide info regarding package level scans
gcmurphy Dec 13, 2017
97cde35
update travis-ci to use ginkgo tests
gcmurphy Dec 13, 2017
cfa4327
fix hound-ci errors
gcmurphy Dec 13, 2017
af25ac1
fix golint errors picked up by hound-ci
gcmurphy Dec 13, 2017
25d74c6
address review comments
gcmurphy Dec 14, 2017
e925d3c
Migrated old test cases.
gcmurphy Dec 28, 2017
4c49716
move utils to separate executable
gcmurphy Dec 28, 2017
d452dcb
Fix ginko invocation
gcmurphy Jan 5, 2018
867d300
Fix lint issues
gcmurphy Jan 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Migrated old test cases.
  • Loading branch information
gcmurphy committed Dec 28, 2017
commit e925d3c34794f158471980ff05df9dd63601e16b
1 change: 1 addition & 0 deletions call_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (c CallList) ContainsCallExpr(n ast.Node, ctx *Context) *ast.CallExpr {
if err != nil {
return nil
}

// Try direct resolution
if c.Contains(selector, ident) {
return n.(*ast.CallExpr)
Expand Down
22 changes: 14 additions & 8 deletions rules/blacklist.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package rules

import (
"go/ast"
"strings"

"github.com/GoASTScanner/gas"
)
Expand All @@ -25,11 +26,16 @@ type blacklistedImport struct {
Blacklisted map[string]string
}

func (r *blacklistedImport) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
func unquote(original string) string {
copy := strings.TrimSpace(original)
copy = strings.TrimLeft(copy, `"`)
return strings.TrimRight(copy, `"`)
}

func (r *blacklistedImport) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
if node, ok := n.(*ast.ImportSpec); ok {
description, ok := r.Blacklisted[node.Path.Value]
if ok && node.Name.String() != "_" {
return gas.NewIssue(c, n, description, r.Severity, r.Confidence), nil
if description, ok := r.Blacklisted[unquote(node.Path.Value)]; ok {
return gas.NewIssue(c, node, description, r.Severity, r.Confidence), nil
}
}
return nil, nil
Expand All @@ -50,27 +56,27 @@ func NewBlacklistedImports(conf gas.Config, blacklist map[string]string) (gas.Ru
// NewBlacklistedImportMD5 fails if MD5 is imported
func NewBlacklistedImportMD5(conf gas.Config) (gas.Rule, []ast.Node) {
return NewBlacklistedImports(conf, map[string]string{
"crypto/md5": "Use of weak cryptographic primitive",
"crypto/md5": "Blacklisted import crypto/md5: weak cryptographic primitive",
})
}

// NewBlacklistedImportDES fails if DES is imported
func NewBlacklistedImportDES(conf gas.Config) (gas.Rule, []ast.Node) {
return NewBlacklistedImports(conf, map[string]string{
"crypto/des": "Use of weak cryptographic primitive",
"crypto/des": "Blacklisted import crypto/des: weak cryptographic primitive",
})
}

// NewBlacklistedImportRC4 fails if DES is imported
func NewBlacklistedImportRC4(conf gas.Config) (gas.Rule, []ast.Node) {
return NewBlacklistedImports(conf, map[string]string{
"crypto/rc4": "Use of weak cryptographic primitive",
"crypto/rc4": "Blacklisted import crypto/rc4: weak cryptographic primitive",
})
}

// NewBlacklistedImportCGI fails if CGI is imported
func NewBlacklistedImportCGI(conf gas.Config) (gas.Rule, []ast.Node) {
return NewBlacklistedImports(conf, map[string]string{
"net/http/cgi": "Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386)",
"net/http/cgi": "Blacklisted import net/http/cgi: Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386)",
})
}
72 changes: 68 additions & 4 deletions rules/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,86 @@ var _ = Describe("gas rules", func() {
})

Context("report correct errors for all samples", func() {
It("should work for G101 samples", func() {
It("should detect hardcoded credentials", func() {
runner("G101", testutils.SampleCodeG101)
})

It("should work for G102 samples", func() {
It("should detect binding to all network interfaces", func() {
runner("G102", testutils.SampleCodeG102)
})

It("should work for G103 samples", func() {
It("should use of unsafe block", func() {
runner("G103", testutils.SampleCodeG103)
})

It("should work for G104 samples", func() {
It("should errors not being checked", func() {
runner("G104", testutils.SampleCodeG104)
})

It("should detect of big.Exp function", func() {
runner("G105", testutils.SampleCodeG105)
})

It("should detect sql injection via format strings", func() {
runner("G201", testutils.SampleCodeG201)
})

It("should detect sql injection via string concatenation", func() {
runner("G202", testutils.SampleCodeG202)
})

It("should detect unescaped html in templates", func() {
runner("G203", testutils.SampleCodeG203)
})

It("should detect command execution", func() {
runner("G204", testutils.SampleCodeG204)
})

It("should detect poor file permissions on mkdir", func() {
runner("G301", testutils.SampleCodeG301)
})

It("should detect poor permissions when creating or chmod a file", func() {
runner("G302", testutils.SampleCodeG302)
})

It("should detect insecure temp file creation", func() {
runner("G303", testutils.SampleCodeG303)
})

It("should detect weak crypto algorithms", func() {
runner("G401", testutils.SampleCodeG401)
})

It("should find insecure tls settings", func() {
runner("G402", testutils.SampleCodeG402)
})

It("should detect weak creation of weak rsa keys", func() {
runner("G403", testutils.SampleCodeG403)
})

It("should find non cryptographically secure random number sources", func() {
runner("G404", testutils.SampleCodeG404)
})

It("should detect blacklisted imports - MD5", func() {
runner("G501", testutils.SampleCodeG501)
})

It("should detect blacklisted imports - DES", func() {
runner("G502", testutils.SampleCodeG502)
})

It("should detect blacklisted imports - RC4", func() {
runner("G503", testutils.SampleCodeG503)
})

It("should detect blacklisted imports - CGI (httpoxy)", func() {
runner("G504", testutils.SampleCodeG504)
})

})

})
3 changes: 2 additions & 1 deletion rules/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ func NewTemplateCheck(conf gas.Config) (gas.Rule, []ast.Node) {
calls.Add("template", "HTML")
calls.Add("template", "HTMLAttr")
calls.Add("template", "JS")
calls.Add("template", "URL")
return &templateCheck{
calls: gas.NewCallList(),
calls: calls,
MetaData: gas.MetaData{
Severity: gas.Medium,
Confidence: gas.Low,
Expand Down
45 changes: 18 additions & 27 deletions rules/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,13 @@ func stringInSlice(a string, list []string) bool {
}

func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gas.Context) *gas.Issue {
tlsConfig := gas.MatchCompLit(n, c, t.requiredType)
if tlsConfig == nil {
return nil
}

for _, expr := range tlsConfig.Elts {
if keyvalExpr, ok := expr.(*ast.KeyValueExpr); ok {
if keyname, ok := keyvalExpr.Key.(*ast.Ident); ok && keyname.Name == "CipherSuites" {
if ciphers, ok := keyvalExpr.Value.(*ast.CompositeLit); ok {
for _, cipher := range ciphers.Elts {
if ident, ok := cipher.(*ast.SelectorExpr); ok {
if !stringInSlice(ident.Sel.Name, t.goodCiphers) {
str := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name)
return gas.NewIssue(c, n, str, gas.High, gas.High)
}
}
}
if ciphers, ok := n.(*ast.CompositeLit); ok {
for _, cipher := range ciphers.Elts {
if ident, ok := cipher.(*ast.SelectorExpr); ok {
if !stringInSlice(ident.Sel.Name, t.goodCiphers) {
err := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name)
return gas.NewIssue(c, ident, err, gas.High, gas.High)
}
}
}
Expand All @@ -65,6 +55,7 @@ func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gas.Context) *
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Context) *gas.Issue {
if ident, ok := n.Key.(*ast.Ident); ok {
switch ident.Name {

case "InsecureSkipVerify":
if node, ok := n.Value.(*ast.Ident); ok {
if node.Name != "false" {
Expand Down Expand Up @@ -104,7 +95,7 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Contex
}

case "CipherSuites":
if ret := t.processTLSCipherSuites(n, c); ret != nil {
if ret := t.processTLSCipherSuites(n.Value, c); ret != nil {
return ret
}

Expand All @@ -114,24 +105,24 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Contex
return nil
}

func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
if node := gas.MatchCompLit(n, c, t.requiredType); node != nil {
for _, elt := range node.Elts {
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
if complit, ok := n.(*ast.CompositeLit); ok && c.Info.TypeOf(complit.Type).String() == t.requiredType {
for _, elt := range complit.Elts {
if kve, ok := elt.(*ast.KeyValueExpr); ok {
gi = t.processTLSConfVal(kve, c)
if gi != nil {
break
issue := t.processTLSConfVal(kve, c)
if issue != nil {
return issue, nil
}
}
}
}
return
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: "tls.Config",
requiredType: "crypto/tls.Config",
MinVersion: 0x0303, // TLS 1.2 only
MaxVersion: 0x0303,
goodCiphers: []string{
Expand All @@ -146,7 +137,7 @@ func NewModernTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
// 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: "tls.Config",
requiredType: "crypto/tls.Config",
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
MaxVersion: 0x0303,
goodCiphers: []string{
Expand All @@ -172,7 +163,7 @@ func NewIntermediateTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
// 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: "tls.Config",
requiredType: "crypto/tls.Config",
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
MaxVersion: 0x0303,
goodCiphers: []string{
Expand Down
Loading