Skip to content

Commit 00cc78d

Browse files
committed
Make CookieWithoutHttpOnly use new API
The extra nodes in .expected files are due to the changes from #13717, which are not applied to configuration classes extending DataFlow::Configuration or TaintTracking::Configuration.
1 parent a7382e0 commit 00cc78d

3 files changed

Lines changed: 414 additions & 208 deletions

File tree

go/ql/src/experimental/CWE-1004/AuthCookie.qll

Lines changed: 146 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ private class SetCookieSink extends DataFlow::Node {
6565
}
6666

6767
/**
68+
* DEPRECATED: Use `NameToNetHttpCookieTrackingFlow` instead.
69+
*
6870
* A taint-tracking configuration for tracking flow from sensitive names to
6971
* `net/http.SetCookie`.
7072
*/
71-
class NameToNetHttpCookieTrackingConfiguration extends TaintTracking::Configuration {
73+
deprecated class NameToNetHttpCookieTrackingConfiguration extends TaintTracking::Configuration {
7274
NameToNetHttpCookieTrackingConfiguration() { this = "NameToNetHttpCookieTrackingConfiguration" }
7375

7476
override predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
@@ -84,11 +86,29 @@ class NameToNetHttpCookieTrackingConfiguration extends TaintTracking::Configurat
8486
}
8587
}
8688

