fix(WOPI): SuggestedTarget header should not accept file path

master
Aaron Liu 4 days ago
parent 26b6b1044b
commit 7968e50429

@ -1 +1 @@
Subproject commit bf9c1ff7c196c6e3759bacdbf496d5dc2e2d2c35
Subproject commit 0b722766f8808b0a0aaa3c9f3e4766972d746d22

@ -4,11 +4,12 @@ import (
"context"
"errors"
"fmt"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"net/url"
"strings"
"time"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
@ -44,6 +45,7 @@ const (
LockTokenHeader = WopiHeaderPrefix + "Lock"
ItemVersionHeader = WopiHeaderPrefix + "ItemVersion"
SuggestedTargetHeader = WopiHeaderPrefix + "SuggestedTarget"
InvalidFileNameHeader = WopiHeaderPrefix + "InvalidFileNameError"
MethodLock = "LOCK"
MethodUnlock = "UNLOCK"

@ -218,6 +218,14 @@ func (service *WopiService) PutContent(c *gin.Context, isPutRelative bool) error
return fmt.Errorf("failed to decode X-WOPI-SuggestedTarget header (UTF-7): %w", err)
}
// X-WOPI-SuggestedTarget is a filename, not a path. Reject any value
// that could traverse out of the source file's directory.
if !isValidWopiSuggestedTarget(fileName) {
c.Status(http.StatusBadRequest)
c.Header(wopi.InvalidFileNameHeader, "Invalid target file name")
return nil
}
fileUriParsed, err := fs.NewUriFromString(fileUri)
if err != nil {
return fmt.Errorf("failed to parse file uri: %w", err)
@ -265,6 +273,19 @@ func (service *WopiService) PutContent(c *gin.Context, isPutRelative bool) error
return nil
}
// isValidWopiSuggestedTarget enforces that X-WOPI-SuggestedTarget is a bare
// filename (or extension prefixed with ".") and cannot traverse out of the
// source file's directory once joined onto it.
func isValidWopiSuggestedTarget(name string) bool {
if name == "" || name == "." || name == ".." {
return false
}
if strings.ContainsAny(name, "/\\") {
return false
}
return true
}
func (service *WopiService) GetFile(c *gin.Context) error {
uri, m, _, viewerSession, dep, err := prepareFs(c)
if err != nil {
@ -367,9 +388,9 @@ func (service *WopiService) FileInfo(c *gin.Context) (*WopiFileInfo, error) {
type (
CreateViewerSessionService struct {
Uri string `json:"uri" form:"uri" binding:"required"`
Version string `json:"version" form:"version"`
ViewerID string `json:"viewer_id" form:"viewer_id" binding:"required"`
Uri string `json:"uri" form:"uri" binding:"required"`
Version string `json:"version" form:"version"`
ViewerID string `json:"viewer_id" form:"viewer_id" binding:"required"`
PreferredAction types.ViewerAction `json:"preferred_action" form:"preferred_action" binding:"required"`
}
CreateViewerSessionParamCtx struct{}

Loading…
Cancel
Save