1414import go
1515import semmle.go.dataflow.Properties
1616import MultipartAndFormRemoteSource
17+ import DecompressionBombs
1718
1819module DecompressionBombsConfig implements DataFlow:: StateConfigSig {
19- class FlowState = DataFlow :: FlowState ;
20+ class FlowState = DecompressionBombs :: FlowState ;
2021
2122 predicate isSource ( DataFlow:: Node source , FlowState state ) {
2223 source instanceof UntrustedFlowSource and
2324 state = ""
2425 }
2526
2627 predicate isSink ( DataFlow:: Node sink , FlowState state ) {
27- (
28- exists ( Function f | f .hasQualifiedName ( "io" , [ "Copy" , "CopyBuffer" , "CopyN" ] ) |
29- sink = f .getACall ( ) .getArgument ( 1 )
30- )
31- or
32- exists ( Function f | f .hasQualifiedName ( "io" , [ "Pipe" , "ReadAll" , "ReadAtLeast" , "ReadFull" ] ) |
33- sink = f .getACall ( ) .getArgument ( 0 )
34- )
35- or
36- exists ( Function f |
37- f .hasQualifiedName ( "bufio.Reader" ,
38- [ "Read" , "ReadBytes" , "ReadByte" , "ReadLine" , "ReadRune" , "ReadSlice" , "ReadString" ] )
39- |
40- sink = f .getACall ( ) .getReceiver ( )
41- )
42- or
43- exists ( Function f | f .hasQualifiedName ( "bufio.Scanner" , [ "Text" , "Bytes" ] ) |
44- sink = f .getACall ( ) .getReceiver ( )
45- )
46- or
47- exists ( Function f | f .hasQualifiedName ( "io/ioutil" , "ReadAll" ) |
48- sink = f .getACall ( ) .getArgument ( 0 )
49- )
50- or
51- exists ( Function f |
52- f .hasQualifiedName ( [
53- "github.com/klauspost/compress/flate.decompressor" ,
54- "github.com/dsnet/compress/bzip2.Reader" , "compress/flate.decompressor" ,
55- "github.com/dsnet/compress/flate.Reader" , "github.com/klauspost/compress/zlib.reader" ,
56- "compress/zlib.reader" , "github.com/golang/snappy.Reader" ,
57- "github.com/klauspost/compress/s2.Reader" , "github.com/klauspost/compress/gzip.Reader" ,
58- "github.com/klauspost/pgzip.Reader" , "github.com/klauspost/compress/zstd.Decoder" ,
59- "github.com/DataDog/zstd.reader" , "compress/gzip.Reader" ,
60- "github.com/ulikunitz/xz.Reader" , "archive/tar.Reader" , "compress/bzip2.reader"
61- ] , "Read" )
62- |
63- sink = f .getACall ( ) .getReceiver ( )
64- )
65- or
66- exists ( Function f |
67- f .hasQualifiedName ( "github.com/klauspost/compress/s2.Reader" ,
68- [ "DecodeConcurrent" , "ReadByte" ] )
69- or
70- f .hasQualifiedName ( "github.com/golang/snappy.Reader" , "ReadByte" )
71- or
72- f .hasQualifiedName ( "github.com/klauspost/compress/gzip.Reader" , "WriteTo" )
73- or
74- f .hasQualifiedName ( "github.com/klauspost/pgzip.Reader" , "WriteTo" )
75- or
76- f .hasQualifiedName ( "github.com/klauspost/compress/zstd.Decoder" , [ "WriteTo" , "DecodeAll" ] )
77- |
78- sink = f .getACall ( ) .getReceiver ( )
79- )
80- ) and
28+ sink instanceof DecompressionBombs:: Sink and
8129 state =
8230 [
8331 "ZstdNewReader" , "XzNewReader" , "GzipNewReader" , "S2NewReader" , "SnapyNewReader" ,
@@ -86,131 +34,16 @@ module DecompressionBombsConfig implements DataFlow::StateConfigSig {
8634 }
8735
8836 predicate isAdditionalFlowStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
89- exists ( DataFlow:: FieldReadNode fi |
90- fi .getType ( ) .hasQualifiedName ( "github.com/klauspost/compress/zip" , "Reader" )
91- |
92- fromNode = fi .getBase ( ) and
93- toNode = fi
94- )
95- or
96- exists ( Method f , DataFlow:: CallNode call |
97- f .hasQualifiedName ( "github.com/klauspost/compress/zip" , "File" , [ "Open" , "OpenRaw" ] ) and
98- call = f .getACall ( )
99- |
100- fromNode = call .getReceiver ( ) and
101- toNode = call
37+ exists ( DecompressionBombs:: AdditionalTaintStep addStep |
38+ addStep .isAdditionalFlowStep ( fromNode , toNode )
10239 )
10340 }
10441
10542 predicate isAdditionalFlowStep (
10643 DataFlow:: Node fromNode , FlowState fromState , DataFlow:: Node toNode , FlowState toState
10744 ) {
108- exists ( Function f , DataFlow:: CallNode call |
109- f .hasQualifiedName ( "archive/zip" , [ "OpenReader" , "NewReader" ] ) and call = f .getACall ( )
110- |
111- fromNode = call .getArgument ( 0 ) and
112- toNode = call .getResult ( 0 ) and
113- fromState = "" and
114- toState = "ZipOpenReader"
115- )
116- or
117- exists ( Function f , DataFlow:: CallNode call |
118- f .hasQualifiedName ( "github.com/klauspost/compress/zip" , [ "NewReader" , "OpenReader" ] ) and
119- call = f .getACall ( )
120- |
121- fromNode = call .getArgument ( 0 ) and
122- toNode = call .getResult ( 0 ) and
123- fromState = "" and
124- toState = "ZipKlauspost"
125- )
126- or
127- exists ( Function f , DataFlow:: CallNode call |
128- f .hasQualifiedName ( "github.com/ulikunitz/xz" , "NewReader" ) and call = f .getACall ( )
129- |
130- fromNode = call .getArgument ( 0 ) and
131- toNode = call .getResult ( 0 ) and
132- fromState = "" and
133- toState = "XzNewReader"
134- )
135- or
136- exists ( Function f , DataFlow:: CallNode call |
137- f .hasQualifiedName ( [
138- "compress/gzip" , "github.com/klauspost/compress/gzip" , "github.com/klauspost/pgzip"
139- ] , "NewReader" ) and
140- call = f .getACall ( )
141- |
142- fromNode = call .getArgument ( 0 ) and
143- toNode = call .getResult ( 0 ) and
144- fromState = "" and
145- toState = "GzipNewReader"
146- )
147- or
148- exists ( Function f , DataFlow:: CallNode call |
149- f .hasQualifiedName ( [
150- "compress/bzip2" , "github.com/dsnet/compress/bzip2" , "github.com/cosnicolaou/pbzip2"
151- ] , "NewReader" ) and
152- call = f .getACall ( )
153- |
154- fromNode = call .getArgument ( 0 ) and
155- toNode = call .getResult ( 0 ) and
156- fromState = "" and
157- toState = "Bzip2NewReader"
158- )
159- or
160- exists ( Function f , DataFlow:: CallNode call |
161- (
162- f .hasQualifiedName ( "github.com/dsnet/compress/flate" , "NewReader" ) or
163- f .hasQualifiedName ( [ "compress/flate" , "github.com/klauspost/compress/flate" ] ,
164- [ "NewReaderDict" , "NewReader" ] )
165- ) and
166- call = f .getACall ( )
167- |
168- fromNode = call .getArgument ( 0 ) and
169- toNode = call .getResult ( 0 ) and
170- fromState = "" and
171- toState = "FlateNewReader"
172- )
173- or
174- exists ( Function f , DataFlow:: CallNode call |
175- f .hasQualifiedName ( [ "compress/zlib" , "github.com/klauspost/compress/zlib" ] , "NewReader" ) and
176- call = f .getACall ( )
177- |
178- fromNode = call .getArgument ( 0 ) and
179- toNode = call .getResult ( 0 ) and
180- fromState = "" and
181- toState = "ZlibNewReader"
182- )
183- or
184- exists ( Function f , DataFlow:: CallNode call |
185- f .hasQualifiedName ( [ "github.com/klauspost/compress/zstd" , "github.com/DataDog/zstd" ] ,
186- "NewReader" ) and
187- call = f .getACall ( )
188- |
189- fromNode = call .getArgument ( 0 ) and
190- toNode = call .getResult ( 0 ) and
191- fromState = "" and
192- toState = "ZstdNewReader"
193- )
194- or
195- exists ( Function f , DataFlow:: CallNode call |
196- f .hasQualifiedName ( [ "github.com/golang/snappy" , "github.com/klauspost/compress/snappy" ] ,
197- "NewReader" ) and
198- call = f .getACall ( )
199- |
200- fromNode = call .getArgument ( 0 ) and
201- toNode = call .getResult ( 0 ) and
202- fromState = "" and
203- toState = "SnapyNewReader"
204- )
205- or
206- exists ( Function f , DataFlow:: CallNode call |
207- f .hasQualifiedName ( "github.com/klauspost/compress/s2" , "NewReader" ) and
208- call = f .getACall ( )
209- |
210- fromNode = call .getArgument ( 0 ) and
211- toNode = call .getResult ( 0 ) and
212- fromState = "" and
213- toState = "S2NewReader"
45+ exists ( DecompressionBombs:: AdditionalTaintStep addStep |
46+ addStep .isAdditionalFlowStep ( fromNode , fromState , toNode , toState )
21447 )
21548 }
21649
0 commit comments