Skip to content

Commit dcc2b2c

Browse files
authored
Merge pull request github#15057 from aydinnyunus/main
Web Cache Deception Vulnerability on Go Frameworks
2 parents 00e77a3 + 8a7c3c1 commit dcc2b2c

20 files changed

+1598
-18
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
| WebCacheDeceptionBad.go:82:18:82:31 | "/adminusers/" | "/adminusers/" is used as wildcard endpoint. |
2+
| WebCacheDeceptionFiber.go:15:10:15:17 | "/api/*" | "/api/*" is used as wildcard endpoint. |
3+
| WebCacheDeceptionFiber.go:20:11:20:18 | "/api/*" | "/api/*" is used as wildcard endpoint. |
4+
| WebCacheDeceptionGoChi.go:13:8:13:11 | "/*" | "/*" is used as wildcard endpoint. |
5+
| WebCacheDeceptionHTTPRouter.go:21:13:21:25 | "/test/*test" | "/test/*test" is used as wildcard endpoint. |

go/ql/src/experimental/CWE-525/WebCacheDeception.qhelp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,31 @@
1717
<p>
1818
Vulnerable code example: A web server is configured to cache all responses ending in '.css'. An attacker requests 'profile.css', and the server processes 'profile', a sensitive page, and caches it.
1919
</p>
20-
<sample src="WebCacheDeceptionBad.go" />
20+
<sample src="examples/WebCacheDeceptionBad.go" />
2121
</example>
2222
<example>
2323
<p>
2424
Secure code example: The server is configured with strict cache controls and URL validation, preventing caching of dynamic or sensitive pages regardless of their URL pattern.
2525
</p>
26-
<sample src="WebCacheDeceptionGood.go" />
26+
<sample src="examples/WebCacheDeceptionGood.go" />
27+
</example>
28+
<example>
29+
<p>
30+
Vulnerable code example: The server is configured with strict cache controls and URL validation, preventing caching of dynamic or sensitive pages regardless of their URL pattern.
31+
</p>
32+
<sample src="examples/WebCacheDeceptionFiber.go" />
33+
</example>
34+
<example>
35+
<p>
36+
Vulnerable code example: The server is configured with strict cache controls and URL validation, preventing caching of dynamic or sensitive pages regardless of their URL pattern.
37+
</p>
38+
<sample src="examples/WebCacheDeceptionGoChi.go" />
39+
</example>
40+
<example>
41+
<p>
42+
Vulnerable code example: The server is configured with strict cache controls and URL validation, preventing caching of dynamic or sensitive pages regardless of their URL pattern.
43+
</p>
44+
<sample src="examples/WebCacheDeceptionHTTPRouter.go" />
2745
</example>
2846
<references>
2947
<li>

go/ql/src/experimental/CWE-525/WebCacheDeception.ql

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,7 @@
1111
*/
1212

1313
import go
14+
import WebCacheDeceptionLib
1415

