From 33c41b55bb43e8c5a7c1f11aed485ba1fcb31629 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Wed, 23 Dec 2020 11:30:00 +0100 Subject: [PATCH] Security: Prevent loading of usernames containing a slash "/" is valid char in HTTP authorization headers, but is also used in rest-server to map usernames to private repos. This commit prevents loading maliciously composed usernames like "/foo/config" by restricting the allowed characters to the unicode character class, numbers, "-", "." and "@". Closes #131 --- changelog/unreleased/issue-131 | 16 ++++++++++++++++ htpasswd.go | 6 ++++++ 2 files changed, 22 insertions(+) create mode 100644 changelog/unreleased/issue-131 diff --git a/changelog/unreleased/issue-131 b/changelog/unreleased/issue-131 new file mode 100644 index 0000000..2c7877c --- /dev/null +++ b/changelog/unreleased/issue-131 @@ -0,0 +1,16 @@ +Security: Prevent loading of usernames containing a slash + +"/" is valid char in HTTP authorization headers, but is also used in +rest-server to map usernames to private repos. + +This commit prevents loading maliciously composed usernames like +"/foo/config" by restricting the allowed characters to the unicode +character class, numbers, "-", "." and "@". + +This prevents requests to other users files like: + +curl -v -X DELETE -u foo/config:attack http://localhost:8000/foo/config + +https://github.com/restic/rest-server/issues/131 +https://github.com/restic/rest-server/pull/132 + diff --git a/htpasswd.go b/htpasswd.go index cadd7ef..d319e05 100644 --- a/htpasswd.go +++ b/htpasswd.go @@ -100,6 +100,8 @@ func (h *HtpasswdFile) throttleTimer() { } } +var validUsernameRegexp = regexp.MustCompile(`^[\p{L}@.-]+$`) + // Reload reloads the htpasswd file. If the reload fails, the Users map is not changed and the error is returned. func (h *HtpasswdFile) Reload() error { r, err := os.Open(h.path) @@ -119,6 +121,10 @@ func (h *HtpasswdFile) Reload() error { } users := make(map[string]string) for _, record := range records { + if !validUsernameRegexp.MatchString(record[0]) { + log.Printf("Ignoring invalid username %q in htpasswd, consists of characters other than letters", record[0]) + continue + } users[record[0]] = record[1] }