Sep 4, 2014

Lab Coat Lesson: Sample SOQL Injection

As a developer, you're familiar with performing SOQL queries and how flexible and powerful they can be. As you're developing for your company or customers whether it be for just internal use or creating a Managed Package, you've probably read, heard, or learned the hard way (hopefully not that last one) that you want to avoid scenarios that create an entry point for SOQL injection.

SOQL injection exploits your code in a way that modifies and takes advantage of an expected input used in a part of your query to return more information than is normally asked for.

Here's a quick example: On the Visualforce page below, there is a table of Contact information for records where only Contacts with a LastName starting with a letter provided in the URL parameter "letter."

The URL includes: .../apex/SOQLInjection?letter=b

Take a look at the Apex method that queries for matching Contact records and returns the results:

Basically, whatever is in the URL parameter is fed into this line:

While it works like a charm, by accepting input directly from a URL parameter (exposed/visible to an end user or not), you're opening your code up to the possibility of injection.

What if we do exactly that? Here's one example of how you can update the URL to return ALL of the Contacts, even those not flagged as "Public":

The URL now includes:

Then ends up translating in your query to:

To remedy this, the primary best practice from Salesforce is to avoid dynamic queries whenever possible by using static queries and binding variables within those queries. If you can't get away from dynamic SOQL, you can make use of the string.escapeSingleQuotes method.

Let's modify our getter method to use the escapeSingleQuotes method:

Making this change will result in the following query string:

This query results in the user receiving 0 results: