security: reject traversal segments before permission checks
This commit is contained in:
@@ -123,6 +123,16 @@ func writeJSONError(w http.ResponseWriter, status int, message string) {
|
||||
w.WriteHeader(status)
|
||||
_ = json.NewEncoder(w).Encode(map[string]string{"error": message})
|
||||
}
|
||||
func unsafePath(p string) bool {
|
||||
p = strings.ReplaceAll(p, "\\", "/")
|
||||
for _, part := range strings.Split(p, "/") {
|
||||
if part == ".." {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func qpath(r *http.Request) string {
|
||||
return strings.Trim(strings.ReplaceAll(r.URL.Query().Get("filepath"), "\\", "/"), "/")
|
||||
}
|
||||
@@ -167,6 +177,10 @@ func writeCreated(w http.ResponseWriter) { w.WriteHeader(http.StatusCreated) }
|
||||
|
||||
func (s *Server) files(w http.ResponseWriter, r *http.Request) {
|
||||
a := account(r, s)
|
||||
if unsafePath(r.URL.Query().Get("filepath")) {
|
||||
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
|
||||
return
|
||||
}
|
||||
p := qpath(r)
|
||||
m := a.MaskFor(p)
|
||||
if !m.HasRead() {
|
||||
@@ -213,6 +227,10 @@ func (s *Server) newdir(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseMultipartForm(16 << 20)
|
||||
_ = r.ParseForm()
|
||||
p := qpath(r)
|
||||
if unsafePath(r.URL.Query().Get("filepath")) || unsafePath(r.FormValue("filepath")) {
|
||||
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
|
||||
return
|
||||
}
|
||||
if p == "" {
|
||||
p = strings.Trim(strings.ReplaceAll(r.FormValue("filepath"), "\\", "/"), "/")
|
||||
}
|
||||
@@ -536,6 +554,10 @@ func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
p := strings.Trim(strings.TrimPrefix(r.URL.Path, "/chfs/shared/"), "/")
|
||||
if unsafePath(p) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
fi, err := s.Store.Stat(p)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
@@ -716,6 +738,10 @@ func (s *Server) webdav(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
vp := strings.Trim(strings.TrimPrefix(r.URL.Path, "/webdav"), "/")
|
||||
if unsafePath(vp) {
|
||||
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
|
||||
return
|
||||
}
|
||||
old := r.URL.Path
|
||||
r.URL.Path = "/" + vp
|
||||
defer func() { r.URL.Path = old }()
|
||||
|
||||
Reference in New Issue
Block a user