SQL Injection attacks in BaaS and prevention tips

APIs built on Apigee BaaS can be vulnerable to SQL Injection attacks. Lets look at some code snippets, an example attack and methods to prevent it.

APIs receive data from client in the form of headers, query params, path fragments or payload. This data is often used directly to construct a query for use with BaaS. When such a value is not sanitised, the client can mount a SQL Injection attack on the API.

Lets look at an example API that returns discounts for a request category.

<a href="http://example-prod.apigee.net/v1/discounts?category=default">http://example-prod.apigee.net/v1/discounts?category=default</a>

The value 'default' is received from client as a query parameter. Below is a node.js snippet from the API that uses this query parameter value to construct the BaaS query.

    var category = request.query.category;
    var options = {
        'method' : 'GET',
        'uri' : baaSParams.URI + baaSParams.app + '/customerDiscounts',
        'qs': {
              'client_id' : baaSParams.clientId,
              'client_secret' : baaSParams.clientSecret,
              'ql':"select * where discountCategory='" + category + "'"
        }
    }
    request(options, callback);

The query parameter is directly appended to the 'ql' property. The value of the query parameter category is used to construct the query.

ql = select * where discountCategory = 'default'

Let us see how the above code can be exploited to mount a SQL Injection attack. Consider the following request to the same API,

<a href="http://example-prod.apigee.net/v1/discounts?category=default%27+or+name%3D%27premium">http://example-prod.apigee.net/v1/discounts?category=default%27+or+name%3D%27premium</a>

decoded value of query parameter category is as follows:

default' or discountCategory='premium

The single quote after 'default' balances the single quote in the query in the node.js snippet. It further extends the query to do more. Here is the final structure of the 'ql' param.

select * where discountCategory='default' or discountCategory='premium'

The API originally intends to return only the default discounts applicable to all users, but ends up returning discounts for premium users too. When the API response contains additional discounts a SQL Injection attack has succeeded.

A SQL Injection need not reflect in the API response, it may cause a specific entity to be created in a collection that could later cause the response from other APIs to change or an API behaviour to be different often favourable to the attacker.

Now let us look at a few ways to prevent this attack and things to note while implementing prevention methods:

  1. Always sanitise data from client before adding it to a query. Look for special characters, especially single quote.
  2. Add sanitisation or assertion code as close to the query as possible. Data validation when performed early may be lost when other pieces of data are concatenated to it and used in a query.
  3. Consider adding sql-injection check to express. Refer: https://www.npmjs.com/package/sql-injection (a relatively young package though. Use at your own discretion)
  4. Add SQL Injection tests to your testcases
  5. A difficult to prove attack doesn't mean there is no vulnerability. Certain code constructs make it difficult to prove an attack, however the code can still be vulnerable.
  6. An undocumented, unpublished code can still make the entire system vulnerable. Fix all issues.
  7. Remember, attacks can be performed in multiple stages and your API could be one of the stage. A minor corner case can compromise an entire system.

Do you have more suggestions, please feel free to add them in the comments.

Comments
Not applicable

Apigee also has a RegularExpressionProtection policy that can be included to protect - at least to a large extent - against not only SQL injection attacks but JS injection as well. The protection is only as good as the regular expression you use, but there's a sample of a decent regex included in the policy documentation. You can easily include this policy in the proxy PreFlow or Conditional flow, prior to invoking the Node.js target. http://apigee.com/docs/api-services/reference/regular-expression-protection

Version history
Last update:
‎03-07-2015 10:21 AM
Updated by: