CZĘŚĆ 17
Bezpieczeństwo: SQL injection
PPrezentacja dla nauczyciela
Sklejenie zmiennych z formularza lub adresu URL bezpośrednio z tekstem zapytania SQL otwiera najgroźniejszą lukę: SQL Injection. Jedynym w 100% skutecznym i wymaganym na egzaminie INF.03 sposobem ochrony są zapytania przygotowane (prepared statements) w proceduralnym mysqli.
Jak działa SQL injection
SQL injection polega na dopisaniu fragmentu SQL do danych z formularza. Jeśli zapytanie powstaje przez sklejenie tekstu, użytkownik może zmienić jego sens.
Klasyczny przykład: pole login z wartością ' OR 1=1 -- zamyka apostrof i sprawia, że warunek staje się zawsze prawdziwy. Wtedy logowanie przechodzi bez hasła.
Skutki to nie tylko obejście logowania: odczyt innych tabel, zmiana danych, a przy błędnej konfiguracji nawet usunięcie tabel. Ryzyko rośnie, gdy konto bazy ma szerokie uprawnienia.
$login = $_POST['login'] ?? '';
// podatne: dane staja sie czescia zapytania
$sql = "SELECT id FROM users WHERE login = '$login'";
// bezpieczne: osobne zapytanie i osobne dane
$stmt = $pdo->prepare('SELECT id FROM users WHERE login = ?');
$stmt->execute([$login]);
Zapytania przygotowane
Zapytanie przygotowane rozdziela kod SQL od danych. Najpierw wysyłamy szkielet z pytajnikami, potem osobno wartości — baza nigdy nie potraktuje ich jak polecenia.
W PDO używamy prepare() i execute([...]). W mysqli jest mysqli_prepare() oraz wiązanie parametrów przez bind_param().
To podstawowe zabezpieczenie i jednocześnie wygodny sposób pracy: to samo zapytanie można wykonać wiele razy z różnymi danymi, bez budowania tekstu od nowa.
$stmt = $pdo->prepare('SELECT id, imie FROM uczniowie WHERE klasa = ? AND punkty > ?');
$stmt->execute(['3TI', 10]);
foreach ($stmt as $w) {
echo htmlspecialchars($w['imie'], ENT_QUOTES, 'UTF-8');
}
// mysqli
$stmt2 = mysqli_prepare($polaczenie, 'SELECT imie FROM uczniowie WHERE klasa = ?');
mysqli_stmt_bind_param($stmt2, 's', $klasa);
mysqli_stmt_execute($stmt2);
Walidacja i uprawnienia bazy
Zapytania przygotowane chronią przed wstrzyknięciem, ale nie zastępują walidacji. Nadal sprawdzamy typ, zakres i długość danych, bo błędne wartości psują logikę aplikacji.
Drugi filar to minimalne uprawnienia konta bazy. Konto aplikacji powinno mieć prawo odczytu i zapisu w swoich tabelach, a nie prawo usuwania bazy.
Warto też wyłączać szczegółowe komunikaty błędów na produkcji. Komunikat z treścią zapytania ułatwia atakującemu poznanie struktury bazy.
$klasa = trim($_GET['klasa'] ?? '');
if (!preg_match('/^[1-4][A-Z]{2}$/', $klasa)) {
exit('Nieprawidlowa klasa');
}
$stmt = $pdo->prepare('SELECT imie FROM uczniowie WHERE klasa = ?');
$stmt->execute([$klasa]);
$dane = $stmt->fetchAll();
Ćwiczenia
- 1Pierwsze zapytanie przygotowane i apostrofpierwsze zapytanie i apostrofZadanie i podpowiedzi →
- 2Parametr liczbowy całkowity (typ i)parametr liczbowy całkowity iZadanie i podpowiedzi →
- 3Odczyt listy wierszy z zapytania przygotowanegoodczyt wierszy z zapytaniaZadanie i podpowiedzi →
- 4Parametr zmiennoprzecinkowy (typ d)parametr zmiennoprzecinkowy dZadanie i podpowiedzi →
- 5Dwa parametry tekstowe (ss) w klauzuli WHEREdwa parametry tekstowe ssZadanie i podpowiedzi →
- 6Parametry mieszane tekst i liczba (si)parametry mieszane si w WHEREZadanie i podpowiedzi →
- 7Wyszukiwanie LIKE z parametrem i znakiem %wyszukiwanie LIKE z parametremZadanie i podpowiedzi →
- 8Bezpieczny INSERT INTO z parametramibezpieczny INSERT z parametramiZadanie i podpowiedzi →
- 9Identyfikator wstawionego wiersza (mysqli_stmt_insert_id)klucz wstawionego wiersza insert_idZadanie i podpowiedzi →
- 10Bezpieczna aktualizacja UPDATE z parametramibezpieczny UPDATE z parametramiZadanie i podpowiedzi →
- 11Liczba zmienionych wierszy (mysqli_stmt_affected_rows)liczba zmian affected_rowsZadanie i podpowiedzi →
- 12Bezpieczne usuwanie DELETE z parametrembezpieczny DELETE po idZadanie i podpowiedzi →
- 13Biała lista dla nazw kolumn i parametr dla WHEREbiała lista kolumn w ORDER BYZadanie i podpowiedzi →
- 14Zwalnianie zasobów (mysqli_stmt_close)zwalnianie zasobów mysqli_stmt_closeZadanie i podpowiedzi →
- 15Naprawa podatnego zapytania ze sklejaniemnaprawa podatnego skryptuZadanie i podpowiedzi →
- 16Bezpieczna wyszukiwarka produktów (synteza)bezpieczna wyszukiwarka syntezaZadanie i podpowiedzi →