89+
private module NameToNetHttpCookieTrackingConfig implements DataFlow::ConfigSig {
90+
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
91+
92+
predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
93+
94+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
95+
exists(StructLit sl |
96+
sl.getType() instanceof NetHttpCookieType and
97+
getValueForFieldWrite(sl, "Name") = pred and
98+
sl = succ.asExpr()
99+
)
100+
}
101+
}
102+
103+
module NameToNetHttpCookieTrackingFlow = TaintTracking::Global<NameToNetHttpCookieTrackingConfig>;
104+
87105
/**
106+
* DEPRECATED: Use `BoolToNetHttpCookieTrackingFlow` instead.
107+
*
88108
* A taint-tracking configuration for tracking flow from `bool` assigned to
89109
* `HttpOnly` that flows into `net/http.SetCookie`.
90110
*/
91-
class BoolToNetHttpCookieTrackingConfiguration extends TaintTracking::Configuration {
111+
deprecated class BoolToNetHttpCookieTrackingConfiguration extends TaintTracking::Configuration {
92112
BoolToNetHttpCookieTrackingConfiguration() { this = "BoolToNetHttpCookieTrackingConfiguration" }
93113

94114
override predicate isSource(DataFlow::Node source) {
@@ -106,11 +126,31 @@ class BoolToNetHttpCookieTrackingConfiguration extends TaintTracking::Configurat
106126
}
107127
}
108128

129+
private module BoolToNetHttpCookieTrackingConfig implements DataFlow::ConfigSig {
130+
predicate isSource(DataFlow::Node source) {
131+
source.getType().getUnderlyingType() instanceof BoolType
132+
}
133+
134+
predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
135+
136+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
137+
exists(StructLit sl |
138+
sl.getType() instanceof NetHttpCookieType and
139+
getValueForFieldWrite(sl, "HttpOnly") = pred and
140+
sl = succ.asExpr()
141+
)
142+
}
143+
}
144+
145+
module BoolToNetHttpCookieTrackingFlow = TaintTracking::Global<BoolToNetHttpCookieTrackingConfig>;
146+
109147
/**
148+
* DEPRECATED: Use `BoolToGinSetCookieTrackingFlow` instead.
149+
*
110150
* A taint-tracking configuration for tracking flow from `HttpOnly` set to
111151
* `false` to `gin-gonic/gin.Context.SetCookie`.
112152
*/
113-
class BoolToGinSetCookieTrackingConfiguration extends DataFlow::Configuration {
153+
deprecated class BoolToGinSetCookieTrackingConfiguration extends DataFlow::Configuration {
114154
BoolToGinSetCookieTrackingConfiguration() { this = "BoolToGinSetCookieTrackingConfiguration" }
115155

116156
override predicate isSource(DataFlow::Node source) { source.getBoolValue() = false }
@@ -119,31 +159,48 @@ class BoolToGinSetCookieTrackingConfiguration extends DataFlow::Configuration {
119159
exists(DataFlow::MethodCallNode mcn |
120160
mcn.getTarget() instanceof GinContextSetCookieMethod and
121161
mcn.getArgument(6) = sink and
122-
exists(NameToGinSetCookieTrackingConfiguration cfg, DataFlow::Node nameArg |
123-
cfg.hasFlowTo(nameArg) and
162+
exists(DataFlow::Node nameArg |
163+
NameToGinSetCookieTrackingFlow::flowTo(nameArg) and
164+
mcn.getArgument(0) = nameArg
165+
)
166+
)
167+
}
168+
}
169+
170+
private module BoolToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
171+
predicate isSource(DataFlow::Node source) { source.getBoolValue() = false }
172+
173+
predicate isSink(DataFlow::Node sink) {
174+
exists(DataFlow::MethodCallNode mcn |
175+
mcn.getTarget() instanceof GinContextSetCookieMethod and
176+
mcn.getArgument(6) = sink and
177+
exists(DataFlow::Node nameArg |
178+
NameToGinSetCookieTrackingFlow::flowTo(nameArg) and
124179
mcn.getArgument(0) = nameArg
125180
)
126181
)
127182
}
128183
}
129184

185+
module BoolToGinSetCookieTrackingFlow = DataFlow::Global<BoolToGinSetCookieTrackingConfig>;
186+
130187
/**
131188
* A taint-tracking configuration for tracking flow from sensitive names to
132189
* `gin-gonic/gin.Context.SetCookie`.
133190
*/
134-
private class NameToGinSetCookieTrackingConfiguration extends DataFlow2::Configuration {
135-
NameToGinSetCookieTrackingConfiguration() { this = "NameToGinSetCookieTrackingConfiguration" }
136-
137-
override predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
191+
private module NameToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
192+
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
138193

139-
override predicate isSink(DataFlow::Node sink) {
194+
predicate isSink(DataFlow::Node sink) {
140195
exists(DataFlow::MethodCallNode mcn |
141196
mcn.getTarget() instanceof GinContextSetCookieMethod and
142197
mcn.getArgument(0) = sink
143198
)
144199
}
145200
}
146201

202+
private module NameToGinSetCookieTrackingFlow = DataFlow::Global<NameToGinSetCookieTrackingConfig>;
203+
147204
/**
148205
* The receiver of `gorilla/sessions.Session.Save` call.
149206
*/
@@ -168,10 +225,12 @@ private class GorillaStoreSaveSink extends DataFlow::Node {
168225
}
169226

170227
/**
228+
* DEPRECATED: Use `GorillaCookieStoreSaveTrackingFlow` instead.
229+
*
171230
* A taint-tracking configuration for tracking flow from gorilla cookie store
172231
* creation to `gorilla/sessions.Session.Save`.
173232
*/
174-
class GorillaCookieStoreSaveTrackingConfiguration extends DataFlow::Configuration {
233+
deprecated class GorillaCookieStoreSaveTrackingConfiguration extends DataFlow::Configuration {
175234
GorillaCookieStoreSaveTrackingConfiguration() {
176235
this = "GorillaCookieStoreSaveTrackingConfiguration"
177236
}
@@ -198,11 +257,38 @@ class GorillaCookieStoreSaveTrackingConfiguration extends DataFlow::Configuratio
198257
}
199258
}
200259

260+
private module GorillaCookieStoreSaveTrackingConfig implements DataFlow::ConfigSig {
261+
predicate isSource(DataFlow::Node source) {
262+
source
263+
.(DataFlow::CallNode)
264+
.getTarget()
265+
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "NewCookieStore")
266+
}
267+
268+
predicate isSink(DataFlow::Node sink) {
269+
sink instanceof GorillaSessionSaveSink or
270+
sink instanceof GorillaStoreSaveSink
271+
}
272+
273+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
274+
exists(DataFlow::MethodCallNode cn |
275+
cn.getTarget()
276+
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "CookieStore", "Get") and
277+
pred = cn.getReceiver() and
278+
succ = cn.getResult(0)
279+
)
280+
}
281+
}
282+
283+
module GorillaCookieStoreSaveTrackingFlow = DataFlow::Global<GorillaCookieStoreSaveTrackingConfig>;
284+
201285
/**
286+
* DEPRECATED: Use `GorillaSessionOptionsTrackingFlow` instead.
287+
*
202288
* A taint-tracking configuration for tracking flow from session options to
203289
* `gorilla/sessions.Session.Save`.
204290
*/
205-
class GorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configuration {
291+
deprecated class GorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configuration {
206292
GorillaSessionOptionsTrackingConfiguration() {
207293
this = "GorillaSessionOptionsTrackingConfiguration"
208294
}
@@ -224,11 +310,35 @@ class GorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configur
224310
}
225311
}
226312

