In our previous blog post we released a new utility called ‘Lambda-Proxy’, which helps SecDevOps teams to perform automated SQL Injection testing for AWS Lambda functions. The tool harnesses the power of SQLMap, the leading SQL Injection testing and exploitation tool, and wires it with the AWS SDK in order to perform the testing process through AWS Lambda event triggers, rather than over HTTP, which is what SQLMap was originally designed for.
Today, we’re going to demonstrate how a serverless function that is vulnerable to SQL Injection (and other event-data injection attacks) can quickly and effortlessly become immune to SQL Injection, when protected with PureSec.
In our example scenario, we have a Lambda function, which receives an SNS event, reads the ‘Message’ field from the event and checks it against a SQL database table (AWS RDS), which holds SNS messages that were stored previously. If the table has an entry with the same Message field, all the relevant SNS message data is retrieved.
Unfortunately, the developer of this Lambda function made a poor development choice, trusted the event input blindly, and used the Message as-is, without performing any input validation first. The root cause of the vulnerability lies in lines #30 and #32.
As you can see in the source code above, malicious input can enter our code through the event’s Message (the “source”), which is an untrusted field that may potentially be controlled by a malicious user, it is then assigned to the “msg” variable, and embedded into the SQL SELECT statement done using the call to cur.execute(...) (the “sink”).
This is a classic text-book SQL Injection vulnerability.
It goes without saying that by following secure development best practices, this vulnerability could have been avoided, however, people make mistakes. And in this case, the mistake is catastrophic.
Exploiting this vulnerability is as simple as riding a bicycle.
Here’s how a legitimate SNS event would look like, and then the function’s output:
Output (presented in the AWS Lambda console):
As you can see, the query returned a single matching SNS message. However, here’s a SQL Injection attack, carried inside the Message field of the event:
And the output to this SNS event now includes all the SNS messages in the database table:
Going back to our previous post, let’s release SQLMap (with Lambda-Proxy) on this function, as see what it comes up with:
As expected, SQLMap managed to dump the entire contents of the sns_messages table. Ouch!
As promised, we will now install the PureSec SSRE (Serverless Security Runtime Environment) protection library. The installation is extremely simple and includes 2 steps, which should take us not more than 2 minutes at most.
Add the PureSec runtime protection library as a dependency to our build process. This can be done quickly by using “pip install”, which we will add to the ‘requirements.txt’ file:
Add the PureSec runtime protection library as a dependency in our Python Lambda function. This is as simple as adding a line of code (line #10) to our Lambda function:
That was easy, right?
And now we can deploy the function - we will use the Serverless framework for this:
Voila! Our function is now secure and immune to event-data injection attacks. You don’t have to trust me of course, have a look at our function’s output logs, when sending the same SQL Injection payload that succeeded earlier:
Now let’s go back to our good ol’ friend SQLMap, and let it intelligently hammer the function with a battery of thousands of SQL Injection attacks, and see what it comes up with:
Awwwww…. All tested parameters do not appear to be injectable, and “shutting down…” - music to our ears.
Mission accomplished! function secured! nothing to see here, move along…
Stay tuned for our next blog post, which will showcase the unparalleled security visibility and forensics analysis, which are provided by the PureSec Serverless Security Dashboard and Splunk integration. After all, if you don’t know you are getting attacked, how can you defend yourself?