Guarding Against SQL Injection at the Database Layer (SQL Server)

  • Comments posted to this topic are about the item Guarding Against SQL Injection at the Database Layer (SQL Server)

  • The solution to SQL injection is to place all user identification and security in the database.

    Using a combination of table and row level security is possible to define exactly which data the users in any role can select or update. As far as a particular group of users is concerned this defined subset of the database is the database.

    So an application can use whatever SQL it likes, including dynamic SQL, without compromising the data or the structure of the database in any way.

     

  • You’re right, putting proper user identification and security in the database is a strong solution. Using table and row level security properly can lock things down very tightly and, in theory, let the application do what it wants without exposing data or structure.

    The difficulty is that a lot of systems in production today were built years ago, when security was not always designed in from the start. Many still use shared SQL accounts with broad permissions, and access control is handled mostly in the application layer.

    Moving those systems to granular role-based access and row level security can mean major refactoring. It often involves changes to authentication, permissions, stored procedures, and sometimes the overall architecture. That is the right direction, but it is rarely something that can be done quickly.

    I still see SQL injection in the wild quite often, especially in legacy estates. For many organisations, strengthening database-layer security has to happen step by step rather than all at once.

    Completely agree with you on the end goal though.

  • Implementing the database level security would open up the database to flexible access independent of applications. This is one of the reasons that we have relational DBMSs to begin with.

    This could be done without any impact on existing applications. The applications could follow on, though the first step would be to severely restrict the access rights of the generic login used by each application.

     

  • You  are right however, Restricting database login rights reduces the impact surface of a successful SQL injection attack but does not prevent injection itself. Prevention requires parameterized queries and safe query construction at the application layer. Database-level controls provide defence-in-depth, not primary mitigation.

  • Database level security offers security of the data against SQL injection completely independently of how the database is accessed either through applications or ad-hoc queries. There need be no duplication of the security logic in different applications, substantially reducing errors and the workload of application developers.

    The remaining risk of SQL injection is denial of service by, for example, starting a Cartesian product of the largest tables in the database inside a serialisable transaction. Some other methods would be necessary to protect against this, but the data would still be safe.

  • will 58232 wrote:

    Implementing the database level security would open up the database to flexible access independent of applications. This is one of the reasons that we have relational DBMSs to begin with.

    This could be done without any impact on existing applications. The applications could follow on, though the first step would be to severely restrict the access rights of the generic login used by each application.

    The policies I've worked with for a long time do not allow users to have any update type access to a database with their regular login credentials. In fact, we typically limit direct user access to data completely because too many users in the past used MS access a sa tool and locked up the database. If users can directly access data for query, it's done on a copy of the data. If users have update access, how do you stop them from randomly changing data outside an application? Users cannot be trusted to not break things on a regular basis.

     

    will 58232 wrote:

    The solution to SQL injection is to place all user identification and security in the database.

    Using a combination of table and row level security is possible to define exactly which data the users in any role can select or update. As far as a particular group of users is concerned this defined subset of the database is the database.

    So an application can use whatever SQL it likes, including dynamic SQL, without compromising the data or the structure of the database in any way.

    The solution to SQL injection is to write applications in a manner that makes injection impossible. And set up security to prevent users from doing anything outside an application.

  • The solution to SQL injection is to write applications in a manner that makes injection impossible. And set up security to prevent users from doing anything outside an application.

    There might be hundreds or even thousands of SQL queries in an application that might have been worked on by dozens of programmers over time. The chances that every programmer has written every piece of code to avoid SQL injection is pretty close to zero.

    The risk to data security is too great to rely on such methods.

    • This reply was modified 3 days, 8 hours ago by will 58232.
    • This reply was modified 3 days, 8 hours ago by will 58232.
  • If users have update access, how do you stop them from randomly changing data outside an application? Users cannot be trusted to not break things on a regular basis.

    By having constraints in the database. The constraints prevent users from doing anything that they are not allowed to do or to do anything that would damage the integrity of the data.

    If you leave the constraints in the applications then every application will have to re-implement these constraints. The integrity of the database will be compromised and code reduplicated.

    What applications do is to provide some constraint on input so that users can only choose valid entries but this shouldn't be where the data integrity rules are implemented. The constraints in the user interface should be directly derived from the constraints in the database - something that can be achieved automatically without the application programmer having to be concerned with it. Otherwise you are reduplicating logic and risking data quality. All the application is doing is applying the already defined constraints in the database pre-emptively so the user is guided to making correct input.

    Putting the constraints in the database is the only way to ensure the integrity of the data and rendering SQL injection completely incapable of violating these constraints.

  • Just to be clear, this solution only works if the code is using stored procs. If the code is building its own dynamic SQL and sending that to the database, this solution won't catch it and in my experience, it is the middle-tier code assembling raw SQL statements where I've found the vast majority of SQL injection vulnerabilities. It can clearly happen when the middle-tier code tries to assemble the call to the stored procs but my experience has been that this is less often. Still, for those times, as mentioned in the article, I can see how this would be an additional layer of protection.

Viewing 10 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic. Login to reply