Recently I was approached by one of my customers who wanted a storage service in AWS and wanted to use their existing corporate Entra ID credentials for authentication.
Looking at the possible options to achieve this and available guidance from AWS, the option with the custom Lambda IDP seemed to be a quick and easy way forward.
(Please note it is now possible to use Entra ID Domain Services for such use case but requires more effort to setup and doesn't illustrate the purpose of this article.)
Solution at a Glance
So how does a Lambda function as a custom IDP work in a high level? As depicted in the diagram below:
- First a user connects to the Transfer Family SFTP server. The server prompts for the user's username and password. The user types in their Entra ID credentials.
- The credentials are then passed to the Lambda function that validates the credentials by contacting the Entra ID public API URL and using the supplied credentials to log in.
- If the login is successful, the Lambda returns an IAM role and a session policy to the SFTP server which enables the user to interact with the SFTP server (e.g. write files).
So far so good, the workflow works as expected, the Lambda function even logs some part of the payload to CloudWatch for monitoring or debugging purposes.
An example output from logs can look as follows:
Opportunity Makes the Thief
From the functional perspective there is nothing wrong with the setup above, the users are happy and can upload data to the SFTP server and enjoy the benefits of the highly durable S3 storage in the background.
However let's assume that the AWS account where the SFTP server is running is used by multiple users and the Security team didn't spend too much time with IAM management, let alone enforce the principle of least privilege. So such a user with over-permissive privileges might go unnoticed for quite some time.
Let's say this user is a developer or a DevOps engineer so he/she has some pretty common permissions, e.g.:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DevAccess",
"Effect": "Allow",
"Action": [
"lambda:*",
"dynamodb:*",
"sqs:*",
"sns:*"
],
"Resource": "*"
}
]
}
And furthermore, the user has the ReadOnlyAccess AWS managed job policy attached:
arn:aws:iam::aws:policy/ReadOnlyAccess
What this combination of access the user can browse through the source code of the IDP Lambda function and not only that. The user can also inject malicious code into the Lambda function and thus exfiltrate sensitive data into CloudWatch. It can go from this:
To this:
Upon looking into the corresponding CloudWatch log group, indeed the adversary (or just an overprivileged user) can indeed read passwords in plain text!
Mitigation
So, how to fix this? As stated in the beginning there are now better ways how to integrate the SFTP server with e.g. Entra ID or Entra ID Domain Services.
However, if you end up in a situation where you need to use an IDP Lambda function such as above, following the below best practices should considerably improve the security posture of your environment.
1. Employ a multi-account strategy
Isolate your workloads by deploying them into multiple AWS accounts. A rule of thumb is one account per application/workload per SDLC stage plus other AWS accounts for specific use cases. This limits the blast radius and makes sure the AWS accounts can't "talk" to each other unless you explicitly allow them to do so on either IAM (cross-account IAM roles) or networking (VPC Peering, Transit Gateway) layer. A good way to start with this approach is using AWS Control Tower which sets up the whole landing zone for you and allows you to enforce various controls and guardrails across AWS accounts.
2. Establish a proper IAM management
Ideally manage the identities at one place (e.g. corporate Entra ID / Active Directory) and federate with AWS Identity Center. This allows users to use their corporate credentials to access AWS, you don't need to duplicate your organisational structure in the cloud and allows you to make use of concepts such as ABAC and RBAC.
The above approach provides an additional benefit where you get rid of any static long-lived credentials or forgotten over-privileges IAM users.
3. Enforce least privilege
Use services such as AWS IAM Access Analyzer to help you fine tune the permissions of your IAM entities based on their historical usage patterns. Or find excessive permissions which were not used in a given time frame.
4. Encrypt, encrypt, encrypt
The password exfiltration scenario above wouldn't be successful if the CloudWatch log group was encrypted by a KMS key with a proper KMS policy. This is a quick win and a recommended approach for any use case.