fix: validate symlink's target (#11)

pull/3756/head
Laurynas Gadliauskas 2021-06-08 18:28:05 +03:00 committed by GitHub
parent 372b1f00ed
commit 094ee331d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 6 deletions

View File

@ -65,6 +65,21 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
return nil, os.ErrPermission 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) info, err := opts.Fs.Stat(opts.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -77,6 +92,8 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
ModTime: info.ModTime(), ModTime: info.ModTime(),
Mode: info.Mode(), Mode: info.Mode(),
IsDir: info.IsDir(), IsDir: info.IsDir(),
IsSymlink: isSymlink,
Link: symlink,
Size: info.Size(), Size: info.Size(),
Extension: filepath.Ext(info.Name()), Extension: filepath.Ext(info.Name()),
Token: opts.Token, Token: opts.Token,
@ -257,7 +274,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
} }
isSymlink := IsSymlink(f.Mode()) isSymlink := IsSymlink(f.Mode())
symLink := "" symlink := ""
if isSymlink { if isSymlink {
// It's a symbolic link. We try to follow it. If it doesn't work, // 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. // 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 // Try to read the link's target
if lsf, ok := i.Fs.(afero.LinkReader); ok { if lsf, ok := i.Fs.(afero.LinkReader); ok {
link, err := lsf.ReadlinkIfPossible(fPath) symlink, _ = lsf.ReadlinkIfPossible(fPath)
if err == nil {
symLink = link
}
} }
} }
@ -283,7 +297,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
Mode: f.Mode(), Mode: f.Mode(),
IsDir: f.IsDir(), IsDir: f.IsDir(),
IsSymlink: isSymlink, IsSymlink: isSymlink,
Link: symLink, Link: symlink,
Extension: filepath.Ext(name), Extension: filepath.Ext(name),
Path: fPath, Path: fPath,
} }

View File

@ -37,6 +37,17 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
return errToStatus(err), err 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" { if r.URL.Query().Get("disk_usage") == "true" {
du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path, 100) du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path, 100)
if err != nil { if err != nil {