Browse Source

pkg/tool/path: use IsMaliciousPath to replace SanitizePath

Yoginth 7 years ago
parent
commit
ee86f1e6b6
3 changed files with 24 additions and 17 deletions
  1. 5 1
      models/repo_editor.go
  2. 5 6
      pkg/tool/path.go
  3. 14 10
      pkg/tool/path_test.go

+ 5 - 1
models/repo_editor.go

@@ -313,9 +313,13 @@ func (upload *Upload) LocalPath() string {
 
 
 // NewUpload creates a new upload object.
 // NewUpload creates a new upload object.
 func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err error) {
 func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err error) {
+	if tool.IsMaliciousPath(name) {
+		return nil, fmt.Errorf("malicious path detected: %s", name)
+	}
+
 	upload := &Upload{
 	upload := &Upload{
 		UUID: gouuid.NewV4().String(),
 		UUID: gouuid.NewV4().String(),
-		Name: tool.SanitizePath(name),
+		Name: name,
 	}
 	}
 
 
 	localPath := upload.LocalPath()
 	localPath := upload.LocalPath()

+ 5 - 6
pkg/tool/path.go

@@ -7,6 +7,7 @@
 package tool
 package tool
 
 
 import (
 import (
+	"path/filepath"
 	"strings"
 	"strings"
 )
 )
 
 
@@ -18,10 +19,8 @@ func IsSameSiteURLPath(url string) bool {
 	return len(url) >= 2 && url[0] == '/' && url[1] != '/' && url[1] != '\\'
 	return len(url) >= 2 && url[0] == '/' && url[1] != '/' && url[1] != '\\'
 }
 }
 
 
-// SanitizePath sanitizes user-defined file paths to prevent remote code execution.
-func SanitizePath(path string) string {
-	path = strings.TrimLeft(path, "/")
-	path = strings.Replace(path, "../", "", -1)
-	path = strings.Replace(path, "..\\", "", -1)
-	return path
+// IsMaliciousPath returns true if given path is an absolute path or contains malicious content
+// which has potential to traverse upper level directories.
+func IsMaliciousPath(path string) bool {
+	return filepath.IsAbs(path) || strings.Contains(path, "..")
 }
 }

+ 14 - 10
pkg/tool/path_test.go

@@ -22,30 +22,34 @@ func Test_IsSameSiteURLPath(t *testing.T) {
 			{"http://github.com", false},
 			{"http://github.com", false},
 			{"https://github.com", false},
 			{"https://github.com", false},
 			{"/\\github.com", false},
 			{"/\\github.com", false},
+
 			{"/admin", true},
 			{"/admin", true},
 			{"/user/repo", true},
 			{"/user/repo", true},
 		}
 		}
+
 		for _, tc := range testCases {
 		for _, tc := range testCases {
 			So(IsSameSiteURLPath(tc.url), ShouldEqual, tc.expect)
 			So(IsSameSiteURLPath(tc.url), ShouldEqual, tc.expect)
 		}
 		}
 	})
 	})
 }
 }
 
 
-func Test_SanitizePath(t *testing.T) {
-	Convey("Sanitize malicious user-defined path", t, func() {
+func Test_IsMaliciousPath(t *testing.T) {
+	Convey("Detects malicious path", t, func() {
 		testCases := []struct {
 		testCases := []struct {
 			path   string
 			path   string
-			expect string
+			expect bool
 		}{
 		}{
-			{"../../../../../../../../../data/gitote/data/sessions/a/9/a9f0ab6c3ef63dd8", "data/gitote/data/sessions/a/9/a9f0ab6c3ef63dd8"},
-			{"data/gitote/../../../../../../../../../data/sessions/a/9/a9f0ab6c3ef63dd8", "data/gitote/data/sessions/a/9/a9f0ab6c3ef63dd8"},
-			{"..\\..\\..\\..\\..\\..\\..\\..\\..\\data\\gitote\\data\\sessions\\a\\9\\a9f0ab6c3ef63dd8", "data\\gitote\\data\\sessions\\a\\9\\a9f0ab6c3ef63dd8"},
-			{"data\\gitote\\..\\..\\..\\..\\..\\..\\..\\..\\..\\data\\sessions\\a\\9\\a9f0ab6c3ef63dd8", "data\\gitote\\data\\sessions\\a\\9\\a9f0ab6c3ef63dd8"},
-			{"data/sessions/a/9/a9f0ab6c3ef63dd8", "data/sessions/a/9/a9f0ab6c3ef63dd8"},
-			{"data\\sessions\\a\\9\\a9f0ab6c3ef63dd8", "data\\sessions\\a\\9\\a9f0ab6c3ef63dd8"},
+			{"../../../../../../../../../data/gitote/data/sessions/a/9/a9f0ab6c3ef63dd8", true},
+			{"..\\/..\\/../data/gitote/data/sessions/a/9/a9f0ab6c3ef63dd8", true},
+			{"data/gitote/../../../../../../../../../data/sessions/a/9/a9f0ab6c3ef63dd8", true},
+			{"..\\..\\..\\..\\..\\..\\..\\..\\..\\data\\gitote\\data\\sessions\\a\\9\\a9f0ab6c3ef63dd8", true},
+			{"data\\gitote\\..\\..\\..\\..\\..\\..\\..\\..\\..\\data\\sessions\\a\\9\\a9f0ab6c3ef63dd8", true},
+
+			{"data/sessions/a/9/a9f0ab6c3ef63dd8", false},
+			{"data\\sessions\\a\\9\\a9f0ab6c3ef63dd8", false},
 		}
 		}
 		for _, tc := range testCases {
 		for _, tc := range testCases {
-			So(SanitizePath(tc.path), ShouldEqual, tc.expect)
+			So(IsMaliciousPath(tc.path), ShouldEqual, tc.expect)
 		}
 		}
 	})
 	})
 }
 }