15-
from
16-
DataFlow::CallNode httpHandleFuncCall, DataFlow::ReadNode rn, Http::HeaderWrite::Range hw,
17-
DeclaredFunction f
18-
where
19-
httpHandleFuncCall.getTarget().hasQualifiedName("net/http", "HandleFunc") and
20-
httpHandleFuncCall.getArgument(0).getStringValue().matches("%/") and
21-
httpHandleFuncCall.getArgument(1) = rn and
22-
rn.reads(f) and
23-
f.getParameter(0) = hw.getResponseWriter() and
24-
hw.getHeaderName() = "cache-control"
25-
select httpHandleFuncCall.getArgument(0),
26-
"Wildcard Endpoint used with " + httpHandleFuncCall.getArgument(0) + " and '" + hw.getHeaderName()
27-
+ "' Header is used"
16+
from WebCacheDeception::Sink httpHandleFuncCall
17+
select httpHandleFuncCall, httpHandleFuncCall + " is used as wildcard endpoint."
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import go
2+
import StringOps
3+
4+
module WebCacheDeception {
5+
abstract class Sink extends DataFlow::Node { }
6+
7+
private class GoNetHttp extends Sink {
8+
GoNetHttp() {
9+
exists(
10+
DataFlow::CallNode m, DataFlow::ReadNode rn, Http::HeaderWrite::Range hw, DeclaredFunction f
11+
|
12+
m.getTarget().hasQualifiedName("net/http", "HandleFunc") and
13+
m.getArgument(0).getStringValue().matches("%/") and
14+
m.getArgument(1) = rn and
15+
rn.reads(f) and
16+
f.getParameter(0) = hw.getResponseWriter() and
17+
hw.getHeaderName() = "cache-control" and
18+
this = m.getArgument(0)
19+
)
20+
}
21+
}
22+
23+
private class GoFiber extends Sink {
24+
GoFiber() {
25+
exists(ImportSpec i |
26+
i.getPath() = "github.com/gofiber/fiber" or
27+
i.getPath() = "github.com/gofiber/fiber/v2"
28+
|
29+
exists(DataFlow::CallNode m |
30+
m.getCall().getArgument(0).toString().matches("%/*%") and
31+
this = m.getArgument(0)
32+
)
33+
)
34+
}
35+
}
36+
37+
private class GoChi extends Sink {
38+
GoChi() {
39+
exists(ImportSpec i |
40+
i.getPath() = "github.com/go-chi/chi/v5" or
41+
i.getPath() = "github.com/go-chi/chi/v5/middleware"
42+
|
43+
exists(DataFlow::CallNode m |
44+
m.getCall().getArgument(0).toString().matches("%/*%") and
45+
this = m.getArgument(0)
46+
)
47+
)
48+
}
49+
}
50+
51+
private class GoHttpRouter extends Sink {
52+
GoHttpRouter() {
53+
exists(string pkg | pkg = "github.com/julienschmidt/httprouter" |
54+
exists(DataFlow::CallNode m |
55+
m.getCall().getArgument(0).toString().matches("%/*%") and
56+
this = m.getArgument(0)
57+
)
58+
)
59+
}
60+
}
61+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package fiber
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/gofiber/fiber/v2"
8+
)
9+
10+
func main() {
11+
app := fiber.New()
12+
log.Println("We are logging in Golang!")
13+
14+
// GET /api/register
15+
app.Get("/api/*", func(c *fiber.Ctx) error {
16+
msg := fmt.Sprintf("✋")
17+
return c.SendString(msg) // => ✋ register
18+
})
19+
20+
app.Post("/api/*", func(c *fiber.Ctx) error {
21+
msg := fmt.Sprintf("✋")
22+
return c.SendString(msg) // => ✋ register
23+
})
24+
25+
// GET /flights/LAX-SFO
26+
app.Get("/flights/:from-:to", func(c *fiber.Ctx) error {
27+
msg := fmt.Sprintf("💸 From: %s, To: %s", c.Params("from"), c.Params("to"))
28+
return c.SendString(msg) // => 💸 From: LAX, To: SFO
29+
})
30+
31+
// GET /dictionary.txt
32+
app.Get("/:file.:ext", func(c *fiber.Ctx) error {
33+
msg := fmt.Sprintf("📃 %s.%s", c.Params("file"), c.Params("ext"))
34+
return c.SendString(msg) // => 📃 dictionary.txt
35+
})
36+
37+
log.Fatal(app.Listen(":3000"))
38+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/go-chi/chi/v5"
7+
"github.com/go-chi/chi/v5/middleware"
8+
)
9+
10+
func main() {
11+
r := chi.NewRouter()
12+
r.Use(middleware.Logger)
13+
r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
14+
w.Write([]byte("welcome"))
15+
})
16+
http.ListenAndServe(":3000", r)
17+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package httprouter
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/http"
7+
8+
"github.com/julienschmidt/httprouter"
9+
)
10+
11+
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
12+
fmt.Fprint(w, "Welcome!\n")
13+
}
14+
15+
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
16+
fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
17+
}
18+
19+
func main() {
20+
router := httprouter.New()
21+
router.GET("/test/*test", Index)
22+
router.GET("/hello/:name", Hello)
23+
24+
log.Fatal(http.ListenAndServe(":8082", router))
25+
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
| WebCacheDeceptionBad.go:82:18:82:31 | "/adminusers/" | Wildcard Endpoint used with "/adminusers/" and 'cache-control' Header is used |
1+
| WebCacheDeceptionBad.go:82:18:82:31 | "/adminusers/" | "/adminusers/" is used as wildcard endpoint. |
2+
| WebCacheDeceptionFiber.go:15:10:15:17 | "/api/*" | "/api/*" is used as wildcard endpoint. |
3+
| WebCacheDeceptionFiber.go:20:11:20:18 | "/api/*" | "/api/*" is used as wildcard endpoint. |
4+
| WebCacheDeceptionGoChi.go:13:8:13:11 | "/*" | "/*" is used as wildcard endpoint. |
5+
| WebCacheDeceptionHTTPRouter.go:21:13:21:25 | "/test/*test" | "/test/*test" is used as wildcard endpoint. |

0 commit comments

Comments
 (0)