Blog Dla Programistów C#/.NET

wtorek, 18 listopada 2025

SQL Injection (wstrzyknięcie SQL) to jedno z najgroźniejszych zagrożeń dla aplikacji bazodanowych. Atakujący mogą wykorzystać tę lukę, aby uzyskać nieautoryzowany dostęp do danych lub nawet usunąć zawartość bazy danych. Nic dziwnego, że ataki tego typu regularnie pojawiają się w czołówce rankingów bezpieczeństwa (wg OWASP Top 10 ataki typu Injection zajmują jedno z najwyższych miejsc). Dlatego każdy programista C# powinien znać podstawy ochrony przed SQL Injection. W tym artykule wyjaśniam, na czym polega ten atak oraz jak zabezpieczyć przed nim aplikacje pisane w C#.

Jak Chronić Aplikację C# Przed SQL Injection?

Czym jest SQL Injection?


W dużym skrócie, SQL Injection polega na wstrzyknięciu własnego kodu SQL do zapytania bazy danych konstruowanego przez aplikację. Dzieje się tak najczęściej, gdy aplikacja buduje dynamiczne zapytanie SQL na podstawie danych wejściowych od użytkownika. Przykładowo, rozważmy następujący (błędny) fragment kodu C#:

/* Niebezpieczne podejście – podatne na SQL Injection: */
string userInput = "Jan'; DROP TABLE Users;--";
string query = "SELECT * FROM Users WHERE Name = '" + userInput + "'";
/* Wynikowe zapytanie SQL: */
/* SELECT * FROM Users WHERE Name = 'Jan'; DROP TABLE Users;--' */

W powyższym kodzie aplikacja bezpośrednio dokleja dane użytkownika do tekstu zapytania SQL. Jeśli userInput zawiera złośliwy ciąg znaków taki jak w przykładzie (zakończenie apostrofem, komenda DROP TABLE i komentarz --), to finalne zapytanie wysłane do bazy stanie się połączeniem naszej intencji z poleceniem atakującego. Zamiast bezpiecznie wyszukać użytkownika "Jan", baza wykona dwa polecenia: najpierw normalne zapytanie SELECT, a zaraz po nim destrukcyjne skasowanie tabeli Users. Taki nieautoryzowany dostęp czy modyfikacja danych to właśnie cel ataku SQL Injection.


Jak zabezpieczyć aplikację przed SQL Injection?


Najważniejsza zasada obrony to nigdy nie łączyć bezpośrednio danych wejściowych z treścią zapytania SQL – jest to jeden z najczęstszych błędów popełnianych przez programistów, który otwiera furtkę dla ataków. Zamiast tego należy stosować parametryzowane zapytania, które oddzielają kod SQL od danych. Mechanizm parametrów sprawia, że dane od użytkownika są przekazywane do bazy osobno – jako wartości, a nie część zapytania. Dzięki temu nawet jeśli ktoś wprowadzi złośliwy ciąg znaków, baza danych potraktuje go wyłącznie jako zwykłą wartość (np. część warunku wyszukiwania), a nie jako dodatkową komendę do wykonania.

/* Bezpieczne podejście – wykorzystanie parametru zamiast konkatenacji: */
string userInput = "Jan";
string query = "SELECT * FROM Users WHERE Name = @name";
using var command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@name", userInput);
/* ... wykonanie zapytania przy użyciu command */

W powyższym kodzie zamiast wstawiać wartość userInput bezpośrednio w treści SQL, użyliśmy parametru @name. Dzięki temu do bazy danych zostanie wysłane zapytanie z parametrem, a wartość "Jan" zostanie przekazana osobno. Serwer SQL wykona zapytanie, podstawiając wartość parametru w miejsce @name, ale nie potraktuje jej jako kod do wykonania. Tym samym nawet podanie złośliwego ciągu (jak poprzednio) nie wyrządzi szkód – zostanie on potraktowany jedynie jako zwykły literał tekstowy, który nie może zamknąć stringa ani dodać własnej komendy SQL.

