mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2026-05-06 15:20:32 +08:00
fix(fsmanage): improve path validation (#2437)
* fix(fsmanage): improve path validation in FsMove, FsCopy, and FsRemove functions
This commit is contained in:
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/OpenListTeam/OpenList/v4/server/common"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type MkdirOrLinkReq struct {
|
||||
@@ -110,15 +109,15 @@ func FsMove(c *gin.Context) {
|
||||
common.ErrorResp(c, errs.PermissionDenied, 403)
|
||||
return
|
||||
}
|
||||
|
||||
validPaths := make([]string, 0, len(req.Names))
|
||||
for _, name := range req.Names {
|
||||
if !strings.HasSuffix(srcDir, "/") {
|
||||
srcDir += "/"
|
||||
}
|
||||
for i, name := range req.Names {
|
||||
// ensure req.Names is not a relative path
|
||||
srcPath := stdpath.Join(req.SrcDir, name)
|
||||
srcPath, err = user.JoinPath(srcPath)
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 403)
|
||||
return
|
||||
srcPath := stdpath.Join(srcDir, name)
|
||||
if !strings.HasPrefix(srcPath+"/", srcDir) {
|
||||
req.Names[i] = ""
|
||||
continue
|
||||
}
|
||||
if !req.Overwrite {
|
||||
base := stdpath.Base(srcPath)
|
||||
@@ -135,14 +134,17 @@ func FsMove(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
validPaths = append(validPaths, srcPath)
|
||||
req.Names[i] = srcPath
|
||||
}
|
||||
|
||||
// Create all tasks immediately without any synchronous validation
|
||||
// All validation will be done asynchronously in the background
|
||||
var addedTasks []task.TaskExtensionInfo
|
||||
for i, p := range validPaths {
|
||||
t, err := fs.Move(c.Request.Context(), p, dstDir, len(validPaths) > i+1)
|
||||
for i, p := range req.Names {
|
||||
if p == "" {
|
||||
continue
|
||||
}
|
||||
t, err := fs.Move(c.Request.Context(), p, dstDir, len(req.Names) > i+1)
|
||||
if t != nil {
|
||||
addedTasks = append(addedTasks, t)
|
||||
}
|
||||
@@ -210,14 +212,15 @@ func FsCopy(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
validPaths := make([]string, 0, len(req.Names))
|
||||
for _, name := range req.Names {
|
||||
if !strings.HasSuffix(srcDir, "/") {
|
||||
srcDir += "/"
|
||||
}
|
||||
for i, name := range req.Names {
|
||||
// ensure req.Names is not a relative path
|
||||
srcPath := stdpath.Join(req.SrcDir, name)
|
||||
srcPath, err = user.JoinPath(srcPath)
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 403)
|
||||
return
|
||||
srcPath := stdpath.Join(srcDir, name)
|
||||
if !strings.HasPrefix(srcPath+"/", srcDir) {
|
||||
req.Names[i] = ""
|
||||
continue
|
||||
}
|
||||
if !req.Overwrite {
|
||||
base := stdpath.Base(srcPath)
|
||||
@@ -234,18 +237,21 @@ func FsCopy(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
validPaths = append(validPaths, srcPath)
|
||||
req.Names[i] = srcPath
|
||||
}
|
||||
|
||||
// Create all tasks immediately without any synchronous validation
|
||||
// All validation will be done asynchronously in the background
|
||||
var addedTasks []task.TaskExtensionInfo
|
||||
for i, p := range validPaths {
|
||||
for i, p := range req.Names {
|
||||
if p == "" {
|
||||
continue
|
||||
}
|
||||
var t task.TaskExtensionInfo
|
||||
if req.Merge {
|
||||
t, err = fs.Merge(c.Request.Context(), p, dstDir, len(validPaths) > i+1)
|
||||
t, err = fs.Merge(c.Request.Context(), p, dstDir, len(req.Names) > i+1)
|
||||
} else {
|
||||
t, err = fs.Copy(c.Request.Context(), p, dstDir, len(validPaths) > i+1)
|
||||
t, err = fs.Copy(c.Request.Context(), p, dstDir, len(req.Names) > i+1)
|
||||
}
|
||||
if t != nil {
|
||||
addedTasks = append(addedTasks, t)
|
||||
@@ -362,10 +368,12 @@ func FsRemove(c *gin.Context) {
|
||||
common.ErrorResp(c, errs.PermissionDenied, 403)
|
||||
return
|
||||
}
|
||||
if !strings.HasSuffix(reqPath, "/") {
|
||||
reqPath += "/"
|
||||
}
|
||||
for i, name := range req.Names {
|
||||
fullPath := stdpath.Join(reqPath, name)
|
||||
if !strings.HasPrefix(fullPath+"/", reqPath+"/") {
|
||||
log.Warnf("FsRemove: path traversal attempt skipped: %s (dir: %s)\n", name, req.Dir)
|
||||
if !strings.HasPrefix(fullPath+"/", reqPath) {
|
||||
req.Names[i] = ""
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user