P M A J E W S K I

Please Wait For Loading

SQL Injection in C# Application: An Example - Software Developer's Tour

    You Are Currently Here!
  • Home
  • ProgrammingSQL Injection in C# Application: An Example
Data mining and big data

SQL Injection in C# Application: An Example

Today, I'll show you some code vulnerable to SQL Injection. We will talk about good and bad practices. At the end I'll tell you which option is in my opinion the best one and why.


So... Let's get started...

To try to do something with SQL, we need a new table in our fake database.

users table

Now, have a look at this ugly code…

What do we have here?

We have a POST endpoint /login which receives two strings, email and password.

 

This endpoint connects to the database and executes a command to select the first match of a user where the email and password (in plain text for testing purposes 🙃) match the provided data.

app.MapPost("/login", (string email, string password) =>
{
    const string connectionString = "Data Source=localhost;Initial Catalog=TestSqlInjection;Integrated Security=true;TrustServerCertificate=true;";
    using var connection = new SqlConnection(connectionString);
    using var command = connection.CreateCommand();
    command.CommandText = $"SELECT * FROM USERS WHERE Email = '{email}' AND Password = '{password}';";
    connection.Open();
    using var reader = command.ExecuteReader();
    reader.Read();
    
    return new User(Convert.ToInt32(reader["Id"]), reader["Email"].ToString()!);
})
.WithName("Login")
.WithOpenApi();

This code has couple of minor errors.

Command is concatenated from user’s data without any validation or using sql parameters.

Okay, let’s add some users

SELECT TOP (1000) [Id]
      ,[Email]
      ,[Password]
  FROM [TestSqlInjection].[dbo].[Users]
users_in_db_2

okay, there we have it. Let’s try to log in to our application with email “tester@example.com” and password “qwe“.

It looks like it’s working, doesn’t it? Don’t fall for it.

 

There are many things that can be done with our dirty backend code. Try logging in as “tester@example.com without knowing its password.

login_without_knowing_password

Let’s enter the following code as the password.

' or 1=1--

Explanation:

SELECT * FROM USERS WHERE Email = ‘{email}’ AND Password = ‘{password}‘;

The bolded part will be replaced with the password provided by the user. So, we are using a (single quote) as the end of the string. Do you see it? In the SQL clause, we have:

AND Password = ‘{password}‘;

When we use a single quote as the first character, we end this clause. Then we start a new clause, OR 1 = 1, which is always true.

What is the role of the  (SQL comment syntax) at the end?

Without this, our query would end with a single quote character, which is invalid SQL. We have to comment out the rest of the code after the password to ensure that our query will end with OR 1 = 1. Without this, we would get the following error:

Unclosed quotation mark after the character string ‘;
‘.

So the final clause is

SELECT * FROM USERS WHERE Email = 'tester@example.com' AND Password = '' or 1=1--';

Without security measures, someone could steal sensitive data. We can log in as any registered user.

If what we just did happened in a real application, it would definitely be a breach of GDPR in Europe.

Let’s get back on topic, though. Is that all we can do?

How about destroying data?

Of course system hacker can use that trick to destroy our data. Have a look:

'; update users set password = 'newpass'--

The final clause is

SELECT * FROM USERS WHERE Email = 'tester@example.com' AND Password = ''; update users set password = 'newpass'--';

And the result? Please

updated users

Our application has a bug. When no user has been found, we’re getting an exception,  but that doesn’t matter because I wanted this application to have nothing but the essentials for testing our SQL.

exception

Okay, what’s stopping us from clearing our table? Nothing.

Let’s check the following password

'; delete from users--

The final clause

SELECT * FROM USERS WHERE Email = 'tester@example.com' AND Password = ''; delete from users--';

Of course there’s an exception in our application but what’s happened in our database?

We lost all of them.

How can we avoid SQL Injection? That will be in the next post.

leave a comment