mirror of
https://github.com/securego/gosec.git
synced 2024-12-24 11:35:52 +00:00
Migrated old test cases.
This commit is contained in:
parent
25d74c6b20
commit
e925d3c347
6 changed files with 562 additions and 40 deletions
|
@ -60,6 +60,7 @@ func (c CallList) ContainsCallExpr(n ast.Node, ctx *Context) *ast.CallExpr {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try direct resolution
|
// Try direct resolution
|
||||||
if c.Contains(selector, ident) {
|
if c.Contains(selector, ident) {
|
||||||
return n.(*ast.CallExpr)
|
return n.(*ast.CallExpr)
|
||||||
|
|
|
@ -16,6 +16,7 @@ package rules
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/GoASTScanner/gas"
|
"github.com/GoASTScanner/gas"
|
||||||
)
|
)
|
||||||
|
@ -25,11 +26,16 @@ type blacklistedImport struct {
|
||||||
Blacklisted map[string]string
|
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 {
|
if node, ok := n.(*ast.ImportSpec); ok {
|
||||||
description, ok := r.Blacklisted[node.Path.Value]
|
if description, ok := r.Blacklisted[unquote(node.Path.Value)]; ok {
|
||||||
if ok && node.Name.String() != "_" {
|
return gas.NewIssue(c, node, description, r.Severity, r.Confidence), nil
|
||||||
return gas.NewIssue(c, n, description, r.Severity, r.Confidence), nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -50,27 +56,27 @@ func NewBlacklistedImports(conf gas.Config, blacklist map[string]string) (gas.Ru
|
||||||
// NewBlacklistedImportMD5 fails if MD5 is imported
|
// NewBlacklistedImportMD5 fails if MD5 is imported
|
||||||
func NewBlacklistedImportMD5(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewBlacklistedImportMD5(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return NewBlacklistedImports(conf, map[string]string{
|
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
|
// NewBlacklistedImportDES fails if DES is imported
|
||||||
func NewBlacklistedImportDES(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewBlacklistedImportDES(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return NewBlacklistedImports(conf, map[string]string{
|
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
|
// NewBlacklistedImportRC4 fails if DES is imported
|
||||||
func NewBlacklistedImportRC4(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewBlacklistedImportRC4(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return NewBlacklistedImports(conf, map[string]string{
|
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
|
// NewBlacklistedImportCGI fails if CGI is imported
|
||||||
func NewBlacklistedImportCGI(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewBlacklistedImportCGI(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return NewBlacklistedImports(conf, map[string]string{
|
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)",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,22 +47,86 @@ var _ = Describe("gas rules", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("report correct errors for all samples", 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)
|
runner("G101", testutils.SampleCodeG101)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should work for G102 samples", func() {
|
It("should detect binding to all network interfaces", func() {
|
||||||
runner("G102", testutils.SampleCodeG102)
|
runner("G102", testutils.SampleCodeG102)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should work for G103 samples", func() {
|
It("should use of unsafe block", func() {
|
||||||
runner("G103", testutils.SampleCodeG103)
|
runner("G103", testutils.SampleCodeG103)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should work for G104 samples", func() {
|
It("should errors not being checked", func() {
|
||||||
runner("G104", testutils.SampleCodeG104)
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -44,8 +44,9 @@ func NewTemplateCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
calls.Add("template", "HTML")
|
calls.Add("template", "HTML")
|
||||||
calls.Add("template", "HTMLAttr")
|
calls.Add("template", "HTMLAttr")
|
||||||
calls.Add("template", "JS")
|
calls.Add("template", "JS")
|
||||||
|
calls.Add("template", "URL")
|
||||||
return &templateCheck{
|
return &templateCheck{
|
||||||
calls: gas.NewCallList(),
|
calls: calls,
|
||||||
MetaData: gas.MetaData{
|
MetaData: gas.MetaData{
|
||||||
Severity: gas.Medium,
|
Severity: gas.Medium,
|
||||||
Confidence: gas.Low,
|
Confidence: gas.Low,
|
||||||
|
|
45
rules/tls.go
45
rules/tls.go
|
@ -38,23 +38,13 @@ func stringInSlice(a string, list []string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gas.Context) *gas.Issue {
|
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 ciphers, ok := n.(*ast.CompositeLit); ok {
|
||||||
if keyvalExpr, ok := expr.(*ast.KeyValueExpr); ok {
|
for _, cipher := range ciphers.Elts {
|
||||||
if keyname, ok := keyvalExpr.Key.(*ast.Ident); ok && keyname.Name == "CipherSuites" {
|
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
||||||
if ciphers, ok := keyvalExpr.Value.(*ast.CompositeLit); ok {
|
if !stringInSlice(ident.Sel.Name, t.goodCiphers) {
|
||||||
for _, cipher := range ciphers.Elts {
|
err := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name)
|
||||||
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
return gas.NewIssue(c, ident, err, gas.High, gas.High)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Context) *gas.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" {
|
||||||
|
@ -104,7 +95,7 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Contex
|
||||||
}
|
}
|
||||||
|
|
||||||
case "CipherSuites":
|
case "CipherSuites":
|
||||||
if ret := t.processTLSCipherSuites(n, c); ret != nil {
|
if ret := t.processTLSCipherSuites(n.Value, c); ret != nil {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,24 +105,24 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Contex
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||||
if node := gas.MatchCompLit(n, c, t.requiredType); node != nil {
|
if complit, ok := n.(*ast.CompositeLit); ok && c.Info.TypeOf(complit.Type).String() == t.requiredType {
|
||||||
for _, elt := range node.Elts {
|
for _, elt := range complit.Elts {
|
||||||
if kve, ok := elt.(*ast.KeyValueExpr); ok {
|
if kve, ok := elt.(*ast.KeyValueExpr); ok {
|
||||||
gi = t.processTLSConfVal(kve, c)
|
issue := t.processTLSConfVal(kve, c)
|
||||||
if gi != nil {
|
if issue != nil {
|
||||||
break
|
return issue, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewModernTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
|
// NewModernTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
|
||||||
func NewModernTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewModernTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return &insecureConfigTLS{
|
return &insecureConfigTLS{
|
||||||
requiredType: "tls.Config",
|
requiredType: "crypto/tls.Config",
|
||||||
MinVersion: 0x0303, // TLS 1.2 only
|
MinVersion: 0x0303, // TLS 1.2 only
|
||||||
MaxVersion: 0x0303,
|
MaxVersion: 0x0303,
|
||||||
goodCiphers: []string{
|
goodCiphers: []string{
|
||||||
|
@ -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
|
// NewIntermediateTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
|
||||||
func NewIntermediateTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewIntermediateTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return &insecureConfigTLS{
|
return &insecureConfigTLS{
|
||||||
requiredType: "tls.Config",
|
requiredType: "crypto/tls.Config",
|
||||||
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
|
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
|
||||||
MaxVersion: 0x0303,
|
MaxVersion: 0x0303,
|
||||||
goodCiphers: []string{
|
goodCiphers: []string{
|
||||||
|
@ -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
|
// NewCompatTLSCheck see: https://wiki.mozilla.org/Security/Server_Side_TLS#Old_compatibility_.28default.29
|
||||||
func NewCompatTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
func NewCompatTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||||
return &insecureConfigTLS{
|
return &insecureConfigTLS{
|
||||||
requiredType: "tls.Config",
|
requiredType: "crypto/tls.Config",
|
||||||
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
|
MinVersion: 0x0301, // TLS 1.2, 1.1, 1.0
|
||||||
MaxVersion: 0x0303,
|
MaxVersion: 0x0303,
|
||||||
goodCiphers: []string{
|
goodCiphers: []string{
|
||||||
|
|
|
@ -166,6 +166,269 @@ func main() {
|
||||||
fmt.Println(e)
|
fmt.Println(e)
|
||||||
}`, 0}}
|
}`, 0}}
|
||||||
|
|
||||||
|
// SampleCodeG105 - bignum overflow
|
||||||
|
SampleCodeG105 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
z := new(big.Int)
|
||||||
|
x := new(big.Int)
|
||||||
|
x = x.SetUint64(2)
|
||||||
|
y := new(big.Int)
|
||||||
|
y = y.SetUint64(4)
|
||||||
|
m := new(big.Int)
|
||||||
|
m = m.SetUint64(0)
|
||||||
|
z = z.Exp(x, y, m)
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG201 - SQL injection via format string
|
||||||
|
SampleCodeG201 = []CodeSample{
|
||||||
|
{`
|
||||||
|
// Format string without proper quoting
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
//_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main(){
|
||||||
|
db, err := sql.Open("sqlite3", ":memory:")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
q := fmt.Sprintf("SELECT * FROM foo where name = '%s'", os.Args[1])
|
||||||
|
rows, err := db.Query(q)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
}`, 1}, {
|
||||||
|
`
|
||||||
|
// Format string false positive
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
//_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
var staticQuery = "SELECT * FROM foo WHERE age < 32"
|
||||||
|
func main(){
|
||||||
|
db, err := sql.Open("sqlite3", ":memory:")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
rows, err := db.Query(staticQuery)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
}`, 0}}
|
||||||
|
|
||||||
|
// SampleCodeG202 - SQL query string building via string concatenation
|
||||||
|
SampleCodeG202 = []CodeSample{
|
||||||
|
{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
//_ "github.com/mattn/go-sqlite3"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
func main(){
|
||||||
|
db, err := sql.Open("sqlite3", ":memory:")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
rows, err := db.Query("SELECT * FROM foo WHERE name = " + os.Args[1])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
}`, 1}, {`
|
||||||
|
// false positive
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
//_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
var staticQuery = "SELECT * FROM foo WHERE age < "
|
||||||
|
func main(){
|
||||||
|
db, err := sql.Open("sqlite3", ":memory:")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
rows, err := db.Query(staticQuery + "32")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
}`, 0}, {`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
//_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
const age = "32"
|
||||||
|
var staticQuery = "SELECT * FROM foo WHERE age < "
|
||||||
|
func main(){
|
||||||
|
db, err := sql.Open("sqlite3", ":memory:")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
rows, err := db.Query(staticQuery + age)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
}
|
||||||
|
`, 0}}
|
||||||
|
|
||||||
|
// SampleCodeG203 - Template checks
|
||||||
|
SampleCodeG203 = []CodeSample{
|
||||||
|
{`
|
||||||
|
// We assume that hardcoded template strings are safe as the programmer would
|
||||||
|
// need to be explicitly shooting themselves in the foot (as below)
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
const tmpl = ""
|
||||||
|
func main() {
|
||||||
|
t := template.Must(template.New("ex").Parse(tmpl))
|
||||||
|
v := map[string]interface{}{
|
||||||
|
"Title": "Test <b>World</b>",
|
||||||
|
"Body": template.HTML("<script>alert(1)</script>"),
|
||||||
|
}
|
||||||
|
t.Execute(os.Stdout, v)
|
||||||
|
}`, 0}, {
|
||||||
|
`
|
||||||
|
// Using a variable to initialize could potentially be dangerous. Under the
|
||||||
|
// current model this will likely produce some false positives.
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
const tmpl = ""
|
||||||
|
func main() {
|
||||||
|
a := "something from another place"
|
||||||
|
t := template.Must(template.New("ex").Parse(tmpl))
|
||||||
|
v := map[string]interface{}{
|
||||||
|
"Title": "Test <b>World</b>",
|
||||||
|
"Body": template.HTML(a),
|
||||||
|
}
|
||||||
|
t.Execute(os.Stdout, v)
|
||||||
|
}`, 1}, {
|
||||||
|
`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
const tmpl = ""
|
||||||
|
func main() {
|
||||||
|
a := "something from another place"
|
||||||
|
t := template.Must(template.New("ex").Parse(tmpl))
|
||||||
|
v := map[string]interface{}{
|
||||||
|
"Title": "Test <b>World</b>",
|
||||||
|
"Body": template.JS(a),
|
||||||
|
}
|
||||||
|
t.Execute(os.Stdout, v)
|
||||||
|
}`, 1}, {
|
||||||
|
`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
const tmpl = ""
|
||||||
|
func main() {
|
||||||
|
a := "something from another place"
|
||||||
|
t := template.Must(template.New("ex").Parse(tmpl))
|
||||||
|
v := map[string]interface{}{
|
||||||
|
"Title": "Test <b>World</b>",
|
||||||
|
"Body": template.URL(a),
|
||||||
|
}
|
||||||
|
t.Execute(os.Stdout, v)
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG204 - Subprocess auditing
|
||||||
|
SampleCodeG204 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import "syscall"
|
||||||
|
func main() {
|
||||||
|
syscall.Exec("/bin/cat", []string{ "/etc/passwd" }, nil)
|
||||||
|
}`, 1}, {`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
cmd := exec.Command("sleep", "5")
|
||||||
|
err := cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Printf("Waiting for command to finish...")
|
||||||
|
err = cmd.Wait()
|
||||||
|
log.Printf("Command finished with error: %v", err)
|
||||||
|
}`, 1}, {`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
run := "sleep" + os.Getenv("SOMETHING")
|
||||||
|
cmd := exec.Command(run, "5")
|
||||||
|
err := cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Printf("Waiting for command to finish...")
|
||||||
|
err = cmd.Wait()
|
||||||
|
log.Printf("Command finished with error: %v", err)
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG301 - mkdir permission check
|
||||||
|
SampleCodeG301 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import "os"
|
||||||
|
func main() {
|
||||||
|
os.Mkdir("/tmp/mydir", 0777)
|
||||||
|
os.Mkdir("/tmp/mydir", 0600)
|
||||||
|
os.MkdirAll("/tmp/mydir/mysubidr", 0775)
|
||||||
|
}`, 2}}
|
||||||
|
|
||||||
|
// SampleCodeG302 - file create / chmod permissions check
|
||||||
|
SampleCodeG302 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import "os"
|
||||||
|
func main() {
|
||||||
|
os.Chmod("/tmp/somefile", 0777)
|
||||||
|
os.Chmod("/tmp/someotherfile", 0600)
|
||||||
|
os.OpenFile("/tmp/thing", os.O_CREATE|os.O_WRONLY, 0666)
|
||||||
|
os.OpenFile("/tmp/thing", os.O_CREATE|os.O_WRONLY, 0600)
|
||||||
|
}`, 2}}
|
||||||
|
|
||||||
|
// SampleCodeG303 - bad tempfile permissions & hardcoded shared path
|
||||||
|
SampleCodeG303 = []CodeSample{{`
|
||||||
|
package samples
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
file1, _ := os.Create("/tmp/demo1")
|
||||||
|
defer file1.Close()
|
||||||
|
ioutil.WriteFile("/tmp/demo2", []byte("This is some data"), 0644)
|
||||||
|
}`, 2}}
|
||||||
|
|
||||||
// SampleCodeG401 - Use of weak crypto MD5
|
// SampleCodeG401 - Use of weak crypto MD5
|
||||||
SampleCodeG401 = []CodeSample{
|
SampleCodeG401 = []CodeSample{
|
||||||
{`
|
{`
|
||||||
|
@ -190,4 +453,200 @@ func main() {
|
||||||
}
|
}
|
||||||
fmt.Printf("%x", h.Sum(nil))
|
fmt.Printf("%x", h.Sum(nil))
|
||||||
}`, 1}}
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG402 - TLS settings
|
||||||
|
SampleCodeG402 = []CodeSample{{`
|
||||||
|
// InsecureSkipVerify
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
_, err := client.Get("https://golang.org/")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}`, 1}, {
|
||||||
|
`
|
||||||
|
// Insecure minimum version
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{MinVersion: 0},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
_, err := client.Get("https://golang.org/")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}`, 1}, {`
|
||||||
|
// Insecure max version
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{MaxVersion: 0},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
_, err := client.Get("https://golang.org/")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, 1}, {
|
||||||
|
`
|
||||||
|
// Insecure ciphersuite selection
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{CipherSuites: []uint16{
|
||||||
|
tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
},},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
_, err := client.Get("https://golang.org/")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG403 - weak key strength
|
||||||
|
SampleCodeG403 = []CodeSample{
|
||||||
|
{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
//Generate Private Key
|
||||||
|
pvk, err := rsa.GenerateKey(rand.Reader, 1024)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println(pvk)
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG404 - weak random number
|
||||||
|
SampleCodeG404 = []CodeSample{
|
||||||
|
{`
|
||||||
|
package main
|
||||||
|
import "crypto/rand"
|
||||||
|
func main() {
|
||||||
|
good, _ := rand.Read(nil)
|
||||||
|
println(good)
|
||||||
|
}`, 0}, {`
|
||||||
|
package main
|
||||||
|
import "math/rand"
|
||||||
|
func main() {
|
||||||
|
bad := rand.Int()
|
||||||
|
println(bad)
|
||||||
|
}`, 1}, {`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
mrand "math/rand"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
good, _ := rand.Read(nil)
|
||||||
|
println(good)
|
||||||
|
i := mrand.Int31()
|
||||||
|
println(i)
|
||||||
|
}`, 0}}
|
||||||
|
|
||||||
|
// SampleCode501 - Blacklisted import MD5
|
||||||
|
SampleCodeG501 = []CodeSample{
|
||||||
|
{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
for _, arg := range os.Args {
|
||||||
|
fmt.Printf("%x - %s\n", md5.Sum([]byte(arg)), arg)
|
||||||
|
}
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCode502 - Blacklisted import DES
|
||||||
|
SampleCodeG502 = []CodeSample{
|
||||||
|
{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/des"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
block, err := des.NewCipher([]byte("sekritz"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
plaintext := []byte("I CAN HAZ SEKRIT MSG PLZ")
|
||||||
|
ciphertext := make([]byte, des.BlockSize+len(plaintext))
|
||||||
|
iv := ciphertext[:des.BlockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
stream := cipher.NewCFBEncrypter(block, iv)
|
||||||
|
stream.XORKeyStream(ciphertext[des.BlockSize:], plaintext)
|
||||||
|
fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext))
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG503 - Blacklisted import RC4
|
||||||
|
SampleCodeG503 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"crypto/rc4"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
cipher, err := rc4.NewCipher([]byte("sekritz"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
plaintext := []byte("I CAN HAZ SEKRIT MSG PLZ")
|
||||||
|
ciphertext := make([]byte, len(plaintext))
|
||||||
|
cipher.XORKeyStream(ciphertext, plaintext)
|
||||||
|
fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext))
|
||||||
|
}`, 1}}
|
||||||
|
|
||||||
|
// SampleCodeG504 - Blacklisted import CGI
|
||||||
|
SampleCodeG504 = []CodeSample{{`
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"net/http/cgi"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
cgi.Serve(http.FileServer(http.Dir("/usr/share/doc")))
|
||||||
|
}`, 1}}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue