Skip to content

Commit 98f4320

Browse files
committed
fix(serverHandler): prevent mutation from parent directory
When passing file path for Upload, Mkdir and Delete, treat parent directory path as illegal path.
1 parent 8a958cb commit 98f4320

File tree

5 files changed

+117
-8
lines changed

5 files changed

+117
-8
lines changed

src/serverHandler/delete.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
package serverHandler
22

33
import (
4+
"errors"
45
"os"
56
)
67

78
func (h *handler) deleteItems(fsPrefix string, files []string, aliasSubItems []os.FileInfo) bool {
89
errs := []error{}
910

10-
for _, filename := range files {
11-
if containsItem(aliasSubItems, filename) {
11+
for _, inputFilename := range files {
12+
if len(inputFilename) == 0 {
13+
continue
14+
}
15+
16+
var filename string
17+
var ok bool
18+
if filename, ok = getCleanFilePath(inputFilename); !ok {
19+
errs = append(errs, errors.New("delete: illegal item name "+inputFilename))
20+
continue
21+
} else if containsItem(aliasSubItems, filename) {
1222
continue
1323
}
1424
err := os.RemoveAll(fsPrefix + "/" + filename)

src/serverHandler/mkdir.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
package serverHandler
22

33
import (
4+
"errors"
45
"os"
56
)
67

78
func (h *handler) mkdirs(fsPrefix string, files []string, aliasSubItems []os.FileInfo) bool {
89
errs := []error{}
910

10-
for _, filename := range files {
11-
if len(filename) == 0 {
11+
for _, inputFilename := range files {
12+
if len(inputFilename) == 0 {
13+
continue
14+
}
15+
16+
var filename string
17+
var ok bool
18+
if filename, ok = getCleanFilePath(inputFilename); !ok {
19+
errs = append(errs, errors.New("mkdir: illegal directory name "+inputFilename))
1220
continue
1321
} else if containsItem(aliasSubItems, filename) {
1422
continue

src/serverHandler/upload.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@ func (h *handler) saveUploadFiles(fsPrefix string, createDir, overwriteExists bo
5858
break
5959
}
6060

61-
partFilename := path.Clean(strings.Replace(part.FileName(), "\\", "/", -1))
62-
if partFilename[0] == '/' {
63-
partFilename = partFilename[1:]
61+
inputPartFilename := part.FileName()
62+
if len(inputPartFilename) == 0 {
63+
continue
6464
}
65-
if len(partFilename) == 0 {
65+
partFilename, ok := getCleanDirFilePath(inputPartFilename)
66+
if !ok {
67+
errs = append(errs, errors.New("upload: illegal file name "+inputPartFilename))
6668
continue
6769
}
6870

src/serverHandler/util.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package serverHandler
33
import (
44
"net/http"
55
"os"
6+
"path"
7+
"strings"
68
)
79

810
func needResponseBody(method string) bool {
@@ -20,3 +22,17 @@ func containsItem(infos []os.FileInfo, name string) bool {
2022
}
2123
return false
2224
}
25+
26+
func getCleanFilePath(requestPath string) (filePath string, ok bool) {
27+
filePath = path.Clean(requestPath)
28+
ok = filePath == path.Base(filePath)
29+
30+
return
31+
}
32+
33+
func getCleanDirFilePath(requestPath string) (filePath string, ok bool) {
34+
filePath = path.Clean(strings.Replace(requestPath, "\\", "/", -1))
35+
ok = filePath[0] != '/' && filePath != "." && filePath != ".." && !strings.HasPrefix(filePath, "../")
36+
37+
return
38+
}

src/serverHandler/util_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package serverHandler
2+
3+
import "testing"
4+
5+
func TestGetCleanFilePath(t *testing.T) {
6+
var cleanPath string
7+
var ok bool
8+
9+
cleanPath, ok = getCleanFilePath("file1")
10+
if cleanPath != "file1" || !ok {
11+
t.Error(cleanPath, ok)
12+
}
13+
14+
cleanPath, ok = getCleanFilePath("./file2")
15+
if cleanPath != "file2" || !ok {
16+
t.Error(cleanPath, ok)
17+
}
18+
19+
cleanPath, ok = getCleanFilePath("./dir/file3")
20+
if ok {
21+
t.Error(cleanPath, ok)
22+
}
23+
24+
cleanPath, ok = getCleanFilePath("dir/file4")
25+
if ok {
26+
t.Error(cleanPath, ok)
27+
}
28+
29+
cleanPath, ok = getCleanFilePath("../file5")
30+
if ok {
31+
t.Error(cleanPath, ok)
32+
}
33+
}
34+
35+
func TestGetCleanDirFilePath(t *testing.T) {
36+
var cleanPath string
37+
var ok bool
38+
39+
cleanPath, ok = getCleanDirFilePath("file1")
40+
if cleanPath != "file1" || !ok {
41+
t.Error(cleanPath, ok)
42+
}
43+
44+
cleanPath, ok = getCleanDirFilePath("./file2")
45+
if cleanPath != "file2" || !ok {
46+
t.Error(cleanPath, ok)
47+
}
48+
49+
cleanPath, ok = getCleanDirFilePath("./dir/file3")
50+
if cleanPath != "dir/file3" || !ok {
51+
t.Error(cleanPath, ok)
52+
}
53+
54+
cleanPath, ok = getCleanDirFilePath("dir/file4")
55+
if cleanPath != "dir/file4" || !ok {
56+
t.Error(cleanPath, ok)
57+
}
58+
59+
cleanPath, ok = getCleanDirFilePath("dir1/../dir2/file5")
60+
if cleanPath != "dir2/file5" || !ok {
61+
t.Error(cleanPath, ok)
62+
}
63+
64+
cleanPath, ok = getCleanDirFilePath("dir1/../../dir2/file6")
65+
if ok {
66+
t.Error(cleanPath, ok)
67+
}
68+
69+
cleanPath, ok = getCleanDirFilePath("../file5")
70+
if ok {
71+
t.Error(cleanPath, ok)
72+
}
73+
}

0 commit comments

Comments
 (0)