Valid if bucket names are internal (#7476)

This commit fixes a privilege escalation issue against
the S3 and web handlers. An authenticated IAM user
can:

- Read from or write to the internal '.minio.sys'
bucket by simply sending a properly signed
S3 GET or PUT request. Further, the user can
- Read from or write to the internal '.minio.sys'
bucket using the 'Upload'/'Download'/'DownloadZIP'
API by sending a "browser" request authenticated
with its JWT token.
This commit is contained in:
Harshavardhana
2019-04-03 23:10:37 -07:00
committed by kannappanr
parent 9a740736a4
commit c90999df98
8 changed files with 92 additions and 34 deletions

View File

@@ -209,6 +209,11 @@ func (web *webAPIHandlers) DeleteBucket(r *http.Request, args *RemoveBucketArgs,
return toJSONError(errAccessDenied)
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
reply.UIVersion = browser.UIVersion
if isRemoteCallRequired(context.Background(), args.BucketName, objectAPI) {
@@ -500,6 +505,11 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r
}
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
lo, err := listObjects(context.Background(), args.BucketName, args.Prefix, args.Marker, slashSeparator, 1000)
if err != nil {
return &json2.Error{Message: err.Error()}
@@ -566,6 +576,11 @@ func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs,
return toJSONError(errInvalidArgument)
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
reply.UIVersion = browser.UIVersion
if isRemoteCallRequired(context.Background(), args.BucketName, objectAPI) {
sr, err := globalDNSConfig.Get(args.BucketName)
@@ -876,6 +891,13 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
return
}
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(bucket, false) {
writeWebErrorResponse(w, errInvalidBucketName)
return
}
if globalAutoEncryption && !crypto.SSEC.IsRequested(r.Header) {
r.Header.Add(crypto.SSEHeader, crypto.SSEAlgorithmAES256)
}
@@ -1046,6 +1068,12 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
}
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(bucket, false) {
writeWebErrorResponse(w, errInvalidBucketName)
return
}
getObjectNInfo := objectAPI.GetObjectNInfo
if web.CacheAPI() != nil {
getObjectNInfo = web.CacheAPI().GetObjectNInfo
@@ -1193,6 +1221,12 @@ func (web *webAPIHandlers) DownloadZip(w http.ResponseWriter, r *http.Request) {
}
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
writeWebErrorResponse(w, errInvalidBucketName)
return
}
getObject := objectAPI.GetObject
if web.CacheAPI() != nil {
getObject = web.CacheAPI().GetObject
@@ -1379,6 +1413,11 @@ func (web *webAPIHandlers) GetBucketPolicy(r *http.Request, args *GetBucketPolic
return toJSONError(errAccessDenied)
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
var policyInfo = &miniogopolicy.BucketAccessPolicy{Version: "2012-10-17"}
if isRemoteCallRequired(context.Background(), args.BucketName, objectAPI) {
sr, err := globalDNSConfig.Get(args.BucketName)
@@ -1462,6 +1501,11 @@ func (web *webAPIHandlers) ListAllBucketPolicies(r *http.Request, args *ListAllB
return toJSONError(errAccessDenied)
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
var policyInfo = new(miniogopolicy.BucketAccessPolicy)
if isRemoteCallRequired(context.Background(), args.BucketName, objectAPI) {
sr, err := globalDNSConfig.Get(args.BucketName)
@@ -1538,6 +1582,11 @@ func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolic
return toJSONError(errAccessDenied)
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
policyType := miniogopolicy.BucketPolicy(args.Policy)
if !policyType.IsValidBucketPolicy() {
return &json2.Error{
@@ -1685,6 +1734,11 @@ func (web *webAPIHandlers) PresignedGet(r *http.Request, args *PresignedGetArgs,
}
}
// Check if bucket is a reserved bucket name or invalid.
if isReservedOrInvalidBucket(args.BucketName, false) {
return toJSONError(errInvalidBucketName)
}
reply.UIVersion = browser.UIVersion
reply.URL = presignedGet(args.HostName, args.BucketName, args.ObjectName, args.Expiry, creds, region)
return nil