313+
private module GorillaSessionOptionsTrackingConfig implements DataFlow::ConfigSig {
314+
predicate isSource(DataFlow::Node source) {
315+
exists(StructLit sl |
316+
sl.getType().hasQualifiedName(package("github.com/gorilla/sessions", ""), "Options") and
317+
source.asExpr() = sl
318+
)
319+
}
320+
321+
predicate isSink(DataFlow::Node sink) { sink instanceof GorillaSessionSaveSink }
322+
323+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
324+
exists(GorillaSessionOptionsField f, DataFlow::Write w, DataFlow::Node base |
325+
w.writesField(base, f, pred) and
326+
succ = base
327+
)
328+
}
329+
}
330+
331+
module GorillaSessionOptionsTrackingFlow =
332+
TaintTracking::Global<GorillaSessionOptionsTrackingConfig>;
333+
227334
/**
335+
* DEPRECATED: Use `BoolToGorillaSessionOptionsTrackingFlow` instead.
336+
*
228337
* A taint-tracking configuration for tracking flow from a `bool` assigned to
229338
* `HttpOnly` to `gorilla/sessions.Session.Save`.
230339
*/
231-
class BoolToGorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configuration {
340+
deprecated class BoolToGorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configuration
341+
{
232342
BoolToGorillaSessionOptionsTrackingConfiguration() {
233343
this = "BoolToGorillaSessionOptionsTrackingConfiguration"
234344
}
@@ -251,3 +361,26 @@ class BoolToGorillaSessionOptionsTrackingConfiguration extends TaintTracking::Co
251361
)
252362
}
253363
}
364+
365+
private module BoolToGorillaSessionOptionsTrackingConfig implements DataFlow::ConfigSig {
366+
predicate isSource(DataFlow::Node source) {
367+
source.getType().getUnderlyingType() instanceof BoolType
368+
}
369+
370+
predicate isSink(DataFlow::Node sink) { sink instanceof GorillaSessionSaveSink }
371+
372+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
373+
exists(StructLit sl |
374+
getValueForFieldWrite(sl, "HttpOnly") = pred and
375+
sl = succ.asExpr()
376+
)
377+
or
378+
exists(GorillaSessionOptionsField f, DataFlow::Write w, DataFlow::Node base |
379+
w.writesField(base, f, pred) and
380+
succ = base
381+
)
382+
}
383+
}
384+
385+
module BoolToGorillaSessionOptionsTrackingFlow =
386+
TaintTracking::Global<BoolToGorillaSessionOptionsTrackingConfig>;

go/ql/src/experimental/CWE-1004/CookieWithoutHttpOnly.ql

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,40 @@
1515

1616
import go
1717
import AuthCookie
18-
import DataFlow::PathGraph
18+
19+
module MergedFlow1 =
20+
DataFlow::MergePathGraph<NameToNetHttpCookieTrackingFlow::PathNode,
21+
BoolToNetHttpCookieTrackingFlow::PathNode, NameToNetHttpCookieTrackingFlow::PathGraph,
22+
BoolToNetHttpCookieTrackingFlow::PathGraph>;
23+
24+
module MergedFlow2 =
25+
DataFlow::MergePathGraph3<GorillaCookieStoreSaveTrackingFlow::PathNode,
26+
GorillaSessionOptionsTrackingFlow::PathNode, BoolToGorillaSessionOptionsTrackingFlow::PathNode,
27+
GorillaCookieStoreSaveTrackingFlow::PathGraph, GorillaSessionOptionsTrackingFlow::PathGraph,
28+
BoolToGorillaSessionOptionsTrackingFlow::PathGraph>;
29+
30+
module MergedFlow =
31+
DataFlow::MergePathGraph3<MergedFlow1::PathNode, BoolToGinSetCookieTrackingFlow::PathNode,
32+
MergedFlow2::PathNode, MergedFlow1::PathGraph, BoolToGinSetCookieTrackingFlow::PathGraph,
33+
MergedFlow2::PathGraph>;
34+
35+
import MergedFlow::PathGraph
1936

