@marcel91200 / caddy Mirror · read-only / commits / dae4913f
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

http: Patch path matcher to ignore dots and spaces (#2917)

(Try saying "patch path match" ten times fast)

Matthew Holt committed Dec 17, 2019 at 10:14 UTC dae4913fe35ff3f8a97383061ea8d44c1e98279e
4 files changed +23 -2
modules/caddyhttp/matchers.go
+8
@@ -165,6 +165,14 @@ func (m MatchPath) Provision(_ caddy.Context) error {
165 // Match returns true if r matches m.
166 func (m MatchPath) Match(r *http.Request) bool {
167 lowerPath := strings.ToLower(r.URL.Path)
168 +
169 + // see #2917; Windows ignores trailing dots and spaces
170 + // when accessing files (sigh), potentially causing a
171 + // security risk (cry) if PHP files end up being served
172 + // as static files, exposing the source code, instead of
173 + // being matched by *.php to be treated as PHP scripts
174 + lowerPath = strings.TrimRight(lowerPath, ". ")
175 +
176 for _, matchPath := range m {
177 // special case: first character is equals sign,
178 // treat it as an exact match
modules/caddyhttp/matchers_test.go
+12
@@ -247,6 +247,18 @@ func TestPathMatcher(t *testing.T) {
247 }
248 }
249
250 +func TestPathMatcherWindows(t *testing.T) {
251 + // only Windows has this bug where it will ignore
252 + // trailing dots and spaces in a filename, but we
253 + // test for it on all platforms to be more consistent
254 + match := MatchPath{"*.php"}
255 + req := &http.Request{URL: &url.URL{Path: "/index.php . . .."}}
256 + matched := match.Match(req)
257 + if !matched {
258 + t.Errorf("Expected to match; should ignore trailing dots and spaces")
259 + }
260 +}
261 +
262 func TestPathREMatcher(t *testing.T) {
263 for i, tc := range []struct {
264 match MatchPathRE
modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
+2 -1
@@ -115,7 +115,8 @@ func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
115 // php_fastcgi /subpath localhost:7777
116 //
117 // then the resulting routes are wrapped in a subroute that uses the
118 -// user's matcher as a prerequisite to enter the subroute.
118 +// user's matcher as a prerequisite to enter the subroute. In other
119 +// words, the directive's matcher is necessary, but not sufficient.
120 func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
121 if !h.Next() {
122 return nil, h.ArgErr()
modules/caddyhttp/routes.go
+1 -1
@@ -115,7 +115,7 @@ func (routes RouteList) Provision(ctx caddy.Context) error {
115 // matchers
116 matchersIface, err := ctx.LoadModule(&route, "MatcherSetsRaw")
117 if err != nil {
118 - return fmt.Errorf("loadng matchers in route %d: %v", i, err)
118 + return fmt.Errorf("loading matchers in route %d: %v", i, err)
119 }
120 err = routes[i].MatcherSets.FromInterface(matchersIface)
121 if err != nil {