1
mirror of https://github.com/rclone/rclone synced 2025-01-17 22:27:30 +01:00

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
This commit is contained in:
Richard Patel 2019-09-28 14:50:27 +02:00 committed by Nick Craig-Wood
parent 44b603d2bd
commit 32d5af8fb6

View File

@ -3,12 +3,14 @@ package rcd
import ( import (
"archive/zip" "archive/zip"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"log" "log"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/rclone/rclone/cmd" "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 // unzip is a helper function to unzip a file specified in src to path dest
func unzip(src, dest string) (err error) { func unzip(src, dest string) (err error) {
dest = filepath.Clean(dest) + string(os.PathSeparator)
r, err := zip.OpenReader(src) r, err := zip.OpenReader(src)
if err != nil { if err != nil {
return err 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 // Closure to address file descriptors issue with all the deferred .Close() methods
extractAndWriteFile := func(f *zip.File) error { 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() rc, err := f.Open()
if err != nil { if err != nil {
return err return err
} }
defer fs.CheckClose(rc, &err) defer fs.CheckClose(rc, &err)
path := filepath.Join(dest, f.Name)
if f.FileInfo().IsDir() { if f.FileInfo().IsDir() {
if err := os.MkdirAll(path, 0755); err != nil { if err := os.MkdirAll(path, 0755); err != nil {
return err return err