1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-04 21:35:23 +02:00

fix(filesystem): harden the filesystem service to avoid path traversal attacks EE-1922 (#5957)

fix(filesystem): harden the filesystem service to avoid path traversal attacks EE-1922
This commit is contained in:
andres-portainer 2021-11-01 08:01:03 -03:00 committed by GitHub
parent c763219f74
commit 28f71e486a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 292 additions and 176 deletions

View file

@ -2,7 +2,6 @@ package customtemplates
import (
"net/http"
"path"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
@ -41,7 +40,7 @@ func (handler *Handler) customTemplateFile(w http.ResponseWriter, r *http.Reques
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a custom template with the specified identifier inside the database", err}
}
fileContent, err := handler.FileService.GetFileContent(path.Join(customTemplate.ProjectPath, customTemplate.EntryPoint))
fileContent, err := handler.FileService.GetFileContent(customTemplate.ProjectPath, customTemplate.EntryPoint)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve custom template file from disk", err}
}

View file

@ -39,7 +39,7 @@ func (handler *Handler) edgeJobFile(w http.ResponseWriter, r *http.Request) *htt
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an Edge job with the specified identifier inside the database", err}
}
edgeJobFileContent, err := handler.FileService.GetFileContent(edgeJob.ScriptPath)
edgeJobFileContent, err := handler.FileService.GetFileContent("", edgeJob.ScriptPath)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve Edge job script file from disk", err}
}

View file

@ -2,7 +2,6 @@ package edgestacks
import (
"net/http"
"path"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
@ -45,7 +44,7 @@ func (handler *Handler) edgeStackFile(w http.ResponseWriter, r *http.Request) *h
fileName = stack.ManifestPath
}
stackFileContent, err := handler.FileService.GetFileContent(path.Join(stack.ProjectPath, fileName))
stackFileContent, err := handler.FileService.GetFileContent(stack.ProjectPath, fileName)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve Compose file from disk", err}
}

View file

@ -3,7 +3,6 @@ package edgestacks
import (
"fmt"
"net/http"
"path"
"strconv"
"github.com/gorilla/mux"
@ -56,7 +55,7 @@ func (handler *Handler) convertAndStoreKubeManifestIfNeeded(edgeStack *portainer
return nil
}
composeConfig, err := handler.FileService.GetFileContent(path.Join(edgeStack.ProjectPath, edgeStack.EntryPoint))
composeConfig, err := handler.FileService.GetFileContent(edgeStack.ProjectPath, edgeStack.EntryPoint)
if err != nil {
return fmt.Errorf("unable to retrieve Compose file from disk: %w", err)
}

View file

@ -3,7 +3,6 @@ package endpointedge
import (
"errors"
"net/http"
"path"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
@ -75,7 +74,7 @@ func (handler *Handler) endpointEdgeStackInspect(w http.ResponseWriter, r *http.
}
}
stackFileContent, err := handler.FileService.GetFileContent(path.Join(edgeStack.ProjectPath, fileName))
stackFileContent, err := handler.FileService.GetFileContent(edgeStack.ProjectPath, fileName)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve Compose file from disk", err}
}

View file

@ -131,7 +131,7 @@ func (handler *Handler) endpointStatusInspect(w http.ResponseWriter, r *http.Req
Version: job.Version,
}
file, err := handler.FileService.GetFileContent(job.ScriptPath)
file, err := handler.FileService.GetFileContent("", job.ScriptPath)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve Edge job script file", err}

View file

@ -3,7 +3,6 @@ package stacks
import (
"fmt"
"net/http"
"path"
"strconv"
"time"
@ -389,10 +388,9 @@ func (handler *Handler) deployComposeStack(config *composeStackDeploymentConfig)
!isAdminOrEndpointAdmin {
for _, file := range append([]string{config.stack.EntryPoint}, config.stack.AdditionalFiles...) {
path := path.Join(config.stack.ProjectPath, file)
stackContent, err := handler.FileService.GetFileContent(path)
stackContent, err := handler.FileService.GetFileContent(config.stack.ProjectPath, file)
if err != nil {
return errors.Wrapf(err, "failed to get stack file content `%q`", path)
return errors.Wrapf(err, "failed to get stack file content `%q`", file)
}
err = handler.isValidStackFile(stackContent, securitySettings)

View file

@ -3,7 +3,6 @@ package stacks
import (
"fmt"
"net/http"
"path"
"strconv"
"time"
@ -399,8 +398,7 @@ func (handler *Handler) deploySwarmStack(config *swarmStackDeploymentConfig) err
if !settings.AllowBindMountsForRegularUsers && !isAdminOrEndpointAdmin {
for _, file := range append([]string{config.stack.EntryPoint}, config.stack.AdditionalFiles...) {
path := path.Join(config.stack.ProjectPath, file)
stackContent, err := handler.FileService.GetFileContent(path)
stackContent, err := handler.FileService.GetFileContent(config.stack.ProjectPath, file)
if err != nil {
return errors.WithMessage(err, "failed to get stack file content")
}

View file

@ -6,7 +6,6 @@ import (
"io/ioutil"
"net/http"
"os"
"path"
"strconv"
"github.com/pkg/errors"
@ -198,8 +197,8 @@ func (handler *Handler) deleteStack(userID portainer.UserID, stack *portainer.St
defer os.RemoveAll(tmpDir)
for _, fileName := range fileNames {
manifestFilePath := path.Join(tmpDir, fileName)
manifestContent, err := ioutil.ReadFile(path.Join(stack.ProjectPath, fileName))
manifestFilePath := filesystem.JoinPaths(tmpDir, fileName)
manifestContent, err := handler.FileService.GetFileContent(stack.ProjectPath, fileName)
if err != nil {
return errors.Wrap(err, "failed to read manifest file")
}

View file

@ -2,7 +2,6 @@ package stacks
import (
"net/http"
"path"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
@ -82,7 +81,7 @@ func (handler *Handler) stackFile(w http.ResponseWriter, r *http.Request) *httpe
}
}
stackFileContent, err := handler.FileService.GetFileContent(path.Join(stack.ProjectPath, stack.EntryPoint))
stackFileContent, err := handler.FileService.GetFileContent(stack.ProjectPath, stack.EntryPoint)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve Compose file from disk", err}
}

View file

@ -5,7 +5,6 @@ import (
"io/ioutil"
"net/http"
"os"
"path"
"strconv"
"github.com/asaskevich/govalidator"
@ -108,7 +107,7 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
tempFileDir, _ := ioutil.TempDir("", "kub_file_content")
defer os.RemoveAll(tempFileDir)
if err := filesystem.WriteToFile(path.Join(tempFileDir, stack.EntryPoint), []byte(payload.StackFileContent)); err != nil {
if err := filesystem.WriteToFile(filesystem.JoinPaths(tempFileDir, stack.EntryPoint), []byte(payload.StackFileContent)); err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Failed to persist deployment file in a temp directory", Err: err}
}

View file

@ -4,7 +4,6 @@ import (
"errors"
"log"
"net/http"
"path"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
@ -68,9 +67,7 @@ func (handler *Handler) templateFile(w http.ResponseWriter, r *http.Request) *ht
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to clone git repository", err}
}
composeFilePath := path.Join(projectPath, payload.ComposeFilePathInRepository)
fileContent, err := handler.FileService.GetFileContent(composeFilePath)
fileContent, err := handler.FileService.GetFileContent(projectPath, payload.ComposeFilePathInRepository)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Failed loading file content", err}
}