Lip
1
2015

Zabezpieczenie przed SQL Injection

Jakiś czas temu na rozmowie kwalifikacyjnej, która była skutkiem mojej aplikacji na stanowisko PHP Developera rekrutant zapytał mnie o sposoby zabezpieczenia przed SQL Injection. Dzisiaj chciałbym aby ten wpis był w całości poświęcony właśnie zabezpieczeniom przed takim typem ataków na które jesteśmy narażeni (szczególnie na początku naszej przygody z web developmentem). Tym bardziej, że ostatnio rozmawiając z kolegą nt. 2 pytań, które miał na egzaminie Zend PHP Enginner dotyczyło właśnie SQL Injection. Tyle słowem wstępu, na początku podstawy podstaw a więc…

Czym jest w ogóle SQL Injection?

SQL Injection – to sposób ataku na stronę internetową poprzez całkowitą zmianę logiki zapytania SQL na podstawie przesyłanego zapytania (np. poprzez formularz). Prościej rzecz mówiąc, wyobraźmy sobie następujący przykład: posiadamy standardowy formularz logowania na naszej stronie WWW, login i hasło oraz przycisk wysyłający formularz. Użytkownik wpisuje login, a następnie hasło i kliknie zaloguj. Teraz czas na obsługę żądania po stronie serwera (formularz z danymi wysłany) – wkracza do akcji plik .php

Jeśli nie mamy pojęcia co to w ogóle jest SQL Injection to zapewne zapytanie, które programista napisze aby sprawdzić poprawność logowania w/w użytkownika będzie wyglądało następująco

$query = "SELECT * FROM uzytkownicy WHERE pseudonim='$_POST[\'pseudonim\']' AND haslo = '$_POST[\'haslo\']'";

Dalsza obsługa tego żądania wydaję mi się, że nie jest potrzebna do omawiania. Po prostu przypuśćmy, że zmienną $query wykorzystamy do odpytania bazy o usera i zwróci nam 1 w przypadku odnalezienia użytkownika, w innym przypadku wartość 0.

W porządku, wszystko działa tak jak należy, jednak co w przypadku jeśli użytkownik w fomularzu w inpucie hasło umieści następujący ciąg znaków: ‚ OR 1=1 ?

Całe nasze zapytanie legło w gruzach gdyż tak na prawdę nieważne co zostanie wpisane w innych polach warunek będzie sprawdzony i otrzymamy prawo dostępu do bycia zalogowanym, co gorsza, jeśli osoba atakująca takim zapytaniem zna pseudonim admina strony to jesteśmy narażeni na przejęcie konta administratora. Co więcej, jeżeli ktoś wpisze do formularza ciąg znaków zawierający m.in. apostrof, mogą przytrafić się różne błędy – od zwykłego błędu wykonania zapytania SQL, aż po wykasowanie wszystkich danych z bazy danych lub z serwera! Pamiętajmy o tym!

Jak się bronić?

Ktoś kiedyś powiedział, że najlepszą obroną jest atak, w tym przypadku naszym atakiem obronnym będzie po prostu zabezpieczenie się przed możliwością wywołania powyższego niepożądanego zapytania. Istnieją 2 najpopularniejsze metody obrony przed SQL Injection. Przeze mnie najczęściej stosowaną metodą są tzw. zapytania przygotowane

Obsługują je moduły PDO i MySQLi. Ja najczęściej używam wbudowanego adaptera SQL w Zendzie  jest łatwiejszy i oferuje ten sam interfejs do obsługi wielu typów baz danych.

$query = $db->prepare('INSERT INTO moja_tabela (v1,v2) VALUES (:v1, :v2)'); $query->execute(array('v1' => 'wartosc1', 'v2' => 'wartosc2'));

Drugim (chyba najczęściej stosowanym) sposobem jest użycie funkcji mysqli_real_escape_string, polega ona na dodaniu znaków unikowych lewe ukośniki (backslash) do następujących znaków: \x00, \n, \r, \, , ” i \x1a w łańcuchu znaków do użycia w instrukcji SQL. Jeśli nasz kod, który odpowiadałby za wstawianie do bazy danych wartości text wyglądałby tak:

INSERT INTO moja_tabela (text) VALUES ("Jestem dużym "miśkiem"")

wygenerowałoby to koszmarny błąd SQL-owy gdyż nie zrobiliśmy escape’a na wartości wpisywanej. A oto wynik działania w/w funkcji:

mysql_real_escape_string($text)  =>  Jestem dużym \"miśkiem\"

Powiązane wpisy

Autor wpisu:

Jakub Kądzielawa - młodszy programista PHP, student Informatyki, który łączy pracę ze swoją pasją. Czasami narzeka na brak wolnego czasu.

Zostaw komentarz