mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-17 18:27:49 +00:00
fix(security): add IAM authorization to FTP read/metadata/cwd handlers (GHSA-3g29-xff2-92vp) (#3347)
fix(security): add IAM authorization to FTP read/metadata/cwd handlers The FTP frontend's get() (RETR), metadata() (SIZE/MDTM), and cwd() (CWD) handlers dispatched directly to the storage backend without calling authorize_operation(). This allowed any authenticated FTP user, including those with explicit Deny policies, to read arbitrary objects and probe bucket existence regardless of IAM policy. Add authorize_operation() calls matching the pattern used by the write-path handlers (put, del, list, rmd) and the WebDAV driver: - get(): S3Action::GetObject - metadata() for files: S3Action::HeadObject - metadata() for directories: S3Action::HeadBucket - cwd(): S3Action::HeadBucket Fixes: GHSA-3g29-xff2-92vp Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -233,6 +233,11 @@ where
|
||||
.map_err(|e| Error::new(ErrorKind::PermanentFileNotAvailable, format!("{}: {}", "Invalid path", e)))?;
|
||||
|
||||
if let Some(key) = key {
|
||||
// Authorize HeadObject
|
||||
authorize_operation(session_context, &S3Action::HeadObject, &bucket, Some(&key))
|
||||
.await
|
||||
.map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?;
|
||||
|
||||
match self
|
||||
.storage
|
||||
.head_object(
|
||||
@@ -264,6 +269,11 @@ where
|
||||
}
|
||||
} else {
|
||||
// Directory metadata - use HeadBucket
|
||||
// Authorize HeadBucket
|
||||
authorize_operation(session_context, &S3Action::HeadBucket, &bucket, None)
|
||||
.await
|
||||
.map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?;
|
||||
|
||||
let bucket_clone = bucket.clone();
|
||||
match self
|
||||
.storage
|
||||
@@ -434,6 +444,11 @@ where
|
||||
|
||||
let key = key.ok_or_else(|| Error::new(ErrorKind::PermanentFileNotAvailable, "Cannot get directory"))?;
|
||||
|
||||
// Authorize GetObject
|
||||
authorize_operation(session_context, &S3Action::GetObject, &bucket, Some(&key))
|
||||
.await
|
||||
.map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?;
|
||||
|
||||
match self
|
||||
.storage
|
||||
.get_object(
|
||||
@@ -668,6 +683,11 @@ where
|
||||
.parse_s3_path(&path_str)
|
||||
.map_err(|e| Error::new(ErrorKind::PermanentFileNotAvailable, format!("{}: {}", "Invalid path", e)))?;
|
||||
|
||||
// Authorize HeadBucket (CWD probes bucket existence)
|
||||
authorize_operation(session_context, &S3Action::HeadBucket, &bucket, None)
|
||||
.await
|
||||
.map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?;
|
||||
|
||||
// Check if bucket exists
|
||||
match self
|
||||
.storage
|
||||
|
||||
Reference in New Issue
Block a user