CVE-2022-29527: Incorrect Permission Assignment for Critical Resource (CWE-732)
value: Amazon AWS amazon-ssm-agent before 3.1.1208.0 creates a world-writable sudoers file, which allows local attackers to inject Sudo rules and escalate privileges to root. This occurs in certain situations involving a race condition.
CWE description: The product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors.
CVSS v3 base score: 7
Published: 2022-04-20T10:15Z
Repository: https://github.com/aws/amazon-ssm-agent
Language: Go
Files changed: agent/session/utility/utility_unix.go
Commit date: 2022-04-05 19:09:56 +0000
Commit message: Create ssm-agent-users sudoer file with constrained file permission

cr: https://code.amazon.com/reviews/CR-67315538

Diff: diff --git a/agent/session/utility/utility_unix.go b/agent/session/utility/utility_unix.go
index 1a480780..a50ac5a3 100644
--- a/agent/session/utility/utility_unix.go
+++ b/agent/session/utility/utility_unix.go
@@ -35,16 +35,17 @@ import (
 
 var ShellPluginCommandName = "sh"
 var ShellPluginCommandArgs = []string{"-c"}
 
 const (
-	sudoersFile     = "/etc/sudoers.d/ssm-agent-users"
-	sudoersFileMode = 0440
-	fs_ioc_getflags = uintptr(0x80086601)
-	fs_ioc_setflags = uintptr(0x40086602)
-	FS_APPEND_FL    = 0x00000020 /* writes to file may only append */
-	FS_RESET_FL     = 0x00000000 /* reset file property */
+	sudoersFile                = "/etc/sudoers.d/ssm-agent-users"
+	sudoersFileCreateWriteMode = 0640
+	sudoersFileReadOnlyMode    = 0440
+	fs_ioc_getflags            = uintptr(0x80086601)
+	fs_ioc_setflags            = uintptr(0x40086602)
+	FS_APPEND_FL               = 0x00000020 /* writes to file may only append */
+	FS_RESET_FL                = 0x00000000 /* reset file property */
 )
 
 // ResetPasswordIfDefaultUserExists resets default RunAs user password if user exists
 func (u *SessionUtil) ResetPasswordIfDefaultUserExists(context context.T) (err error) {
 	// Do nothing here as no password is required for unix platform local user
@@ -104,12 +105,12 @@ func (u *SessionUtil) createSudoersFileIfNotPresent(log log.T) error {
 		log.Infof("File %s already exists", sudoersFile)
 		_ = u.changeModeOfSudoersFile(log)
 		return err
 	}
 
-	// Create a sudoers file for ssm-user
-	file, err := os.Create(sudoersFile)
+	// Create a sudoers file for ssm-user with read/write access
+	file, err := os.OpenFile(sudoersFile, os.O_WRONLY|os.O_CREATE, sudoersFileCreateWriteMode)
 	if err != nil {
 		log.Errorf("Failed to add %s to sudoers file: %v", appconfig.DefaultRunAsUserName, err)
 		return err
 	}
 	defer func() {
@@ -130,16 +131,16 @@ func (u *SessionUtil) createSudoersFileIfNotPresent(log log.T) error {
 }
 
 // changeModeOfSudoersFile will change the sudoersFile mode to 0440 (read only).
 // This file is created with mode 0666 using os.Create() so needs to be updated to read only with chmod.
 func (u *SessionUtil) changeModeOfSudoersFile(log log.T) error {
-	fileMode := os.FileMode(sudoersFileMode)
+	fileMode := os.FileMode(sudoersFileReadOnlyMode)
 	if err := os.Chmod(sudoersFile, fileMode); err != nil {
-		log.Errorf("Failed to change mode of %s to %d: %v", sudoersFile, sudoersFileMode, err)
+		log.Errorf("Failed to change mode of %s to %d: %v", sudoersFile, sudoersFileReadOnlyMode, err)
 		return err
 	}
-	log.Infof("Successfully changed mode of %s to %d", sudoersFile, sudoersFileMode)
+	log.Infof("Successfully changed mode of %s to %d", sudoersFile, sudoersFileReadOnlyMode)
 	return nil
 }
 
 func (u *SessionUtil) DisableLocalUser(log log.T) (err error) {
 	// Do nothing here as no password is required for unix platform local user, so that no need to disable user.

Vulnerable code: 	sudoersFile     = "/etc/sudoers.d/ssm-agent-users"
	sudoersFileMode = 0440
	fs_ioc_getflags = uintptr(0x80086601)
	fs_ioc_setflags = uintptr(0x40086602)
	FS_APPEND_FL    = 0x00000020 /* writes to file may only append */
	FS_RESET_FL     = 0x00000000 /* reset file property */
	// Create a sudoers file for ssm-user
	file, err := os.Create(sudoersFile)
	fileMode := os.FileMode(sudoersFileMode)
		log.Errorf("Failed to change mode of %s to %d: %v", sudoersFile, sudoersFileMode, err)
	log.Infof("Successfully changed mode of %s to %d", sudoersFile, sudoersFileMode)
Fixed code: 	sudoersFile                = "/etc/sudoers.d/ssm-agent-users"
	sudoersFileCreateWriteMode = 0640
	sudoersFileReadOnlyMode    = 0440
	fs_ioc_getflags            = uintptr(0x80086601)
	fs_ioc_setflags            = uintptr(0x40086602)
	FS_APPEND_FL               = 0x00000020 /* writes to file may only append */
	FS_RESET_FL                = 0x00000000 /* reset file property */
	// Create a sudoers file for ssm-user with read/write access
	file, err := os.OpenFile(sudoersFile, os.O_WRONLY|os.O_CREATE, sudoersFileCreateWriteMode)
	fileMode := os.FileMode(sudoersFileReadOnlyMode)
		log.Errorf("Failed to change mode of %s to %d: %v", sudoersFile, sudoersFileReadOnlyMode, err)
	log.Infof("Successfully changed mode of %s to %d", sudoersFile, sudoersFileReadOnlyMode)