by Cossack Labs Dev Stories

How to prevent database leaks and injections

nuoAoZeGcfCohDY7q8yJplHHTVcxa6AKZSJG

Most web and mobile apps have a backend that includes a database of some kind. Your front end consumes data from your back end, and also gathers new data to feed back into your database.

Often hackers will target your database for malicious attacks, trying to steal or modify sensitive pieces of information. But most back ends are pretty well protected, and the only attack vector available for malicious actions is through your front end itself.

BSMBLVpI4-zg7BBiojecfZUdWPiqzdU-ThI6
Your modern app layout, clean and simple

There are many traditional techniques for protecting your data. Most of them will hurt your performance and also limit the scope of protection of your data at the same time.

This post is about something else — several interesting techniques we’re using for detecting intruders in Acra, our open-source database protection suite.

Front end under attack!

No matter what kinds of authentication and encryption stand between your front end and the remaining parts of your system, you have to trust your front end to let it pass data on in. Any request your front end sends with the correct authentication parameters, your database has to serve.

But what if your front-end application gets exposed in a way that an attacker is able to alter execution or data request flow?

TK2HFw3HHtNhZhyeMt40bYaN-ZfgfOiF-EgJ
How about forgetting to filter quotes?

If you trust your application and its credentials, you will serve all of its requests, no matter how malicious they are.

Let’s introduce a Watchdog

RPXZ25FiPppNgmfPdm8cEZeOxsjUtb5kVW4C
Now, all traffic passes through the Watchdog node

Watchdog is a network proxy server that sits between your app and your database, and controls your data stream. If the infrastructure behind the app was not compromised and only front-end is under attack, the only way for attackers to get the data they’re after is sending malformed requests through this Watchdog.

But apart from just enforcing access policy, it can filter correct requests and deny access for the obviously malicious ones.

So, what does such a Watchdog proxy do? It tries to detect anomalies and all large-scale selects that aren’t typical for an application flow. Then based on threat level, it either shuts down database access or generates notification events for monitoring.

Like the idea? Acra is such a watchdog, additionally providing cryptographic services, focused on selectively and flexibly protecting only sensitive parts of the data you store.

What kind of bad requests should we detect?

Typical payloads for SQL Injections:

  • Inserts, targeting authentication data
  • SELECT *
  • Command execution
  • Grant rights
  • Denial of service attacks
  • Typical signatures of escaping payloads to execution on database side

Detection methods

Detection sounds simple — we should just look at the traffic that passes through Watchdog and match it against some rule. But SQL injections aren’t always simple binary arrays of bytes with pre-determined signatures, which are easy to spot. There are different methods you can use to efficiently scan the database request traffic:

Query templates

A simple, flexible method of detecting suspicious behavior is matching SQL requests against some list of patterns. It takes some effort to create such a list covering most of the typical attack vectors for your particular data flow. Then you have to match queries against this list. But this is an efficient way to spot most unsophisticated attempts at scale, and early on.

Poison records

A classic design used to prevent SELECT *-type injections, poison record is a way to detect massive requests to the database. Designing your database requests yourself — or at least enumerating the ones your ORM generates — allows you to understand which tables with sensitive data are never accessed via requests with full scan requests. You can store a special record, a tag, in this table, which, when passing the Watchdog, triggers the alarm.

Query enumeration

— Let’s try injecting this way…
— Hmm, nah, doesn’t work
— What about that way of escaping magic quotes?

Most processes for finding and exploiting bugs rely on the try-fail-try-again cycle, in which attacker generates a lot of broken queries. Some of them will contain typical signatures, but overall they will increase the number of bad queries to your database.

While detecting these signatures is hard, detecting a sudden increase in empty/syntax error responses from the database is fairly easy.

One of the interesting challenges we’re pursuing right now is being able to detect abnormal (compared to regular request flow) behavior via a machine learning-trained classifier.

What if an attacker mounts an attack that’s indistinguishable from normal application behavior?

If the attacker is able to reverse engineer the regular data flow and emulate it in a way that you can’t distinguish from the normal app behavior, they will be able to get past your watchdog.

Further reading

I recommend reading these three articles on classic and modern patterns in database defenses:

Cossack Labs / Classic backend security design patterns
In modern client-server applications, most of the sensitive data is stored and (consequentially) leaked lives on the…www.cossacklabs.comCossack Labs / Key management for modern application security 101
Frequently overlooked, much less hyped than quantum computers breaking trapdoor functions, managing keys is actually…www.cossacklabs.comCossack Labs / 12 and 1 ideas how to enhance backend data security
Previously, we’ve talked about classic design patterns in backend data security, then about key management goals and…www.cossacklabs.com

Thanks for reading.