Minio Privilege Escalation on Windows via Path separator manipulation
Description
Minio is a Multi-Cloud Object Storage framework. All users on Windows prior to version RELEASE.2023-03-20T20-16-18Z are impacted. MinIO fails to filter the \ character, which allows for arbitrary object placement across buckets. As a result, a user with low privileges, such as an access key, service account, or STS credential, which only has permission to PutObject in a specific bucket, can create an admin user. This issue is patched in RELEASE.2023-03-20T20-16-18Z. There are no known workarounds.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/minio/minioGo | < 0.0.0-202303200735 | 0.0.0-202303200735 |
Affected products
1Patches
2b3c54ec81e0areject object names with '\' on windows (#16856)
3 files changed · +72 −6
cmd/object-api-multipart_test.go+14 −1 modified@@ -22,6 +22,7 @@ import ( "context" "fmt" "reflect" + "runtime" "strings" "testing" @@ -32,6 +33,9 @@ import ( // Wrapper for calling NewMultipartUpload tests for both Erasure multiple disks and single node setup. func TestObjectNewMultipartUpload(t *testing.T) { + if runtime.GOOS == globalWindowsOSName { + t.Skip() + } ExecObjectLayerTest(t, testObjectNewMultipartUpload) } @@ -110,9 +114,18 @@ func testObjectAbortMultipartUpload(obj ObjectLayer, instanceType string, t Test {"--", object, uploadID, BucketNotFound{}}, {"foo", object, uploadID, BucketNotFound{}}, {bucket, object, "foo-foo", InvalidUploadID{}}, - {bucket, "\\", uploadID, InvalidUploadID{}}, {bucket, object, uploadID, nil}, } + + if runtime.GOOS != globalWindowsOSName { + abortTestCases = append(abortTestCases, struct { + bucketName string + objName string + uploadID string + expectedErrType error + }{bucket, "\\", uploadID, InvalidUploadID{}}) + } + // Iterating over creatPartCases to generate multipart chunks. for i, testCase := range abortTestCases { err = obj.AbortMultipartUpload(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, opts)
cmd/object-api-utils.go+2 −5 modified@@ -174,10 +174,7 @@ func IsValidObjectPrefix(object string) bool { // work with file systems, we will reject here // to return object name invalid rather than // a cryptic error from the file system. - if strings.ContainsRune(object, 0) { - return false - } - return true + return !strings.ContainsRune(object, 0) } // checkObjectNameForLengthAndSlash -check for the validity of object name length and prefis as slash @@ -199,7 +196,7 @@ func checkObjectNameForLengthAndSlash(bucket, object string) error { if runtime.GOOS == globalWindowsOSName { // Explicitly disallowed characters on windows. // Avoids most problematic names. - if strings.ContainsAny(object, `:*?"|<>`) { + if strings.ContainsAny(object, `\:*?"|<>`) { return ObjectNameInvalid{ Bucket: bucket, Object: object,
cmd/object-api-utils_test.go+56 −0 modified@@ -19,19 +19,75 @@ package cmd import ( "bytes" + "context" "fmt" "io" "net/http" + "net/http/httptest" "reflect" + "runtime" "strconv" "testing" "github.com/klauspost/compress/s2" + "github.com/minio/minio/internal/auth" "github.com/minio/minio/internal/config/compress" "github.com/minio/minio/internal/crypto" "github.com/minio/pkg/trie" ) +// Wrapper +func TestPathTraversalExploit(t *testing.T) { + if runtime.GOOS != globalWindowsOSName { + t.Skip() + } + defer DetectTestLeak(t)() + ExecExtendedObjectLayerAPITest(t, testPathTraversalExploit, []string{"PutObject"}) +} + +// testPathTraversal exploit test, exploits path traversal on windows +// with following object names "\\../.minio.sys/config/iam/${username}/identity.json" +// #16852 +func testPathTraversalExploit(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, + credentials auth.Credentials, t *testing.T, +) { + if err := newTestConfig(globalMinioDefaultRegion, obj); err != nil { + t.Fatalf("Initializing config.json failed") + } + + objectName := `\../.minio.sys/config/hello.txt` + + // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. + rec := httptest.NewRecorder() + // construct HTTP request for Get Object end point. + req, err := newTestSignedRequestV4(http.MethodPut, getPutObjectURL("", bucketName, objectName), + int64(5), bytes.NewReader([]byte("hello")), credentials.AccessKey, credentials.SecretKey, map[string]string{}) + if err != nil { + t.Fatalf("failed to create HTTP request for Put Object: <ERROR> %v", err) + } + + // Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic ofthe handler. + // Call the ServeHTTP to execute the handler. + apiRouter.ServeHTTP(rec, req) + + ctx, cancel := context.WithCancel(GlobalContext) + defer cancel() + + // Now check if we actually wrote to backend (regardless of the response + // returned by the server). + z := obj.(*erasureServerPools) + xl := z.serverPools[0].sets[0] + erasureDisks := xl.getDisks() + parts, errs := readAllFileInfo(ctx, erasureDisks, bucketName, objectName, "", false) + for i := range parts { + if errs[i] == nil { + if parts[i].Name == objectName { + t.Errorf("path traversal allowed to allow writing to minioMetaBucket: %s", instanceType) + } + } + } +} + // Tests validate bucket name. func TestIsValidBucketName(t *testing.T) { testCases := []struct {
8d6558b23649fix: convert '\' to '/' on windows (#16852)
1 file changed · +2 −1
cmd/generic-handlers.go+2 −1 modified@@ -22,6 +22,7 @@ import ( "net" "net/http" "path" + "path/filepath" "runtime/debug" "strings" "sync/atomic" @@ -349,7 +350,7 @@ func hasBadHost(host string) error { // Check if the incoming path has bad path components, // such as ".." and "." func hasBadPathComponent(path string) bool { - path = strings.TrimSpace(path) + path = filepath.ToSlash(strings.TrimSpace(path)) // For windows '\' must be converted to '/' for _, p := range strings.Split(path, SlashSeparator) { switch strings.TrimSpace(p) { case dotdotComponent:
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-w23q-4hw3-2pp6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-28433ghsaADVISORY
- github.com/minio/minio/commit/8d6558b23649f613414c8527b58973fbdfa4d1b8ghsax_refsource_MISCWEB
- github.com/minio/minio/commit/b3c54ec81e0a06392abfb3a1ffcdc80c6fbf6ebcghsax_refsource_MISCWEB
- github.com/minio/minio/releases/tag/RELEASE.2023-03-20T20-16-18Zghsax_refsource_MISCWEB
- github.com/minio/minio/security/advisories/GHSA-w23q-4hw3-2pp6ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.