diff options
author | Matt Holt <mholt@users.noreply.github.com> | 2021-06-17 09:59:08 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-17 09:59:08 -0600 |
commit | 9d4ed3a3236df06e54c80c4f6633b66d68ad3673 (patch) | |
tree | f516a98ff44465f2434a03c4625dc969d87857e2 /modules/caddyhttp/caddyhttp_test.go | |
parent | fbd6560976dc73052bd5d3277869912de68f6731 (diff) |
caddyhttp: Refactor and export SanitizedPathJoin for use in fastcgi (#4207)
Diffstat (limited to 'modules/caddyhttp/caddyhttp_test.go')
-rw-r--r-- | modules/caddyhttp/caddyhttp_test.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/modules/caddyhttp/caddyhttp_test.go b/modules/caddyhttp/caddyhttp_test.go new file mode 100644 index 0000000..09011fe --- /dev/null +++ b/modules/caddyhttp/caddyhttp_test.go @@ -0,0 +1,94 @@ +package caddyhttp + +import ( + "net/url" + "path/filepath" + "testing" +) + +func TestSanitizedPathJoin(t *testing.T) { + // For reference: + // %2e = . + // %2f = / + // %5c = \ + for i, tc := range []struct { + inputRoot string + inputPath string + expect string + }{ + { + inputPath: "", + expect: ".", + }, + { + inputPath: "/", + expect: ".", + }, + { + inputPath: "/foo", + expect: "foo", + }, + { + inputPath: "/foo/", + expect: "foo" + separator, + }, + { + inputPath: "/foo/bar", + expect: filepath.Join("foo", "bar"), + }, + { + inputRoot: "/a", + inputPath: "/foo/bar", + expect: filepath.Join("/", "a", "foo", "bar"), + }, + { + inputPath: "/foo/../bar", + expect: "bar", + }, + { + inputRoot: "/a/b", + inputPath: "/foo/../bar", + expect: filepath.Join("/", "a", "b", "bar"), + }, + { + inputRoot: "/a/b", + inputPath: "/..%2fbar", + expect: filepath.Join("/", "a", "b", "bar"), + }, + { + inputRoot: "/a/b", + inputPath: "/%2e%2e%2fbar", + expect: filepath.Join("/", "a", "b", "bar"), + }, + { + inputRoot: "/a/b", + inputPath: "/%2e%2e%2f%2e%2e%2f", + expect: filepath.Join("/", "a", "b") + separator, + }, + { + inputRoot: "C:\\www", + inputPath: "/foo/bar", + expect: filepath.Join("C:\\www", "foo", "bar"), + }, + { + inputRoot: "C:\\www", + inputPath: "/D:\\foo\\bar", + expect: filepath.Join("C:\\www", "D:\\foo\\bar"), + }, + } { + // we don't *need* to use an actual parsed URL, but it + // adds some authenticity to the tests since real-world + // values will be coming in from URLs; thus, the test + // corpus can contain paths as encoded by clients, which + // more closely emulates the actual attack vector + u, err := url.Parse("http://test:9999" + tc.inputPath) + if err != nil { + t.Fatalf("Test %d: invalid URL: %v", i, err) + } + actual := SanitizedPathJoin(tc.inputRoot, u.Path) + if actual != tc.expect { + t.Errorf("Test %d: SanitizedPathJoin('%s', '%s') => %s (expected '%s')", + i, tc.inputRoot, tc.inputPath, actual, tc.expect) + } + } +} |