Lambda functions, integrated with various AWS components according to the design of serverless applications, can be a medium of various exploit scenarios if vulnerable. As discussed in the previous blog posts, a vulnerability in a lambda function (with or without outbound connections) can be identified through various methods. In this blog post, we will discuss the exploit scenarios which come into play once the vulnerability in the lambda function has been identified. Below are two major exploit area's: -
1. Exploiting Backend – We use different methods (enumeration, tracing, fuzzing etc.) to identify that the lambda function is vulnerable to SQL injection. Once the vulnerability is identified, we inject attacks to exploit the vulnerability and fetch information about the back-end database, its tables etc. In this scenario, we are just leveraging and exploiting the weakness of the lambda function and not touching any other components in the overall infrastructure design.
2. Exploiting AWS Components – We use different methods (enumeration, tracing, fuzzing etc.) to identify the overall architecture and information about the components integrated with serverless functions. Once the vulnerability is identified (for example command injection), we inject payloads to exploit the vulnerability and steal critical information like access keys/tokens/secret etc. Using this information we can try and access other components like S3 buckets in the serverless infrastructure (assuming that the infrastructure has poor permission controls). We will look at an exploit scenario that would arise by the combination of these two vulnerabilities – injection + poor permission controls.
Of course, there can be other areas beyond the ones mentioned above, which can also be exploited through leveraging information leaked from lambda functions.
Let’s take a simple use case that we used in a previous blog: - There is an invoice processing system where a user submits an invoice (by uploading a file, providing the file name, other basic information etc.) through an API gateway. Some activities are then triggered across other AWS components like S3 and DynamoDB and the message to queue the invoice processing gets posted to Amazon SQS service for asynchronous processing.
As discussed in the previous blog, when the lambda function is vulnerable to command injection, the function allows to extract parameters from the shell in which the lambda function is running. An attacker can simply inject a payload to set or extract environment variables and fetch the below parameters from shell: -
aws_access_key_id
aws_secret_access_key
aws_session_token
It is possible to extract these parameters via vulnerable lambda functions (with and without outbound connections).
Without outbound connection (here)
With outbound connection (here)
It is also imperative to understand permission structure of the lambda function within AWS. These three parameters hold a key, which can be considered as a permission token. Whatever permission is assigned to the lambda function is mapped to these tokens "temporarily". The tokens might be valid for few hours, after which they are refreshed – once refreshed, the tokens need to be grabbed again.
In this case, the lambda function interacts with AWS S3 (Bucket 1) as shown in the above figure. We do not know the permission controls implemented for the lambda function and S3 resources. We execute the below script (the tokens fetched above are passed for authentication/authorization purposes) to enumerate S3 buckets and their content for this account and find out: -
Bingo! As we can see below, we were able to list all S3 buckets and their content. Why? It seems that the lambda function might have access to all S3 buckets.
Further, we can now enumerate and fetch secret files from inside the buckets. We can even end up writing to the buckets, depending on the permissions. Let’s try to fetch a file using the below script: -
The above script establishes a connection with the extracted tokens and tries to fetch the file.
We are also successful in fetching the file. This file should not be accessible to us but we end up having it.
Hence, here we are successful in exploiting the vulnerability due to poor permission controls.
Article by Amish Shah & Shreeraj Shah
1. Exploiting Backend – We use different methods (enumeration, tracing, fuzzing etc.) to identify that the lambda function is vulnerable to SQL injection. Once the vulnerability is identified, we inject attacks to exploit the vulnerability and fetch information about the back-end database, its tables etc. In this scenario, we are just leveraging and exploiting the weakness of the lambda function and not touching any other components in the overall infrastructure design.
2. Exploiting AWS Components – We use different methods (enumeration, tracing, fuzzing etc.) to identify the overall architecture and information about the components integrated with serverless functions. Once the vulnerability is identified (for example command injection), we inject payloads to exploit the vulnerability and steal critical information like access keys/tokens/secret etc. Using this information we can try and access other components like S3 buckets in the serverless infrastructure (assuming that the infrastructure has poor permission controls). We will look at an exploit scenario that would arise by the combination of these two vulnerabilities – injection + poor permission controls.
Of course, there can be other areas beyond the ones mentioned above, which can also be exploited through leveraging information leaked from lambda functions.
Let’s take a simple use case that we used in a previous blog: - There is an invoice processing system where a user submits an invoice (by uploading a file, providing the file name, other basic information etc.) through an API gateway. Some activities are then triggered across other AWS components like S3 and DynamoDB and the message to queue the invoice processing gets posted to Amazon SQS service for asynchronous processing.
As discussed in the previous blog, when the lambda function is vulnerable to command injection, the function allows to extract parameters from the shell in which the lambda function is running. An attacker can simply inject a payload to set or extract environment variables and fetch the below parameters from shell: -
aws_access_key_id
aws_secret_access_key
aws_session_token
It is possible to extract these parameters via vulnerable lambda functions (with and without outbound connections).
Without outbound connection (here)
With outbound connection (here)
It is also imperative to understand permission structure of the lambda function within AWS. These three parameters hold a key, which can be considered as a permission token. Whatever permission is assigned to the lambda function is mapped to these tokens "temporarily". The tokens might be valid for few hours, after which they are refreshed – once refreshed, the tokens need to be grabbed again.
In this case, the lambda function interacts with AWS S3 (Bucket 1) as shown in the above figure. We do not know the permission controls implemented for the lambda function and S3 resources. We execute the below script (the tokens fetched above are passed for authentication/authorization purposes) to enumerate S3 buckets and their content for this account and find out: -
Bingo! As we can see below, we were able to list all S3 buckets and their content. Why? It seems that the lambda function might have access to all S3 buckets.
Further, we can now enumerate and fetch secret files from inside the buckets. We can even end up writing to the buckets, depending on the permissions. Let’s try to fetch a file using the below script: -
The above script establishes a connection with the extracted tokens and tries to fetch the file.
We are also successful in fetching the file. This file should not be accessible to us but we end up having it.
Hence, here we are successful in exploiting the vulnerability due to poor permission controls.
Conclusion:
The permission controls implemented for lambda functions may not seem critical while executing the lambda function stand-alone or by looking at the features or from a developer standpoint but it might turn out to be catastrophic for the overall AWS infrastructure because of a combination of vulnerabilities. It would not only lead to a compromise of the lambda function or backend details but would impact the overall application residing on that particular account. Who knows? – An attacker may end up getting access to secret buckets, sensitive DynamoDB tables, EC2 backups and files etc. Thus, permission controls should be well implemented across the complete infrastructure and not stand-alone lambda functions. We will cover more on permission structures and issues in the coming blog posts.Article by Amish Shah & Shreeraj Shah