Finding SQL Injections through source code in .NET applications

Pavel Shabarkin
6 min readJul 8, 2022

--

Introduction

I have found that the most reliable way to achieve a higher rate of successfully identified vulnerabilities is to review the source code when possible. Source code review is a far more effective way than the black-box testing if you know the tactics and methods. In addition, by mapping each case you find and prepare a solution to identify vulnerabilities. This can then be used in creating a methodology for black box testing.

In this post we will discuss how to find for SQL Injections in .NET applications by walking through the source code.

This blog post is based on the research made by Yurii Sanin

SQL Injections in a .NET application

Basically, SQL Injection occurs when a user-controlled parameter can change the execution flow of an SQL query. This happens when data sent to the server side is concatenated with an actual SQL query. Most people know what SQL injection is, but fewer people know why and where exactly it appears in code.

SQL Injection within the ORM models

Most web applications that work with databases and use ORMs (entity framework , NpgSql) are mitigated against SQL Injection attacks. The usage of these models implies a first-code approach, where the application does not work directly with the SQL syntax, but uses already defined models.

The following examples do the same thing, in the first case with the help of ORM:

while the second one is a simple SQL Query:

Below is a brief description of what an ORM is:

We could not achieve a traditional SQL injection, where the application does not work directly with SQL syntax. However, we can try if the application works with raw SQL query in the FromSqlRaw or FromSqlInterpolated method of the ORM object.

If the tableName is a user-controllable parameter and user input is not properly sanitized, an attacker can perform an SQL Injection attack:

While working in the SQL Context, the web application can securely process user-controlled parameters using the FromSqlInterpolated method by passing an interpolated string as an argument:

In the case of the FromSqlRaw method, the interpolated string is rendered before being passed to the method. In the case of the FromSqlInterpolated method, on the contrary, the interpolated string is not rendered before passing the argument to the method; inside the FromSqlInterpolated method, it parameterizes each SQL parameter to a specific type and performs normalization of the supplied parameter.

An example of a simple parameterization in .NET:

SQL Injection within an ADO.NET SqlHelper class

While walking through the documentation I identified the SqlHelper class supports ExecuteDataset, ExecuteNonQuery, ExecuteScalar and similar methods.

From my observations, applications followed 2 approaches:

  1. By invoking SqlHelper.<method> and providing an SQL query (a raw string) that is composed before being passed to the method parameter, an application informs the SQL method to process the SQL string as CommandType.Text.
  2. By invoking SqlHelper.<method>, first parametrizing the parameters with the SqlParameter and informing the SQL method to process SQL string as CommandType.StoredProcedure.

All SQL injections could be identified when the SQL string is composed by concatenating user-controlled parameters with the actual SQL query and the method of the SqlHelper class is invoked with the CommandType.Text parameter, which informs the method to process the SQL query as a raw string:

Hunting methodology through source code

Again, SQL Injections occur in applications when a user-controlled parameter is composed with an SQL query and the result of this procedure is a raw string passed to the SQL execute function. The SQL query string can be composed before the actual SQL execution.

To search for SQL Injections, identify the pattern and the way in which the application creates and maintains a connection to the database.

Then, grep for entries of the following functions, directives, and classes:

  1. using System.Data.SqlClient - namespace
  2. SqlCommand - Represents a Transact-SQL statement or stored procedure to execute against a SQL Server database.
  3. OracleCommand - Represents a Transact-SQL statement or stored procedure to execute against a SQL Server database.
  4. OdbcCommand - Represents a Transact-SQL statement or stored procedure to execute against a SQL Server database.
  5. OleCommand - Represents a Transact-SQL statement or stored procedure to execute against a SQL Server database.

The presence of the “using System.Data.SqlClient" namespace will tell you what type of SQL class the application uses.

All of these classes inherit the same class. While searching for the injection locations, review the surroundings of these classes to determine the context for the SQL Injection attack.

The SqlConnection and SqlCommand classes are usually used to execute SQL queries. SqlCommand has ExecuteNonQuery and ExecuteQuery methods. NonQuery returns the number of rows that have been affected, while ExecuteQuery returns the DataReader used to read the SQL data stream. You can recognize all kinds of SQL injection possibilities (format strings, concatenations, interpolations) when you look at the ExecuteNonQuery , ExecuteQuery and other methods.

  1. EntityCommand
  2. ExecuteNonQuery
  3. ExecuteQuery
  4. ExecuteDataset
  5. ExecuteScalar
  6. etc …
SqlCommand cmd = new SqlCommand("insert into STUDENT_TABLE (name, age, email) values ( " + this.username + "," + this.age + "," + this.email + ")", <connection_string>);
cmd.ExecuteNonQuery();

Also, I would recommend looking for CommandType.Text directives to identify places where the SQL query will be processed as a raw string in ADO.NET applications.

Summary

SQL Injection is a critical-impact vulnerability that allows an attacker to compromise the application’s database. There is a myth that encountering an SQL Injection attack in today’s applications is almost impossible, especially if you test applications in “black-box” manner. In my experience they are still actively introduced in modern source code and applications, and even furthermore not fixed in older codebases. As long as programming languages and frameworks use those unsafe methods and patterns, the critical vulnerabilities will exist. Finding them through the source code is a simpler and approachable including for non security people.

If you have any questions contact me on my social nets:

Twitter: https://twitter.com/shabarkin

Linkedin: https://www.linkedin.com/in/pavelshabarkin/

References

  1. https://www.tutorialspoint.com/entity_framework/entity_framework_code_first_approach.htm
  2. https://openclassrooms.com/en/courses/5671811-implement-a-relational-database-with-asp-net-core/6588450-identify-object-relational-mapping-orm-tools-for-net
  3. https://www.stackhawk.com/blog/net-sql-injection-guide-examples-and-prevention/
  4. https://www.codemag.com/article/0411061/Data-Access-with-Microsoft-Application-Blocks

--

--

No responses yet