Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 19287fb

Browse files
committed
Add taint-tracking for archive/tar and archive/zip
1 parent 830f83f commit 19287fb

File tree

9 files changed

+779
-0
lines changed

9 files changed

+779
-0
lines changed

ql/src/semmle/go/frameworks/Stdlib.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import go
6+
import semmle.go.frameworks.stdlib.ImportAll
67

78
/** A `String()` method. */
89
class StringMethod extends TaintTracking::FunctionModel, Method {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the standard libraries.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `archive/tar` package. */
8+
module ArchiveTarTaintTracking {
9+
private class FunctionTaintTracking extends TaintTracking::FunctionModel {
10+
FunctionInput inp;
11+
FunctionOutput outp;
12+
13+
FunctionTaintTracking() {
14+
// signature: func FileInfoHeader(fi os.FileInfo, link string) (*Header, error)
15+
hasQualifiedName("archive/tar", "FileInfoHeader") and
16+
(inp.isParameter(0) and outp.isResult(0))
17+
or
18+
// signature: func NewReader(r io.Reader) *Reader
19+
hasQualifiedName("archive/tar", "NewReader") and
20+
(inp.isParameter(0) and outp.isResult())
21+
or
22+
// signature: func NewWriter(w io.Writer) *Writer
23+
hasQualifiedName("archive/tar", "NewWriter") and
24+
(inp.isResult() and outp.isParameter(0))
25+
}
26+
27+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
28+
input = inp and output = outp
29+
}
30+
}
31+
32+
private class MethodAndInterfaceTaintTracking extends TaintTracking::FunctionModel, Method {
33+
FunctionInput inp;
34+
FunctionOutput outp;
35+
36+
MethodAndInterfaceTaintTracking() {
37+
// Methods:
38+
// signature: func (*Header).FileInfo() os.FileInfo
39+
this.(Method).hasQualifiedName("archive/tar", "Header", "FileInfo") and
40+
(inp.isReceiver() and outp.isResult())
41+
or
42+
// signature: func (*Reader).Next() (*Header, error)
43+
this.(Method).hasQualifiedName("archive/tar", "Reader", "Next") and
44+
(inp.isReceiver() and outp.isResult(0))
45+
or
46+
// signature: func (*Reader).Read(b []byte) (int, error)
47+
this.(Method).hasQualifiedName("archive/tar", "Reader", "Read") and
48+
(inp.isReceiver() and outp.isParameter(0))
49+
or
50+
// signature: func (*Writer).Write(b []byte) (int, error)
51+
this.(Method).hasQualifiedName("archive/tar", "Writer", "Write") and
52+
(inp.isParameter(0) and outp.isReceiver())
53+
or
54+
// signature: func (*Writer).WriteHeader(hdr *Header) error
55+
this.(Method).hasQualifiedName("archive/tar", "Writer", "WriteHeader") and
56+
(inp.isParameter(0) and outp.isReceiver())
57+
}
58+
59+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
60+
input = inp and output = outp
61+
}
62+
}
63+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the standard libraries.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `archive/zip` package. */
8+
module ArchiveZipTaintTracking {
9+
private class FunctionTaintTracking extends TaintTracking::FunctionModel {
10+
FunctionInput inp;
11+
FunctionOutput outp;
12+
13+
FunctionTaintTracking() {
14+
// signature: func FileInfoHeader(fi os.FileInfo) (*FileHeader, error)
15+
hasQualifiedName("archive/zip", "FileInfoHeader") and
16+
(inp.isParameter(0) and outp.isResult(0))
17+
or
18+
// signature: func NewReader(r io.ReaderAt, size int64) (*Reader, error)
19+
hasQualifiedName("archive/zip", "NewReader") and
20+
(inp.isParameter(0) and outp.isResult(0))
21+
or
22+
// signature: func NewWriter(w io.Writer) *Writer
23+
hasQualifiedName("archive/zip", "NewWriter") and
24+
(inp.isResult() and outp.isParameter(0))
25+
or
26+
// signature: func OpenReader(name string) (*ReadCloser, error)
27+
hasQualifiedName("archive/zip", "OpenReader") and
28+
(inp.isParameter(0) and outp.isResult(0))
29+
}
30+
31+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
32+
input = inp and output = outp
33+
}
34+
}
35+
36+
private class MethodAndInterfaceTaintTracking extends TaintTracking::FunctionModel, Method {
37+
FunctionInput inp;
38+
FunctionOutput outp;
39+
40+
MethodAndInterfaceTaintTracking() {
41+
// Methods:
42+
// signature: func (*File).Open() (io.ReadCloser, error)
43+
this.(Method).hasQualifiedName("archive/zip", "File", "Open") and
44+
(inp.isReceiver() and outp.isResult(0))
45+
or
46+
// signature: func (*FileHeader).FileInfo() os.FileInfo
47+
this.(Method).hasQualifiedName("archive/zip", "FileHeader", "FileInfo") and
48+
(inp.isReceiver() and outp.isResult())
49+
or
50+
// signature: func (*FileHeader).Mode() (mode os.FileMode)
51+
this.(Method).hasQualifiedName("archive/zip", "FileHeader", "Mode") and
52+
(inp.isReceiver() and outp.isResult())
53+
or
54+
// signature: func (*FileHeader).SetMode(mode os.FileMode)
55+
this.(Method).hasQualifiedName("archive/zip", "FileHeader", "SetMode") and
56+
(inp.isParameter(0) and outp.isReceiver())
57+
or
58+
// signature: func (*Reader).RegisterDecompressor(method uint16, dcomp Decompressor)
59+
this.(Method).hasQualifiedName("archive/zip", "Reader", "RegisterDecompressor") and
60+
(inp.isParameter(1) and outp.isReceiver())
61+
or
62+
// signature: func (*Writer).Create(name string) (io.Writer, error)
63+
this.(Method).hasQualifiedName("archive/zip", "Writer", "Create") and
64+
(inp.isResult(0) and outp.isReceiver())
65+
or
66+
// signature: func (*Writer).CreateHeader(fh *FileHeader) (io.Writer, error)
67+
this.(Method).hasQualifiedName("archive/zip", "Writer", "CreateHeader") and
68+
(
69+
(inp.isParameter(0) or inp.isResult(0)) and
70+
outp.isReceiver()
71+
)
72+
or
73+
// signature: func (*Writer).RegisterCompressor(method uint16, comp Compressor)
74+
this.(Method).hasQualifiedName("archive/zip", "Writer", "RegisterCompressor") and
75+
(inp.isParameter(1) and outp.isReceiver())
76+
or
77+
// signature: func (*Writer).SetComment(comment string) error
78+
this.(Method).hasQualifiedName("archive/zip", "Writer", "SetComment") and
79+
(inp.isParameter(0) and outp.isReceiver())
80+
}
81+
82+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
83+
input = inp and output = outp
84+
}
85+
}
86+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Provides imports of all the standard libraries.
3+
*/
4+
5+
import go
6+
import semmle.go.frameworks.stdlib.ArchiveTarTaintTracking
7+
import semmle.go.frameworks.stdlib.ArchiveZipTaintTracking
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
// WARNING: This file was automatically generated. DO NOT EDIT.
2+
3+
package main
4+
5+
import (
6+
"archive/tar"
7+
"io"
8+
"os"
9+
)
10+
11+
func TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} {
12+
// The flow is from `fromFileInfo656` into `intoHeader414`.
13+
14+
// Assume that `sourceCQL` has the underlying type of `fromFileInfo656`:
15+
fromFileInfo656 := sourceCQL.(os.FileInfo)
16+
17+
// Call the function that transfers the taint
18+
// from the parameter `fromFileInfo656` to result `intoHeader414`
19+
// (`intoHeader414` is now tainted).
20+
intoHeader414, _ := tar.FileInfoHeader(fromFileInfo656, "")
21+
22+
// Return the tainted `intoHeader414`:
23+
return intoHeader414
24+
}
25+
26+
func TaintStepTest_ArchiveTarNewReader_B0I0O0(sourceCQL interface{}) interface{} {
27+
// The flow is from `fromReader518` into `intoReader650`.
28+
29+
// Assume that `sourceCQL` has the underlying type of `fromReader518`:
30+
fromReader518 := sourceCQL.(io.Reader)
31+
32+
// Call the function that transfers the taint
33+
// from the parameter `fromReader518` to result `intoReader650`
34+
// (`intoReader650` is now tainted).
35+
intoReader650 := tar.NewReader(fromReader518)
36+
37+
// Return the tainted `intoReader650`:
38+
return intoReader650
39+
}
40+
41+
func TaintStepTest_ArchiveTarNewWriter_B0I0O0(sourceCQL interface{}) interface{} {
42+
// The flow is from `fromWriter784` into `intoWriter957`.
43+
44+
// Assume that `sourceCQL` has the underlying type of `fromWriter784`:
45+
fromWriter784 := sourceCQL.(*tar.Writer)
46+
47+
// Declare `intoWriter957` variable:
48+
var intoWriter957 io.Writer
49+
50+
// Call the function that will transfer the taint
51+
// from the result `intermediateCQL` to parameter `intoWriter957`:
52+
intermediateCQL := tar.NewWriter(intoWriter957)
53+
54+
// Extra step (`fromWriter784` taints `intermediateCQL`, which taints `intoWriter957`:
55+
link(fromWriter784, intermediateCQL)
56+
57+
// Return the tainted `intoWriter957`:
58+
return intoWriter957
59+
}
60+
61+
func TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(sourceCQL interface{}) interface{} {
62+
// The flow is from `fromHeader520` into `intoFileInfo443`.
63+
64+
// Assume that `sourceCQL` has the underlying type of `fromHeader520`:
65+
fromHeader520 := sourceCQL.(tar.Header)
66+
67+
// Call the method that transfers the taint
68+
// from the receiver `fromHeader520` to the result `intoFileInfo443`
69+
// (`intoFileInfo443` is now tainted).
70+
intoFileInfo443 := fromHeader520.FileInfo()
71+
72+
// Return the tainted `intoFileInfo443`:
73+
return intoFileInfo443
74+
}
75+
76+
func TaintStepTest_ArchiveTarReaderNext_B0I0O0(sourceCQL interface{}) interface{} {
77+
// The flow is from `fromReader127` into `intoHeader483`.
78+
79+
// Assume that `sourceCQL` has the underlying type of `fromReader127`:
80+
fromReader127 := sourceCQL.(tar.Reader)
81+
82+
// Call the method that transfers the taint
83+
// from the receiver `fromReader127` to the result `intoHeader483`
84+
// (`intoHeader483` is now tainted).
85+
intoHeader483, _ := fromReader127.Next()
86+
87+
// Return the tainted `intoHeader483`:
88+
return intoHeader483
89+
}
90+
91+
func TaintStepTest_ArchiveTarReaderRead_B0I0O0(sourceCQL interface{}) interface{} {
92+
// The flow is from `fromReader989` into `intoByte982`.
93+
94+
// Assume that `sourceCQL` has the underlying type of `fromReader989`:
95+
fromReader989 := sourceCQL.(tar.Reader)
96+
97+
// Declare `intoByte982` variable:
98+
var intoByte982 []byte
99+
100+
// Call the method that transfers the taint
101+
// from the receiver `fromReader989` to the argument `intoByte982`
102+
// (`intoByte982` is now tainted).
103+
fromReader989.Read(intoByte982)
104+
105+
// Return the tainted `intoByte982`:
106+
return intoByte982
107+
}
108+
109+
func TaintStepTest_ArchiveTarWriterWrite_B0I0O0(sourceCQL interface{}) interface{} {
110+
// The flow is from `fromByte417` into `intoWriter584`.
111+
112+
// Assume that `sourceCQL` has the underlying type of `fromByte417`:
113+
fromByte417 := sourceCQL.([]byte)
114+
115+
// Declare `intoWriter584` variable:
116+
var intoWriter584 tar.Writer
117+
118+
// Call the method that transfers the taint
119+
// from the parameter `fromByte417` to the receiver `intoWriter584`
120+
// (`intoWriter584` is now tainted).
121+
intoWriter584.Write(fromByte417)
122+
123+
// Return the tainted `intoWriter584`:
124+
return intoWriter584
125+
}
126+
127+
func TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(sourceCQL interface{}) interface{} {
128+
// The flow is from `fromHeader991` into `intoWriter881`.
129+
130+
// Assume that `sourceCQL` has the underlying type of `fromHeader991`:
131+
fromHeader991 := sourceCQL.(*tar.Header)
132+
133+
// Declare `intoWriter881` variable:
134+
var intoWriter881 tar.Writer
135+
136+
// Call the method that transfers the taint
137+
// from the parameter `fromHeader991` to the receiver `intoWriter881`
138+
// (`intoWriter881` is now tainted).
139+
intoWriter881.WriteHeader(fromHeader991)
140+
141+
// Return the tainted `intoWriter881`:
142+
return intoWriter881
143+
}
144+
145+
func RunAllTaints_ArchiveTar() {
146+
{
147+
// Create a new source:
148+
source := newSource()
149+
// Run the taint scenario:
150+
out := TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(source)
151+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
152+
sink(out)
153+
}
154+
{
155+
// Create a new source:
156+
source := newSource()
157+
// Run the taint scenario:
158+
out := TaintStepTest_ArchiveTarNewReader_B0I0O0(source)
159+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
160+
sink(out)
161+
}
162+
{
163+
// Create a new source:
164+
source := newSource()
165+
// Run the taint scenario:
166+
out := TaintStepTest_ArchiveTarNewWriter_B0I0O0(source)
167+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
168+
sink(out)
169+
}
170+
{
171+
// Create a new source:
172+
source := newSource()
173+
// Run the taint scenario:
174+
out := TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(source)
175+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
176+
sink(out)
177+
}
178+
{
179+
// Create a new source:
180+
source := newSource()
181+
// Run the taint scenario:
182+
out := TaintStepTest_ArchiveTarReaderNext_B0I0O0(source)
183+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
184+
sink(out)
185+
}
186+
{
187+
// Create a new source:
188+
source := newSource()
189+
// Run the taint scenario:
190+
out := TaintStepTest_ArchiveTarReaderRead_B0I0O0(source)
191+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
192+
sink(out)
193+
}
194+
{
195+
// Create a new source:
196+
source := newSource()
197+
// Run the taint scenario:
198+
out := TaintStepTest_ArchiveTarWriterWrite_B0I0O0(source)
199+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
200+
sink(out)
201+
}
202+
{
203+
// Create a new source:
204+
source := newSource()
205+
// Run the taint scenario:
206+
out := TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(source)
207+
// If the taint step(s) succeeded, then `out` is tainted and will be sink-able here:
208+
sink(out)
209+
}
210+
}

0 commit comments

Comments
 (0)