Skip to content

Commit 57c645b

Browse files
committed
Added support for same struct and added new test
1 parent 1f2e8d8 commit 57c645b

File tree

4 files changed

+82
-28
lines changed

4 files changed

+82
-28
lines changed

go/ql/lib/semmle/go/frameworks/GinCors.qll

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,75 +22,102 @@ module GinCors {
2222
* A write to the value of Access-Control-Allow-Credentials header
2323
*/
2424
class AllowCredentialsWrite extends DataFlow::ExprNode {
25-
GinConfig gc;
25+
DataFlow::Node base;
2626

2727
AllowCredentialsWrite() {
28-
exists(Field f, Write w, DataFlow::Node base |
28+
exists(Field f, Write w |
2929
f.hasQualifiedName(packagePath(), "Config", "AllowCredentials") and
3030
w.writesField(base, f, this) and
31-
this.getType() instanceof BoolType and
32-
(
33-
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
34-
base.asInstruction() or
35-
gc.getV().getAUse() = base
36-
)
31+
this.getType() instanceof BoolType
3732
)
3833
}
3934

35+
/**
36+
* Get config struct holding header values
37+
*/
38+
DataFlow::Node getBase() { result = base }
39+
4040
/**
4141
* Get config variable holding header values
4242
*/
43-
GinConfig getConfig() { result = gc }
43+
GinConfig getConfig() {
44+
exists(GinConfig gc |
45+
(
46+
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
47+
base.asInstruction() or
48+
gc.getV().getAUse() = base
49+
) and
50+
result = gc
51+
)
52+
}
4453
}
4554

4655
/**
4756
* A write to the value of Access-Control-Allow-Origins header
4857
*/
4958
class AllowOriginsWrite extends DataFlow::ExprNode {
50-
GinConfig gc;
59+
DataFlow::Node base;
5160

5261
AllowOriginsWrite() {
53-
exists(Field f, Write w, DataFlow::Node base |
62+
exists(Field f, Write w |
5463
f.hasQualifiedName(packagePath(), "Config", "AllowOrigins") and
5564
w.writesField(base, f, this) and
56-
this.asExpr() instanceof SliceLit and
57-
(
58-
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
59-
base.asInstruction() or
60-
gc.getV().getAUse() = base
61-
)
65+
this.asExpr() instanceof SliceLit
6266
)
6367
}
6468

69+
/**
70+
* Get config struct holding header values
71+
*/
72+
DataFlow::Node getBase() { result = base }
73+
6574
/**
6675
* Get config variable holding header values
6776
*/
68-
GinConfig getConfig() { result = gc }
77+
GinConfig getConfig() {
78+
exists(GinConfig gc |
79+
(
80+
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
81+
base.asInstruction() or
82+
gc.getV().getAUse() = base
83+
) and
84+
result = gc
85+
)
86+
}
6987
}
7088

7189
/**
7290
* A write to the value of Access-Control-Allow-Origins of value "*", overriding AllowOrigins
7391
*/
7492
class AllowAllOriginsWrite extends DataFlow::ExprNode {
75-
GinConfig gc;
93+
DataFlow::Node base;
7694

7795
AllowAllOriginsWrite() {
78-
exists(Field f, Write w, DataFlow::Node base |
96+
exists(Field f, Write w |
7997
f.hasQualifiedName(packagePath(), "Config", "AllowAllOrigins") and
8098
w.writesField(base, f, this) and
81-
this.getType() instanceof BoolType and
82-
(
83-
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
84-
base.asInstruction() or
85-
gc.getV().getAUse() = base
86-
)
99+
this.getType() instanceof BoolType
87100
)
88101
}
89102

103+
/**
104+
* Get config struct holding header values
105+
*/
106+
DataFlow::Node getBase() { result = base }
107+
90108
/**
91109
* Get config variable holding header values
92110
*/
93-
GinConfig getConfig() { result = gc }
111+
GinConfig getConfig() {
112+
exists(GinConfig gc |
113+
(
114+
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
115+
base.asInstruction() or
116+
gc.getV().getAUse() = base
117+
) and
118+
result = gc
119+
)
120+
}
94121
}
95122

96123
/**

go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,17 @@ predicate allowCredentialsIsSetToTrue(DataFlow::ExprNode allowOriginHW) {
105105
exists(GinCors::AllowCredentialsWrite allowCredentialsGin |
106106
allowCredentialsGin.getExpr().getBoolValue() = true
107107
|
108-
//flow only goes in one direction so fix this before PR
109108
allowCredentialsGin.getConfig() = allowOriginHW.(GinCors::AllowOriginsWrite).getConfig() and
110109
not exists(GinCors::AllowAllOriginsWrite allowAllOrigins |
111110
allowAllOrigins.getExpr().getBoolValue() = true and
112111
allowCredentialsGin.getConfig() = allowAllOrigins.getConfig()
113112
)
113+
or
114+
allowCredentialsGin.getBase() = allowOriginHW.(GinCors::AllowOriginsWrite).getBase() and
115+
not exists(GinCors::AllowAllOriginsWrite allowAllOrigins |
116+
allowAllOrigins.getExpr().getBoolValue() = true and
117+
allowCredentialsGin.getBase() = allowAllOrigins.getBase()
118+
)
114119
)
115120
}
116121

go/ql/test/experimental/CWE-942/CorsGin.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,24 @@ func AllowAllTrue() {
8383
})
8484
router.Run()
8585
}
86+
87+
func NoVariableVulnerable() {
88+
router := gin.Default()
89+
// CORS for https://foo.com origin, allowing:
90+
// - PUT and PATCH methods
91+
// - Origin header
92+
// - Credentials share
93+
// - Preflight requests cached for 12 hours
94+
router.Use(cors.New(cors.Config{
95+
AllowMethods: []string{"GET", "POST"},
96+
AllowHeaders: []string{"Origin"},
97+
ExposeHeaders: []string{"Content-Length"},
98+
AllowOrigins: []string{"null", "https://foo.com"},
99+
AllowCredentials: true,
100+
MaxAge: 12 * time.Hour,
101+
}))
102+
router.GET("/", func(c *gin.Context) {
103+
c.String(http.StatusOK, "hello world")
104+
})
105+
router.Run()
106+
}

go/ql/test/experimental/CWE-942/CorsMisconfiguration.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
| CorsGin.go:28:35:28:69 | slice literal | access-control-allow-origin header is set to `null`, and access-control-allow-credentials is set to `true` |
2+
| CorsGin.go:98:21:98:55 | slice literal | access-control-allow-origin header is set to `null`, and access-control-allow-credentials is set to `true` |
23
| CorsMisconfiguration.go:26:4:26:56 | call to Set | access-control-allow-origin header is set to `null`, and access-control-allow-credentials is set to `true` |
34
| CorsMisconfiguration.go:32:4:32:42 | call to Set | access-control-allow-origin header is set to `null`, and access-control-allow-credentials is set to `true` |
45
| CorsMisconfiguration.go:53:4:53:44 | call to Set | access-control-allow-origin header is set to a user-defined value, and access-control-allow-credentials is set to `true` |

0 commit comments

Comments
 (0)