SQL Injection

SQL Injection

Niezabezpieczony formularz

SQL Injection to technika, która pozwala atakującemu manipulować zapytaniami SQL, które są wykonywane przez aplikację. Atakujący może wykorzystać to do obejścia uwierzytelniania, wyświetlenia, modyfikacji lub usunięcia danych w bazie danych.

W niezabezpieczonej wersji, dane wprowadzone przez użytkownika są bezpośrednio wstawiane do zapytania SQL. Na przykład, w metodzie sprawdzającej dane logowania


public function getUnsafe($username, $password) {
    $stmt = $this->pdo->query("SELECT * FROM users WHERE username = '$username' AND password = '$password'");
    return $stmt->fetch(); 
}
                    
zapytanie SQL jest tworzone przez konkatenację ciągu z danymi wprowadzonymi przez użytkownika. Jeśli atakujący wprowadzi wartości, które zmieniają strukturę zapytania SQL, może to prowadzić do niezamierzonych konsekwencji.
Metoda getUnsafe zwraca wynik zapytania SQL jako tablicę asocjacyjną, gdzie klucze są nazwami kolumn w wyniku zapytania SQL. W tym przypadku, zapytanie SQL to
SELECT * FROM users WHERE username = '$username' AND password = '$password'     
więc wynik będzie zawierał wszystkie kolumny z tabeli users dla użytkownika, który pasuje do podanego username i password. Jednakże, ponieważ metoda getUnsafe jest podatna na ataki SQL Injection, jeśli atakujący wprowadzi specjalnie sformułowane wartości dla username i password, może to prowadzić do niezamierzonych wyników. Na przykład, jeśli atakujący wprowadzi
 ' or ''='  
jako wartość dla username i password, metoda getUnsafe zwróci dane pierwszego użytkownika w tabeli users, niezależnie od tego, jakie wartości username i password zostały faktycznie przekazane.

Zabezpieczony formularz

W zabezpieczonej wersji, dane wprowadzone przez użytkownika są parametryzowane, co oznacza, że są traktowane wyłącznie jako dane, a nie część zapytania SQL. Na przykład, w metodzie zabezpieczonej, która sprawdza dane logowania


public function getSafe($username, $password) { 
    $stmt = $this->pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); 
    $stmt->execute([$username, $password]); 
    return $stmt->fetch();
 } 
                    
zapytanie SQL jest przygotowywane z miejscami na parametry, które są później wypełniane danymi wprowadzonymi przez użytkownika. To zapobiega manipulacji struktury zapytania SQL przez atakującego.


Parametryzacja zapytań SQL jest zdecydowanie lepsza, ponieważ zapobiega atakom SQL Injection. Nawet jeśli atakujący próbuje wprowadzić wartości, które zmieniają strukturę zapytania SQL, te wartości są traktowane jako dane, a nie jako część zapytania SQL. To oznacza, że atakujący nie może manipulować zapytaniem SQL wykonywanym przez aplikację.

Dodawanie użytkowników