AWS Enhancements to UpdateLoginProfile and CreateLoginProfile logging
Hear Ye, Hear Ye
Subscribe to Cloud Chronicles for the latest in cloud security!
Introduction
While working on detection content for our clients, we often come across situations where logging from cloud providers and identity providers does not contain the level of detail needed. In this case we were working on detections to identify when a login profile is created or updated without the reset password flag set to true. This flag identifies if the user is required to reset their password on the next authentication.
Permiso has long included this detection for CreateLoginProfile
and intended to expand coverage to UpdateLoginProfile
as well. Unfortunately we found that while CreateLoginProfile
and UpdateLoginProfile
share request parameters, they do not share the same parameters within logs.
UpdateLoginProfile
did not include any reference to the password reset flag within logs, making it impossible to signal on the password reset flag.
Additionally, we found that logs for CreateLoginProfile
always show as false
for the PasswordResetRequired
request parameter, even if you set it to True
in the the API call.
Testing and verifying logging is an important part of threat detection. At Permiso, we come across logging discrepancies like this often. Luckily, AWS is known for having a great outreach team that is willing to work with researchers like us!
Disclosure Timeline
We cannot understate how responsive the AWS team was in acknowledging the finding and making changes to enhance logging. There are other similar vendors we have worked with, that do not even respond in the same amount of time it took AWS to push a fix.
Technical Details
The table below presents the request parameters of both CreateLoginProfile
and UpdateLoginProfile
. It can be seen that the only difference is the password field which varies when each is required or not. For both, the PasswordResetRequired
parameter is not required and by default would be false
if otherwise not provided.
AWS Actions:
Action |
Request Parameters |
---|---|
CreateLoginProfile |
Password (required) |
UpdateLoginProfile |
Password (optional) |
UpdateLoginProfile
Before AWS began to rollout the disclosed updates, UpdateLoginProfile
would have provided little outside of a sense that an update occurred to the login profile of the disclosed user. A password reset may be required on the next authentication, or maybe the password was reset, and last, both request parameters may have been used but the log would not have provided any variation on these details. With the changes to logging implemented by AWS beginning October 17th, the event log for this same action captures more detail in the request parameter.
{
"requestParameters": {
"userName": "NathanTest",
+ "passwordResetRequired": true
},
"responseElements": null,
...
}
CreateLoginProfile
CreateLoginProfile
in contrast to UpdateLoginProfile
, does provide greater detail. CreateLoginProfile
by its required parameters and by its nature would mean that a password has been set for the given username. The CreateLoginProfile
action also provides logging details around the PasswordResetRequired
parameter. Permiso discovered however that the passwordResetRequired
log line is included in both the requestParameters
and responseElements
JSON objects. There is no issue with redundancy, the issue discovered was that the requestParameters
object always stated that the passwordResetRequired
parameter was false
while the responseElements
may accurately represent that the parameter was true. Permiso has provided a log for both cases to show the static incorrect requestParameters
object.
{
"requestParameters": {
"userName": "CreateLoginProfileTestUserB",
"passwordResetRequired": false // NOTE the mismatch below in the response
},
"responseElements": {
"loginProfile": {
"userName": "CreateLoginProfileTestUserB",
"createDate": "Sep 20, 2022 3:26:25 PM",
"passwordResetRequired": true
}
},
}
With the changes to logging implemented by AWS beginning October 17th, the event log for this same action instead looks similar to the following where passwordResetRequired
will match in both the request and response:
{
"requestParameters": {
"userName": "CreateLoginProfileTestUserD",
"passwordResetRequired": true
},
"responseElements": {
"loginProfile": {
"userName": "CreateLoginProfileTestUserD",
"createDate": "Oct 21, 2022 1:51:12 PM",
"passwordResetRequired": true
}
},
}
Acknowledgements
Big thanks to the AWS Security Outreach Team, and IAM team! They were super responsive, and quick to address our findings. It is clear that AWS is serious about security and willing to work with researchers to address concerns as they come up!
Appendix
Before: UpdateLoginProfile
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "ARABC5IQVABC5JABC5GQI:nathan.eades@permiso.io",
"arn": "arn:aws:sts::353353353353:assumed-role/AWSReservedSSO_AdministratorAccess_c3ABC55ABC53ccef/nathan.eades@permiso.io",
"accountId": "353353353353",
"accessKeyId": "ASABC4IQVCIYZZABC44H",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "ARABC5IQVABC5JABC5GQI",
"arn": "arn:aws:iam::353353353353:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccesABC5ABC55ABC53ccef",
"accountId": "353353353353",
"userName": "AWSReservedSSO_AdministratorAccesABC5ABC55ABC53ccef"
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2022-09-20T14:55:59Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2022-09-20T15:01:24Z",
"eventSource": "iam.amazonaws.com",
"eventName": "UpdateLoginProfile",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "AWS Internal",
"requestParameters": {
"userName": "NathanTest"
},
"responseElements": null,
"requestID": "353a8cef-f1dc-353f-b2ca-bbbfb1d2b5fd",
"eventID": "92b6e4e7-e2b9-3535-bd34-f2c94a79f1d7",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "353353353353",
"eventCategory": "Management",
"sessionCredentialFromConsole": "true"
}
After: UpdateLoginProfile
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "ARABC5IQVABC5JABC5GQI:nathan.eades@permiso.io",
"arn": "arn:aws:sts::353353353353:assumed-role/AWSReservedSSO_AdministratorAccess_c3ABC55ABC53ccef/nathan.eades@permiso.io",
"accountId": "353353353353",
"accessKeyId": "ASABC4IQVCIYZZABC44H",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "ARABC5IQVABC5JABC5GQI",
"arn": "arn:aws:iam::353353353353:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccesABC5ABC55ABC53ccef",
"accountId": "353353353353",
"userName": "AWSReservedSSO_AdministratorAccesABC5ABC55ABC53ccef"
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2022-10-21T13:43:44Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2022-10-21T14:47:59Z",
"eventSource": "iam.amazonaws.com",
"eventName": "UpdateLoginProfile",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "AWS Internal",
"requestParameters": {
"userName": "NathanTest",
"passwordResetRequired": true
},
"responseElements": null,
"requestID": "e807c0b8-8fe6-4cbe-8f5e-572f7e3b930f",
"eventID": "96f714dc-8a71-4078-89ff-bd3aaf341104",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "353353353353",
"eventCategory": "Management",
"sessionCredentialFromConsole": "true"
}
Before: CreateLoginProfile
- password reset not required
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "ARABC5IQVABC5JABC5GQI:nathan.eades@permiso.io",
"arn": "arn:aws:sts::353353353353:assumed-role/AWSReservedSSO_AdministratorAccess_c353e353cc93ccef/nathan.eades@permiso.io",
"accountId": "353353353353",
"accessKeyId": "ASABC4IQVCIYZZABC44H",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "ARABC5IQVABC5JABC5GQI",
"arn": "arn:aws:iam::353353353353:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccess_c353e353cc93ccef",
"accountId": "353353353353",
"userName": "AWSReservedSSO_AdministratorAccess_c353e353cc93ccef"
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2022-09-20T14:55:59Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2022-09-20T15:25:56Z",
"eventSource": "iam.amazonaws.com",
"eventName": "CreateLoginProfile",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "AWS Internal",
"requestParameters": {
"userName": "CreateLoginProfileTestUserA",
"passwordResetRequired": false
},
"responseElements": {
"loginProfile": {
"userName": "CreateLoginProfileTestUserA",
"createDate": "Sep 20, 2022 3:25:56 PM",
"passwordResetRequired": false
}
},
"requestID": "fc3ec353-b60a-4d22-a25b-add7a3533533",
"eventID": "e353353e-05d8-4ec0-3539-35335341fe4b",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "353353353353",
"eventCategory": "Management",
"sessionCredentialFromConsole": "true"
}
Before: CreateLoginProfile
- password reset required
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "ARABC5IQVABC5JABC5GQI:nathan.eades@permiso.io",
"arn": "arn:aws:sts::353353353353:assumed-role/AWSReservedSSO_AdministratorAccess_c353e353cc93ccef/nathan.eades@permiso.io",
"accountId": "353353353353",
"accessKeyId": "ASABC4IQVCIYZZABC44H",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "ARABC5IQVABC5JABC5GQI",
"arn": "arn:aws:iam::353353353353:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccess_c353e353cc93ccef",
"accountId": "353353353353",
"userName": "AWSReservedSSO_AdministratorAccess_c353e353cc93ccef"
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2022-09-20T14:55:59Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2022-09-20T15:26:25Z",
"eventSource": "iam.amazonaws.com",
"eventName": "CreateLoginProfile",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "AWS Internal",
"requestParameters": {
"userName": "CreateLoginProfileTestUserB",
"passwordResetRequired": false
},
"responseElements": {
"loginProfile": {
"userName": "CreateLoginProfileTestUserB",
"createDate": "Sep 20, 2022 3:26:25 PM",
"passwordResetRequired": true
}
},
"requestID": "45e51b66-0a57-4bbe-b651-233fadfc5468",
"eventID": "8504c50f-d84b-4061-b4ca-1bf40d445384",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "353353353353",
"eventCategory": "Management",
"sessionCredentialFromConsole": "true"
}
After: CreateLoginProfile
- password reset required
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "ARABC5IQVABC5JABC5GQI:nathan.eades@permiso.io",
"arn": "arn:aws:sts::353353353353:assumed-role/AWSReservedSSO_AdministratorAccess_c353e353cc93ccef/nathan.eades@permiso.io",
"accountId": "353353353353",
"accessKeyId": "ASABC4IQVCIYZZABC44H",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "ARABC5IQVABC5JABC5GQI",
"arn": "arn:aws:iam::353353353353:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccess_c353e353cc93ccef",
"accountId": "353353353353",
"userName": "AWSReservedSSO_AdministratorAccess_c353e353cc93ccef"
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2022-10-21T13:43:08Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2022-10-21T13:51:12Z",
"eventSource": "iam.amazonaws.com",
"eventName": "CreateLoginProfile",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "AWS Internal",
"requestParameters": {
"userName": "CreateLoginProfileTestUserD",
"passwordResetRequired": true
},
"responseElements": {
"loginProfile": {
"userName": "CreateLoginProfileTestUserD",
"createDate": "Oct 21, 2022 1:51:12 PM",
"passwordResetRequired": true
}
},
"requestID": "f5b7de8f-4725-4d5c-9a7a-b20b97cccd87",
"eventID": "0347a96b-999b-4f1e-85a7-2a38307cf686",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "353353353353",
"eventCategory": "Management",
"sessionCredentialFromConsole": "true"
}