From 925fb7e2c9fa4b4c14a012d72a26ca149d6d6f86 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis <contact@jmattheis.de> Date: Wed, 28 Dec 2022 20:13:35 +0100 Subject: [PATCH] Fix file upload XSS The application image file upload allowed authenticated users to upload malious .html files. Opening such a file like https://push.gotify.net/image/ViaxrjzNowdgL-xnEfVV-Ggv5.html would allow the attacker to execute client side scripts. The application image upload will now only allow the upload of files with the following extensions: .gif, .png, .jpg and .jpeg. --- api/application.go | 8 ++++++++ api/application_test.go | 16 ++++++++++++++++ test/assets/image-header-with.html | Bin 0 -> 154 bytes 3 files changed, 24 insertions(+) create mode 100644 test/assets/image-header-with.html diff --git a/api/application.go b/api/application.go index ff64075f0..736330ee5 100644 --- a/api/application.go +++ b/api/application.go @@ -329,6 +329,14 @@ func (a *ApplicationAPI) UploadApplicationImage(ctx *gin.Context) { ext := filepath.Ext(file.Filename) + switch ext { + case ".gif", ".png", ".jpg", ".jpeg": + // ok + default: + ctx.AbortWithError(400, errors.New("invalid file extension")) + return + } + name := generateNonExistingImageName(a.ImageDir, func() string { return generateImageName() + ext }) diff --git a/api/application_test.go b/api/application_test.go index c7fe43d52..22777eb08 100644 --- a/api/application_test.go +++ b/api/application_test.go @@ -398,6 +398,22 @@ func (s *ApplicationSuite) Test_UploadAppImage_WithTextFile_expectBadRequest() { assert.Equal(s.T(), s.ctx.Errors[0].Err, errors.New("file must be an image")) } +func (s *ApplicationSuite) Test_UploadAppImage_WithHtmlFileHavingImageHeader() { + s.db.User(5).App(1) + + cType, buffer, err := upload(map[string]*os.File{"file": mustOpen("../test/assets/image-header-with.html")}) + assert.Nil(s.T(), err) + s.ctx.Request = httptest.NewRequest("POST", "/irrelevant", &buffer) + s.ctx.Request.Header.Set("Content-Type", cType) + test.WithUser(s.ctx, 5) + s.ctx.Params = gin.Params{{Key: "id", Value: "1"}} + + s.a.UploadApplicationImage(s.ctx) + + assert.Equal(s.T(), 400, s.recorder.Code) + assert.Equal(s.T(), s.ctx.Errors[0].Err, errors.New("invalid file extension")) +} + func (s *ApplicationSuite) Test_UploadAppImage_expectNotFound() { s.db.User(5) diff --git a/test/assets/image-header-with.html b/test/assets/image-header-with.html new file mode 100644 index 0000000000000000000000000000000000000000..4d05a95869f0f75b1ec9fe5384edff9529b8f626 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp@K+MO%1|+}KPrC%97>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`03d%8G=Xapz!`1kmFebC1hY8rA^S&lYGU0(m6q50Br{{2Ubj{uc1c)I$z ttaD0evMEk3$}A|cOUy|vD$!8#NX^N~*HH-1FUm<#RMNDz(TB=&0RRasFtz{y literal 0 HcmV?d00001