CVE-2021-23772: Improper Link Resolution Before File Access ('Link Following') (CWE-59)
value: This affects all versions of package github.com/kataras/iris; all versions of package github.com/kataras/iris/v12. The unsafe handling of file names during upload using UploadFormFiles method may enable attackers to write to arbitrary locations outside the designated target folder.
CWE description: The product attempts to access a file based on the filename, but it does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource.
CVSS v3 base score: 8.8
Published: 2021-12-24T12:15Z
Repository: https://github.com/kataras/iris
Language: Go
Files changed: HISTORY.md, context/context.go
Commit date: 2021-12-23 22:05:26 +0200
Commit message: security fix

Diff: diff --git a/HISTORY.md b/HISTORY.md
index 32b8d87c..7f49e93e 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -26,10 +26,12 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
 This release introduces new features and some breaking changes.
 The codebase for Dependency Injection, Internationalization and localization and more have been simplified a lot (fewer LOCs and easier to read and follow up).
 
 ## Fixes and Improvements
 
+- Push a security fix reported by [Kirill Efimov](https://github.com/kirill89) for older go runtimes.
+
 - New `Configuration.Timeout` and `Configuration.TimeoutMessage` fields. Use it to set HTTP timeouts. Note that your http server's (`Application.ConfigureHost`) Read/Write timeouts should be a bit higher than the `Configuration.Timeout` in order to give some time to http timeout handler to kick in and be able to send the `Configuration.TimeoutMessage` properly.
 
 - New `apps.OnApplicationRegistered` method which listens on new Iris applications hosted under the same binary. Use it on your `init` functions to configure Iris applications by any spot in your project's files.
 
 - `Context.JSON` respects any object implements the `easyjson.Marshaler` interface and renders the result using the [easyjon](https://github.com/mailru/easyjson)'s writer.
diff --git a/context/context.go b/context/context.go
index 1b4e43c7..28fa9ae8 100644
--- a/context/context.go
+++ b/context/context.go
@@ -2030,17 +2030,11 @@ func (ctx *Context) FormFiles(key string, before ...func(*Context, *multipart.Fi
 			files = make([]multipart.File, 0, n)
 			headers = make([]*multipart.FileHeader, 0, n)
 
 		innerLoop:
 			for _, header := range fhs[key] {
-				// Fix an issue that net/http has,
-				// an attacker can push a filename
-				// which could lead to override existing system files
-				// by ../../$header.
-				// Reported by Frank through security reports.
-				header.Filename = strings.ReplaceAll(header.Filename, "../", "")
-				header.Filename = strings.ReplaceAll(header.Filename, "..\\", "")
+				header.Filename = filepath.Base(header.Filename)
 
 				for _, b := range before {
 					if !b(ctx, header) {
 						continue innerLoop
 					}
@@ -2098,17 +2092,13 @@ func (ctx *Context) UploadFormFiles(destDirectory string, before ...func(*Contex
 	if ctx.request.MultipartForm != nil {
 		if fhs := ctx.request.MultipartForm.File; fhs != nil {
 			for _, files := range fhs {
 			innerLoop:
 				for _, file := range files {
-					// Fix an issue that net/http has,
-					// an attacker can push a filename
-					// which could lead to override existing system files
-					// by ../../$file.
-					// Reported by Frank through security reports.
-					file.Filename = strings.ReplaceAll(file.Filename, "../", "")
-					file.Filename = strings.ReplaceAll(file.Filename, "..\\", "")
+					// Security fix for go < 1.17.5:
+					// Reported by Kirill Efimov (snyk.io) through security reports.
+					file.Filename = filepath.Base(file.Filename)
 
 					for _, b := range before {
 						if !b(ctx, file) {
 							continue innerLoop
 						}

Vulnerable code: 				// Fix an issue that net/http has,
				// an attacker can push a filename
				// which could lead to override existing system files
				// by ../../$header.
				// Reported by Frank through security reports.
				header.Filename = strings.ReplaceAll(header.Filename, "../", "")
				header.Filename = strings.ReplaceAll(header.Filename, "..\\", "")
					// Fix an issue that net/http has,
					// an attacker can push a filename
					// which could lead to override existing system files
					// by ../../$file.
					// Reported by Frank through security reports.
					file.Filename = strings.ReplaceAll(file.Filename, "../", "")
					file.Filename = strings.ReplaceAll(file.Filename, "..\\", "")
Fixed code: - Push a security fix reported by [Kirill Efimov](https://github.com/kirill89) for older go runtimes.

				header.Filename = filepath.Base(header.Filename)
					// Security fix for go < 1.17.5:
					// Reported by Kirill Efimov (snyk.io) through security reports.
					file.Filename = filepath.Base(file.Filename)