W praktyce łatwo zapewnić sobie ochronę przed SQL Injection, korzystając z nowoczesnych bibliotek dostępu do danych lub ORM. Na przykład Entity Framework Core automatycznie stosuje parametryzację, gdy tworzysz zapytania przy użyciu LINQ – zapytania LINQ są tłumaczone na SQL z parametrami, co zapobiega wstrzyknięciom kodu. Innymi słowy, jeśli napiszesz w EF Core zapytanie jak poniżej:

var lista = context.Users.Where(u => u.Name == userInput).ToList();

to pod spodem EF wygeneruje odpowiedni SQL z użyciem parametru zamiast wstawiać wartość userInput wprost do zapytania. Korzystając z takiego ORM w typowy sposób, ryzyko SQL Injection jest więc zminimalizowane. Oczywiście, jeśli zajdzie potrzeba wykonania surowego SQL-a w EF, można to zrobić bezpiecznie – należy skorzystać z metod typu FromSqlInterpolated lub przekazać osobno parametry do FromSqlRaw, a EF zadba wtedy o ich prawidłowe wstawienie jako parametry.

Warto również stosować zdroworozsądkową walidację danych wejściowych po stronie serwera. Nie chodzi o ręczne "czyszczenie" stringów z podejrzanych znaków (takie podejście jest zawodne), ale o sprawdzenie, czy dane mają poprawny format i mieszczą się w spodziewanym zakresie. Przykładowo, możemy upewnić się, że identyfikator użytkownika to liczba, a nazwa nie przekracza rozsądnej długości. Taka pozytywna walidacja utrudni atakującemu podawanie całkowicie niepasujących danych i stanowi dodatkową warstwę obrony – choć kluczowe i tak jest użycie parametrów.

Podsumowując podstawowe zasady ochrony przed SQL Injection w C#:
Stosuj zapytania parametryzowane – oddzielaj dane od kodu SQL, zamiast wbudowywać wartości użytkownika bezpośrednio w tekst zapytania.
Unikaj konkatenacji stringów SQL z danymi wejściowymi – nie buduj zapytań poprzez sklejanie fragmentów tekstu z niesprawdzonym inputem użytkownika.
Korzystaj z ORM lub bibliotek, które automatycznie parametryzują zapytania (np. Entity Framework Core, Dapper) – ułatwia to pisanie bezpiecznego kodu.
Waliduj dane wejściowe – sprawdzaj, czy parametry od użytkowników mają oczekiwany format i zakres; to pomoże wychwycić podejrzane wartości już na etapie logiki aplikacji.


Podsumowanie


Ataki SQL Injection są groźne, ale na szczęście można się przed nimi stosunkowo łatwo zabezpieczyć – głównie trzymając się zasady używania parametryzowanych zapytań i ostrożnego obchodzenia się z danymi wejściowymi. Warto wyrobić sobie te dobre nawyki już na początku przygody z programowaniem, bo dzięki nim nasze aplikacje będą znacznie bardziej odporne na potencjalne ataki.

Jeśli interesuje Cię temat bezpiecznego programowania w C#/.NET, zachęcam do sprawdzenia mojego szkolenia online "Szkoła Bezpieczeństwa w C#/.NET". To kompleksowe szkolenie o tym, jak pisać bezpieczne aplikacje webowe w ASP.NET Core – omawiam tam m.in. ochronę przed SQL Injection oraz wiele innych aspektów zabezpieczania aplikacji.

Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
CTO & Founder - FindSolution.pl
Programista C#/.NET. Specjalizuje się w Blazor, ASP.NET Core, ASP.NET MVC, ASP.NET Web API, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Dodaj komentarz

Wyszukiwarka

© Copyright 2025 modestprogrammer.pl | Sztuczna Inteligencja | Regulamin | Polityka prywatności. Design by Kazimierz Szpin. Wszelkie prawa zastrzeżone.