From 094ee331d6cebb1589dd87d1dfde07107c2915ca Mon Sep 17 00:00:00 2001 From: Laurynas Gadliauskas Date: Tue, 8 Jun 2021 18:28:05 +0300 Subject: [PATCH] fix: validate symlink's target (#11) --- files/file.go | 26 ++++++++++++++++++++------ http/resource.go | 11 +++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/files/file.go b/files/file.go index 8dfc299c..bfec691f 100644 --- a/files/file.go +++ b/files/file.go @@ -65,6 +65,21 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { return nil, os.ErrPermission } + isSymlink := false + symlink := "" + if lst, ok := opts.Fs.(afero.Lstater); ok { + info, _, err := lst.LstatIfPossible(opts.Path) + if err == nil { + isSymlink = IsSymlink(info.Mode()) + } + } + + if isSymlink { + if lsf, ok := opts.Fs.(afero.LinkReader); ok { + symlink, _ = lsf.ReadlinkIfPossible(opts.Path) + } + } + info, err := opts.Fs.Stat(opts.Path) if err != nil { return nil, err @@ -77,6 +92,8 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { ModTime: info.ModTime(), Mode: info.Mode(), IsDir: info.IsDir(), + IsSymlink: isSymlink, + Link: symlink, Size: info.Size(), Extension: filepath.Ext(info.Name()), Token: opts.Token, @@ -257,7 +274,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { } isSymlink := IsSymlink(f.Mode()) - symLink := "" + symlink := "" if isSymlink { // It's a symbolic link. We try to follow it. If it doesn't work, // we stay with the link information instead of the target's. @@ -268,10 +285,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { // Try to read the link's target if lsf, ok := i.Fs.(afero.LinkReader); ok { - link, err := lsf.ReadlinkIfPossible(fPath) - if err == nil { - symLink = link - } + symlink, _ = lsf.ReadlinkIfPossible(fPath) } } @@ -283,7 +297,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { Mode: f.Mode(), IsDir: f.IsDir(), IsSymlink: isSymlink, - Link: symLink, + Link: symlink, Extension: filepath.Ext(name), Path: fPath, } diff --git a/http/resource.go b/http/resource.go index c6737f04..644c624d 100644 --- a/http/resource.go +++ b/http/resource.go @@ -37,6 +37,17 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d return errToStatus(err), err } + // check if symlink's target is within base path + if file.IsSymlink { + parentDir := filepath.Dir(filepath.Clean(file.Path)) + fullLinkTarget := filepath.Join(d.user.FullPath(parentDir), file.Link) + scopedLinkTarget := d.user.FullPath(filepath.Join(parentDir, file.Link)) + if fullLinkTarget != scopedLinkTarget { + err = errors.ErrNotExist + return errToStatus(err), err + } + } + if r.URL.Query().Get("disk_usage") == "true" { du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path, 100) if err != nil {