From 32d5af8fb61adf1f3ebdadaf2c61350587965b0f Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Sat, 28 Sep 2019 14:50:27 +0200 Subject: [PATCH] cmd/rcd: Address ZipSlip vulnerability Don't create files outside of target directory while unzipping. Fixes #3529 reported by Nico Waisman at Semmle Security Team --- cmd/rcd/rcd.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/rcd/rcd.go b/cmd/rcd/rcd.go index d6f360b96..0e2b15fde 100644 --- a/cmd/rcd/rcd.go +++ b/cmd/rcd/rcd.go @@ -3,12 +3,14 @@ package rcd import ( "archive/zip" "encoding/json" + "fmt" "io" "log" "net/http" "os" "path/filepath" "strconv" + "strings" "time" "github.com/rclone/rclone/cmd" @@ -179,6 +181,8 @@ func downloadFile(filepath string, url string) error { // unzip is a helper function to unzip a file specified in src to path dest func unzip(src, dest string) (err error) { + dest = filepath.Clean(dest) + string(os.PathSeparator) + r, err := zip.OpenReader(src) if err != nil { return err @@ -191,14 +195,18 @@ func unzip(src, dest string) (err error) { // Closure to address file descriptors issue with all the deferred .Close() methods extractAndWriteFile := func(f *zip.File) error { + path := filepath.Join(dest, f.Name) + // Check for Zip Slip: https://github.com/rclone/rclone/issues/3529 + if !strings.HasPrefix(path, dest) { + return fmt.Errorf("%s: illegal file path", path) + } + rc, err := f.Open() if err != nil { return err } defer fs.CheckClose(rc, &err) - path := filepath.Join(dest, f.Name) - if f.FileInfo().IsDir() { if err := os.MkdirAll(path, 0755); err != nil { return err