Skip to content

Commit e76b258

Browse files
wileystargcmurphy
authored andcommitted
New Rule Tainted file (#183)
* Add a tool to generate the TLS configuration form Mozilla's ciphers recommendation (#178) * Add a tool which generates the TLS rule configuration from Mozilla server side TLS configuration * Update README * Remove trailing space in README * Update dependencies * Fix the commends of the generated functions * Add nil pointer check to rule. (#181) TypeOf returns the type of expression e, or nil if not found. We are calling .String() on a value that may be nil in this clause. Relates to #174 * Add support for YAML output format (#177) * Add YAML output format * Update README * added rule to check for tainted file path * added #nosec to main/issue.go * updated test case import
1 parent 57dd25a commit e76b258

File tree

7 files changed

+100
-0
lines changed

7 files changed

+100
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ or to specify a set of rules to explicitly exclude using the '-exclude=' flag.
4949
- G301: Poor file permissions used when creating a directory
5050
- G302: Poor file permisions used with chmod
5151
- G303: Creating tempfile using a predictable path
52+
- G304: File path provided as taint input
5253
- G401: Detect the usage of DES, RC4, or MD5
5354
- G402: Look for bad TLS connection settings
5455
- G403: Ensure minimum RSA key length of 2048 bits

cmd/gas/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ func usage() {
110110
func loadConfig(configFile string) (gas.Config, error) {
111111
config := gas.NewConfig()
112112
if configFile != "" {
113+
// #nosec
113114
file, err := os.Open(configFile)
114115
if err != nil {
115116
return nil, err

issue.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func NewIssue(ctx *Context, node ast.Node, desc string, severity Score, confiden
9797
line = fmt.Sprintf("%d-%d", start, end)
9898
}
9999

100+
// #nosec
100101
if file, err := os.Open(fobj.Name()); err == nil {
101102
defer file.Close()
102103
s := (int64)(fobj.Position(node.Pos()).Offset) // Go bug, should be int64

rules/readfile.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package rules
16+
17+
import (
18+
"go/ast"
19+
"go/types"
20+
21+
"github.com/GoASTScanner/gas"
22+
)
23+
24+
type readfile struct {
25+
gas.CallList
26+
}
27+
28+
// Match inspects AST nodes to determine if the match the methods `os.Open` or `ioutil.ReadFile`
29+
func (r *readfile) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
30+
if node := r.ContainsCallExpr(n, c); node != nil {
31+
for _, arg := range node.Args {
32+
if ident, ok := arg.(*ast.Ident); ok {
33+
obj := c.Info.ObjectOf(ident)
34+
if _, ok := obj.(*types.Var); ok && !gas.TryResolve(ident, c) {
35+
return gas.NewIssue(c, n, "File inclusion launched with variable", gas.Medium, gas.High), nil
36+
}
37+
}
38+
}
39+
}
40+
return nil, nil
41+
}
42+
43+
// NewReadFile detects cases where we read files
44+
func NewReadFile(conf gas.Config) (gas.Rule, []ast.Node) {
45+
rule := &readfile{gas.NewCallList()}
46+
rule.Add("io/ioutil", "ReadFile")
47+
rule.Add("os", "Open")
48+
return rule, []ast.Node{(*ast.CallExpr)(nil)}
49+
}

rules/rulelist.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func Generate(filters ...RuleFilter) RuleList {
7777
"G301": {"Poor file permissions used when creating a directory", NewMkdirPerms},
7878
"G302": {"Poor file permisions used when creation file or using chmod", NewFilePerms},
7979
"G303": {"Creating tempfile using a predictable path", NewBadTempFile},
80+
"G304": {"File path provided as taint input", NewReadFile},
8081

8182
// crypto
8283
"G401": {"Detect the usage of DES, RC4, or MD5", NewUsesWeakCryptography},

rules/rules_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ var _ = Describe("gas rules", func() {
9797
runner("G303", testutils.SampleCodeG303)
9898
})
9999

100+
It("should detect file path provided as taint input", func() {
101+
runner("G304", testutils.SampleCodeG304)
102+
})
103+
100104
It("should detect weak crypto algorithms", func() {
101105
runner("G401", testutils.SampleCodeG401)
102106
})

testutils/source.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,49 @@ func main() {
459459
ioutil.WriteFile("/tmp/demo2", []byte("This is some data"), 0644)
460460
}`, 2}}
461461

462+
// SampleCodeG304 - potential file inclusion vulnerability
463+
SampleCodeG304 = []CodeSample{{`
464+
package main
465+
import (
466+
"os"
467+
"io/ioutil"
468+
"log"
469+
)
470+
func main() {
471+
f := os.Getenv("tainted_file")
472+
body, err := ioutil.ReadFile(f)
473+
if err != nil {
474+
log.Printf("Error: %v\n", err)
475+
}
476+
log.Print(f)
477+
478+
}`, 1}, {`
479+
package main
480+
481+
import (
482+
"fmt"
483+
"log"
484+
"net/http"
485+
"os"
486+
)
487+
488+
func main() {
489+
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
490+
title := r.URL.Query().Get("title")
491+
f, err := os.Open(title)
492+
if err != nil {
493+
fmt.Printf("Error: %v\n", err)
494+
}
495+
body := make([]byte, 5)
496+
n1, err := f.Read(body)
497+
if err != nil {
498+
fmt.Printf("Error: %v\n", err)
499+
}
500+
fmt.Fprintf(w, "%s", body)
501+
})
502+
log.Fatal(http.ListenAndServe(":3000", nil))
503+
}`, 1}}
504+
462505
// SampleCodeG401 - Use of weak crypto MD5
463506
SampleCodeG401 = []CodeSample{
464507
{`

0 commit comments

Comments
 (0)