2037
/** Holds if `HttpOnly` of `net/http.SetCookie` is set to `false` or not set (default value is used). */
21-
predicate isNetHttpCookieFlow(DataFlow::PathNode source, DataFlow::PathNode sink) {
22-
exists(DataFlow::PathNode sensitiveName, DataFlow::PathNode setCookieSink |
23-
exists(NameToNetHttpCookieTrackingConfiguration cfg |
24-
cfg.hasFlowPath(sensitiveName, setCookieSink)
25-
) and
38+
predicate isNetHttpCookieFlow(MergedFlow1::PathNode source, MergedFlow1::PathNode sink) {
39+
exists(
40+
NameToNetHttpCookieTrackingFlow::PathNode sensitiveName,
41+
NameToNetHttpCookieTrackingFlow::PathNode setCookieSink
42+
|
43+
NameToNetHttpCookieTrackingFlow::flowPath(sensitiveName, setCookieSink) and
2644
(
27-
not any(BoolToNetHttpCookieTrackingConfiguration cfg).hasFlowTo(setCookieSink.getNode()) and
28-
source = sensitiveName and
29-
sink = setCookieSink
45+
not BoolToNetHttpCookieTrackingFlow::flowTo(sink.getNode()) and
46+
source.asPathNode1() = sensitiveName and
47+
sink.asPathNode1() = setCookieSink
3048
or
31-
exists(BoolToNetHttpCookieTrackingConfiguration cfg, DataFlow::PathNode setCookieSink2 |
32-
cfg.hasFlowPath(source, setCookieSink2) and
33-
source.getNode().getBoolValue() = false and
34-
sink = setCookieSink2 and
35-
setCookieSink.getNode() = setCookieSink2.getNode()
36-
)
49+
BoolToNetHttpCookieTrackingFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and
50+
source.getNode().getBoolValue() = false and
51+
setCookieSink.getNode() = sink.getNode()
3752
)
3853
)
3954
}
@@ -42,44 +57,38 @@ predicate isNetHttpCookieFlow(DataFlow::PathNode source, DataFlow::PathNode sink
4257
* Holds if there is gorilla cookie store creation to `Save` path and
4358
* `HttpOnly` is set to `false` or not set (default value is used).
4459
*/
45-
predicate isGorillaSessionsCookieFlow(DataFlow::PathNode source, DataFlow::PathNode sink) {
46-
exists(DataFlow::PathNode cookieStoreCreate, DataFlow::PathNode sessionSave |
47-
any(GorillaCookieStoreSaveTrackingConfiguration cfg).hasFlowPath(cookieStoreCreate, sessionSave) and
60+
predicate isGorillaSessionsCookieFlow(MergedFlow2::PathNode source, MergedFlow2::PathNode sink) {
61+
exists(
62+
GorillaCookieStoreSaveTrackingFlow::PathNode cookieStoreCreate,
63+
GorillaCookieStoreSaveTrackingFlow::PathNode sessionSave
64+
|
65+
GorillaCookieStoreSaveTrackingFlow::flowPath(cookieStoreCreate, sessionSave) and
4866
(
49-
not any(GorillaSessionOptionsTrackingConfiguration cfg).hasFlowTo(sessionSave.getNode()) and
50-
source = cookieStoreCreate and
51-
sink = sessionSave
67+
not GorillaSessionOptionsTrackingFlow::flowTo(sink.getNode()) and
68+
source.asPathNode1() = cookieStoreCreate and
69+
sink.asPathNode1() = sessionSave
5270
or
53-
exists(
54-
GorillaSessionOptionsTrackingConfiguration cfg, DataFlow::PathNode options,
55-
DataFlow::PathNode sessionSave2
56-
|
57-
cfg.hasFlowPath(options, sessionSave2) and
71+
exists(MergedFlow2::PathNode options, MergedFlow2::PathNode sessionSave2 |
72+
GorillaSessionOptionsTrackingFlow::flowPath(options.asPathNode2(),
73+
sessionSave2.asPathNode2()) and
5874
(
59-
not any(BoolToGorillaSessionOptionsTrackingConfiguration boolCfg)
60-
.hasFlowTo(sessionSave.getNode()) and
61-
sink = sessionSave2 and
75+
not BoolToGorillaSessionOptionsTrackingFlow::flowTo(sink.getNode()) and
6276
source = options and
77+
sink = sessionSave2 and
6378
sessionSave.getNode() = sessionSave2.getNode()
6479
or
65-
exists(
66-
BoolToGorillaSessionOptionsTrackingConfiguration boolCfg,
67-
DataFlow::PathNode sessionSave3
68-
|
69-
boolCfg.hasFlowPath(source, sessionSave3) and
70-
source.getNode().getBoolValue() = false and
71-
sink = sessionSave3 and
72-
sessionSave.getNode() = sessionSave3.getNode()
73-
)
80+
BoolToGorillaSessionOptionsTrackingFlow::flowPath(source.asPathNode3(), sink.asPathNode3()) and
81+
source.getNode().getBoolValue() = false and
82+
sink.getNode() = sessionSave.getNode()
7483
)
7584
)
7685
)
7786
)
7887
}
7988

80-
from DataFlow::PathNode source, DataFlow::PathNode sink
89+
from MergedFlow::PathNode source, MergedFlow::PathNode sink
8190
where
82-
isNetHttpCookieFlow(source, sink) or
83-
any(BoolToGinSetCookieTrackingConfiguration cfg).hasFlowPath(source, sink) or
84-
isGorillaSessionsCookieFlow(source, sink)
91+
isNetHttpCookieFlow(source.asPathNode1(), sink.asPathNode1()) or
92+
BoolToGinSetCookieTrackingFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) or
93+
isGorillaSessionsCookieFlow(source.asPathNode3(), sink.asPathNode3())
8594
select sink.getNode(), source, sink, "Cookie attribute 'HttpOnly' is not set to true."

0 commit comments

Comments
 (0)