Żeby korzystać z opisywanego modułu, należy go włączyć do kompilowanej wersji interpretatora PHP:

Podobne dokumenty
E.14 Bazy Danych cz. 18 SQL Funkcje, procedury składowane i wyzwalacze

PHP może zostać rozszerzony o mechanizmy dostępu do różnych baz danych:

Języki programowania wysokiego poziomu. PHP cz.4. Bazy danych

Wykład 5: PHP: praca z bazą danych MySQL

DECLARE VARIABLE zmienna1 typ danych; BEGIN

PHP: bazy danych, SQL, AJAX i JSON

Autor: Joanna Karwowska

6. Bezpieczeństwo przy współpracy z bazami danych

Języki skryptowe - PHP. PHP i bazy danych. Paweł Kasprowski. pawel@kasprowski.pl. vl07

Sprawdzenie czy połączenie przebiegło poprawnie if (mysqli_connect_errno()) { echo Błąd; Połączenie z bazą danych nie powiodło się.

Projektowani Systemów Inf.

Baza danych do przechowywania użytkowników

5. Współpraca z bazą danych MySQL

CREATE USER

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Ćwiczenia laboratoryjne nr 11 Bazy danych i SQL.

Programowanie w SQL procedury i funkcje. UWAGA: Proszę nie zapominać o prefiksowaniu nazw obiektów ciągiem [OLIMP\{nr indeksu}] Funkcje użytkownika

Zakres tematyczny dotyczący kursu PHP i MySQL - Podstawy pracy z dynamicznymi stronami internetowymi

Wydział Elektrotechniki, Informatyki i Telekomunikacji Instytut Informatyki i Elektroniki

Składowane procedury i funkcje

Informatyka I. Standard JDBC Programowanie aplikacji bazodanowych w języku Java

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ),

PRZESTRZENNE BAZY DANYCH WYKŁAD 2

Podstawy programowania III WYKŁAD 2

Po instalacji serwera MYSQL dostępne jest konto o nazwie root. Domyślnie nie ma ono przypisanego hasła, aczkolwiek podczas procesu konfiguracji jest

Informatyka I. Programowanie aplikacji bazodanowych w języku Java. Standard JDBC.

strukturalny język zapytań używany do tworzenia i modyfikowania baz danych oraz do umieszczania i pobierania danych z baz danych

Przykład 3 Zdefiniuj w bazie danych hurtownia_nazwisko przykładową funkcję użytkownika fn_rok;

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

SQL injection. Metody włamań do systemów komputerowych p. 1/13. Bogusław Kluge, Karina Łuksza, Ewa Makosa

Administracja bazami danych

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny Technologiczny Politechnika Śląska

DECLARE <nazwa_zmiennej> typ [(<rozmiar> )] [ NOT NULL ] [ { := DEFAULT } <wartość> ];

Wykład 5. SQL praca z tabelami 2

Wdrożenie modułu płatności eservice. dla systemu Zen Cart

Bezpieczeństwo systemów komputerowych

Relacyjne bazy danych. Podstawy SQL

Wdrożenie modułu płatności eservice. dla systemu oscommerce 2.3.x

Oracle PL/SQL. Paweł Rajba.

Aplikacje WWW - laboratorium

Aplikacje WWW - laboratorium

Budowa aplikacji ASP.NET współpracującej z bazą dany do obsługi przesyłania wiadomości

Przypadki testowe. Spis treści. Plan testów. From Sęp. Wstęp. 2 Plan testów

Aplikacje webowe w obliczu ataków internetowych na przykładzie CodeIgniter Framework

Procedury i funkcje składowane

Bazy danych i strony WWW

Dokumentacja smsapi wersja 1.4

KatMPBSoft - 1 -

Umieszczanie kodu. kod skryptu

SQL (ang. Structured Query Language)

Blaski i cienie wyzwalaczy w relacyjnych bazach danych. Mgr inż. Andrzej Ptasznik

Internetowe bazy danych

INTERNETOWE BAZY DANYCH materiały pomocnicze - wykład VII

Język SQL, zajęcia nr 1

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

1 Moduł Konfigurowanie Modułu

ZAAWANSOWANE BAZY DANYCH I HURTOWNIE DANYCH MySQL, PHP

Sprzeg podstawowy do baz danych w PHP Mateusz Sowa, 2007

Dlaczego PHP? - zalety

Dostęp do baz danych z serwisu www - PHP. Wydział Fizyki i Informatyki Stosowanej Joanna Paszkowska, 4 rok FK

Bazy danych. Wykład IV SQL - wprowadzenie. Copyrights by Arkadiusz Rzucidło 1

TOPIT Załącznik nr 3 Programowanie aplikacji internetowych

Zagadnienia. Konstrukcja bibliotek mysql i mysqli w PHP. Dynamiczne generowanie stron. Połączenie, zapytanie i sesja

Szczegółowy opis zamówienia:

Bazy danych i usługi sieciowe

asix4 Podręcznik użytkownika BAZA - drajwer dostępu do baz danych Podręcznik użytkownika

Relacyjne bazy danych. Podstawy SQL

Wysyłanie pliku na serwer. Plik na serwerze.

PHP i MySQL dla każdego / Marcin Lis. Wyd. 3. Gliwice, cop Spis treści

INFORMATYKA MÓJ SPOSÓB NA POZNANIE I OPISANIE ŚWIATA PROGRAM NAUCZANIA INFORMATYKI Z ELEMENTAMI PRZEDMIOTÓW MATEMATYCZNO-PRZYRODNICZYCH

Sesje, ciasteczka, wyjątki. Ciasteczka w PHP. Zastosowanie cookies. Sprawdzanie obecności ciasteczka

Wprowadzenie. Rozdział 23 PDO. Podstawowe kroki aplikacji. Źródło danych

Dokumentacja interfejsu MySQL. Platforma BSMS.PL Instrukcja podłączenia po przez mysql

1 Kursory 1. 2 Wyjątki Wyjątki predefiniowane Wyjątki niezdefiniowane wcześniej Definiowanie własnych wyjątków...

Trigger jest obiektem związanym z tablicą, który aktywuje się gdy do tablicy następuje odpowiednie zapytanie.

Spis treści. Wstęp 5 Rozdział 1. Praca z AJAX-em 9. Rozdział 2. Współpraca ze skryptami PHP 55. Rozdział 3. Obsługa formularzy 81

PODSTAWY BAZ DANYCH 13. PL/SQL

Lekcja 10. Uprawnienia. Dołączanie plików przy pomocy funkcji include() Sprawdzanie, czy plik istnieje przy pmocy funkcji file_exists()

SZYBKI START. Tworzenie nowego połączenia w celu zaszyfrowania/odszyfrowania danych lub tekstu 2. Szyfrowanie/odszyfrowanie danych 4

WINDOWS Instalacja serwera WWW na systemie Windows XP, 7, 8.

Wykład 6: PHP: praca z bazą danych MySQL, cz.2

Transakcje W poprzednich częściach instrukcje języka SQL traktowane były jak indywidualne operacje (transakcje)

Język PL/SQL Procedury i funkcje składowane

XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Bazy Danych i Usługi Sieciowe

Laboratorium nr 4. Temat: SQL część II. Polecenia DML

Wdrożenie modułu płatności eservice. dla systemu Magento

Technologie Internetowe Raport z wykonanego projektu Temat: Internetowy sklep elektroniczny

Zajęcia 11 wykorzystanie MySQL w PHP

Gerard Frankowski, Zespół Bezpieczeństwa PCSS. Nowoczesne technologie bliżej nas Poznań,

Bazy danych II. Andrzej Grzybowski. Instytut Fizyki, Uniwersytet Śląski

Praca Magisterska "System zdalnego składania ofert kupna i sprzedaży za pośrednictwem Internetu" AUTOR PROMOTOR

Bazy Danych i Usługi Sieciowe

Zmiany funkcjonalne i lista obsłużonych zgłoszeń Comarch DMS , Comarch DMS i Comarch DMS

Budowa aplikacji ASP.NET współpracującej z bazą dany do przeprowadzania ankiet internetowych

Instrukcja składania wniosku o dofinansowanie w systemie informatycznym IP na potrzeby konkursu nr 1/1.1.1/2015

Dokumentacja interfejsu HTTPD. Platforma BSMS.PL Instrukcja podłączenia po przez http

Wprowadzenie do Doctrine ORM

SQL 4 Structured Query Lenguage

Transkrypt:

Ostatni odcinek poświęcony jest wykorzystaniu umiejętności z poziomu języka PHP, zdobytych w ramach kursu. Ponieważ jest to kurs MySQL-a, a nie języka PHP, zawiera on jedynie krótki opis interfejsu API serwera i uwagi na temat bardzo popularnego ataku na bazy danych iniekcji kodu SQL. Dwa interfejsy PHP serwera MySQL MySQL zawiera dwa moduły do współpracy z PHP: 1. Moduł mysql używany w wersjach wcześniejszych niż 4.1 do współpracy z PHP 4 i 5. Jeżeli tylko masz taką możliwość, nie korzystaj z tego przestarzałego modułu. 2. Moduł mysqli (i oznacza ulepszony, ang. Improved) przeznaczony dla wersji 4.1.3 i późniejszych serwera MySQL, umożliwiający współpracę jedynie z wersją PHP 5. To rozszerzenie zostało poniżej krótko przedstawione. Dzięki niemu automatycznie poprawisz wydajność i bezpieczeństwo programu (czyli nic nie zmieniając w kodzie, sprawisz, że program będzie działał szybciej i bezpieczniej). Włączanie modułu mysqli Żeby korzystać z opisywanego modułu, należy go włączyć do kompilowanej wersji interpretatora PHP:./configure --with-mysqli=/usr/bin/mysql_config --with-mysql=/usr A następnie skompilować i zainstalować PHP: make make install Mysqli W ramach tego odcinka przedstawię kilka przykładowych skryptów pokazujących typowe techniki programowego odczytywania i przetwarzania danych. Dokładny opis modułu mysqli, włącznie z przykładami użycia większości metod wszystkich klas tego modułu, znajduje się pod adresem http://pl.php.net/mysqli. Przykład połączenia z bazą danych podejście proceduralne Skrypt z listingu 13.1 pokazuje, jak nawiązać połączenie z bazą danych. Poszczególne listingi nie są samodzielnymi, działającymi programami lecz trzema częściami jednego skryptu, podzielonego na części ze względów edukacyjnych. Żeby go wykonać, należy połączyć je w jeden skrypt. Listing 13.1. Łączymy się z testową bazą. Ze względów bezpieczeństwa połączenie nie jest nawiązywane w kontekście użytkownika root /* Łączymy się z serwerem */ $link = mysqli_connect( 'localhost', /* nazwa komputera, na którym działa MySQL */ 'user', /* nazwa użytkownika */ 1 / 11

'password', /* hasło */ 'test'); /* domyślna baza danych */ if (!$link) { printf("brak połączenia z serwerem MySQL. Kod błędu: %sn", mysqli_connect_error()); exit; Zmienna $link będzie naszym uchwytem do nawiązanego połączenia. Jeżeli połączenie zostanie ustanowione, jej wartością będzie prawda, w przeciwnym razie wartością zmiennej będzie fałsz. Za pomocą warunku IF sprawdzamy, czy udało się połączyć z bazą danych, i jeżeli nie, zwracamy kod błędu i przerywamy działanie skryptu. Po nawiązaniu połączenia możemy wykonywać dowolne instrukcje języka SQL (listing 13.2), a jego wynik wykorzystać w skrypcie. Listing 13.2. Odczytujemy z bazy i wyświetlamy nazwy oraz ceny towarów /* Wykonujemy zapytanie */ if ($result = mysqli_query($link, 'SELECT description, sell_price FROM item ORDER BY sell_price DESC')) { print("lista towarów:n"); /* Przetwarzanie wierszy wyniku zapytania */ while( $row = mysqli_fetch_assoc($result) ){ printf("%s (%s)n", $row['description'], $row['sell_price']); /* Usuwamy z pamięci wynik zapytania */ mysqli_free_result($result); 2 / 11

Zwróć uwagę na kilka kwestii: 1. Zmienna $result zawiera wynik zapytania. 2. Do wykonania zapytania (wywołania procedury mysqli_query) wymagane jest otwarte połączenie z bazą. 3. Przekazana jako parametr wywołania instrukcja języka SQL jest umieszczona w apostrofach i nie jest zakończona średnikiem. 4. Ze względu na prostotę i wydajność sortowaniem danych zajął się MySQL. 5. Zapytanie zwraca tylko potrzebne dane. 6. Wynik zapytania jest zapisywany w postaci tablicy (procedura mysqli_fetch_assoc), której kolejne wiersze będą wyświetlone na ekranie. 7. Po przetworzeniu (np. wypełnieniu tabeli) wynik zapytania jest usuwany, a pamięć zwalniana. Pozostało nam tylko zamknąć aktywne połączenie (listing 13.3). Listing 13.3. Otwieranie połączeń jest dość wolne, dlatego warto raz nawiązać je na początku skryptu i zamknąć na jego końcu /* Zamykamy połączenie z bazą */ mysqli_close($link); Przykład połączenia z bazą danych podejście obiektowe PHP 5 umożliwia tworzenie programów zorientowanych obiektowo, a rozszerzenie mysqli nie jest tu wyjątkiem. Program z listingu 13.4 jest funkcjonalnym odpowiednikiem poprzednich skryptów, ale tym razem nawiązanie połączenia, wykonanie zapytania, przetworzenie wyników i zamknięcie sesji zrealizowane zostało obiektowo. Listing 13.4. Odczytujemy listę towarów i ich cen /* Łączymy się z serwerem */ $mysqli = new mysqli('localhost', 'user', 'password', 'test'); if (mysqli_connect_errno()) { printf("brak połączenia z serwerem MySQL. Kod błędu: %sn", mysqli_connect_error()); exit; 3 / 11

/* Wykonujemy zapytanie */ if ($result = $mysqli->query(select description, sell_price FROM item ORDER BY sell_price ')) { print("lista towarów:n"); /* Przetwarzanie wierszy wyniku zapytania */ while( $row = $result->fetch_assoc() ){ printf("%s (%s)n", $row['description'], $row['sell_price']); /* Usuwamy wynik zapytania z pamięci */ $result->close(); /* Zamykamy połączenie z bazą */ $mysqli->close(); Zwróć uwagę, że: 1. W tym wypadku nie musimy przechowywać uchwytu do połączenia w osobnej zmiennej. 2. Wywołując metodę fetch_assoc(), nie musimy jawnie wskazywać na zmienną zawierającą wynik zapytania. Przykład przekazywania parametrów w instrukcjach SQL W poprzednich przykładach MySQL wykonywał zapisane na trwale w skryptach instrukcje języka SQL. W większości wypadków takie rozwiązanie będzie niefunkcjonalne nie będziemy przecież w stanie zapisać wszystkich możliwych wersji zapytań. Znacznie lepszym pomysłem byłoby użycie w kodzie SQL zmiennych, których wartości byłyby dynamicznie ustawiane z poziomu PHP. Czyli chodzi o to, żeby instrukcje typu SELECT description, sell_price FROM v_drogie WHERE description = 'Speakers' zastąpić instrukcjami typu SELECT description, sell_price 4 / 11

FROM v_drogie WHERE description =? a w miejsce znaku? dynamicznie podstawić odpowiednią wartość przed wykonaniem przez MySQL (listing 13.5). Listing 13.5. Przykład dynamicznego przekazywania parametrów $mysqli = new mysqli('localhost', 'user', 'password', 'test'); /* Test połączenia */ if (mysqli_connect_errno()) { printf("brak połączenia z serwerem MySQL. Kod błędu: %sn", mysqli_connect_error()); exit(); /* Przygotowanie instrukcji SQL*/ $stmt = $mysqli->prepare("insert INTO item (description, sell_price, cost_price) VALUES (?,?,?)"); $stmt->bind_param('sdd', $description, $sell_price, $cost_price); $description = 'SQL Server 2005 Standard'; $sell_price = 1500; $cost_price = 1323.12; /* Wykonujemy przygotowaną instrukcję */ $stmt->execute(); printf("%d Wstawiono wierszy: n", $stmt->affected_rows); /* Usuwamy wynik zapytania z pamięci */ 5 / 11

$stmt->close(); /* Zamykamy połączenie z bazą */ $mysqli->close(); Omówienie: 1. Pierwszy parametr metody bind_param() określa typ wiązanych parametrów. W tym przypadku 'sdd' oznacza, że pierwszy parametr jest ciągiem znaków, a dwa następnie liczbami dziesiętnymi. 2. Przed wykonaniem instrukcji SQL trzeba określić wartości wszystkich parametrów. 3. Odczytując atrybut affected_rows, dowiemy się, ile wierszy zostało zmodyfikowanych w ramach ostatnio wykonywanej instrukcji. Przykład wiązania wyników Zwracane przez zapytania wyniki mogą być wiązane poprzez zmienne PHP z polami tekstowymi, polami wyboru czy polami w tabelach. Listing 13.6 pokazuje przykład takiego powiązania. Listing 13.6. Wiążąc pola z wynikami zapytań, w prosty i elegancki sposób umożliwimy użytkownikom odczytywanie i modyfikowanie powiązanych danych $mysqli = new mysqli("localhost", "user", "password", "test"); if (mysqli_connect_errno()) { printf("brak połączenia z serwerem MySQL. Kod błędu %sn", mysqli_connect_error()); exit(); /* Przygotowanie i wykonanie instrukcji SQL*/ if ($stmt = $mysqli->prepare("select description, sell_price FROM item ORDER BY sell_price DESC LIMIT 5")) { $stmt->execute(); /* Powiązanie zmiennych z wynikiem zapytania */ $stmt->bind_result($col1, $col2); 6 / 11

/* Przetwarzanie wyniku */ while ($stmt->fetch()) { printf("%s %sn", $col1, $col2); /* Usuwamy wynik zapytania z pamięci */ $stmt->close(); /* Zamykamy połączenie z bazą */ $mysqli->close(); Iniekcja SQL Iniekcja SQL ma miejsce wtedy, gdy niesprawdzone dane wejściowe są przekazywane do serwera baz danych. Ponieważ SQL jest językiem interpretowanym, dowolny ciąg znaków będzie zinterpretowany przez serwer baz danych. Jeżeli ten ciąg będzie poprawną instrukcją języka SQL, to zostanie wykonany, w przeciwnym razie serwer zgłosi błąd. Atak Iniekcja SQL pozwala atakującemu na: 1. Poznanie struktury bazy danych jeżeli błędy zgłaszane przez serwer bazy danych będą odesłane do przeglądarki, atakujący zdobędzie informacje o nazwach tabel i kolumn, typie poszczególnych kolumn, istniejących procedurach składowanych i funkcjach itd. 2. Poszerzenie posiadanych uprawnień wpisana przez atakującego instrukcja SQL będzie wykonana w kontekście zabezpieczeń innego, często uprzywilejowanego konta użytkownika. 3. Wykonywanie na bazie danych dowolnych instrukcji SQL jeżeli aplikacja WWW nawiązuje połączenie z bazą w kontekście konta administratora, to każda instrukcja SQL wpisana przez użytkownika i bez sprawdzania wysłana do bazy zostanie wykonana. 4. Wywoływanie procedur składowanych serwery baz danych zawierają procedury składowane, niektóre z nich rozszerzają funkcjonalność serwera (np. wywołują dowolny skrypt powłoki). Atakujący, wywołując te procedury, uzyska uprzywilejowany dostęp do zasobów systemowych. Sesje klienckie Zanim działające po stronie serwera WWW programy będą mogły wykonać jakąkolwiek instrukcję języka SQL, muszą nawiązać sesję z wybraną bazą danych. Wymaga to od nich potwierdzenia własnej tożsamości. W najprostszym przypadku skrypt PHP zawiera pokazany na listingu 13.7 fragment kodu. 7 / 11

Listing 13.7. Przykład, jak nie należy łączyć się z serwerem SQL $mysqli = new mysqli('localhost', 'root', 'password', 'test'); $result = $mysqli->query(select * FROM Pracownicy WHERE login = '" + $Login + "' and haslo = '" + $Haslo +"'"); $result->close(); $mysqli->close(); Kluczowe dla bezpieczeństwa są trzy elementy: 1. Po pierwsze, sesja została nawiązana w kontekście zabezpieczeń uprzywilejowanego użytkownika root, a więc dowolne przesłane w ramach tej sesji instrukcje języka SQL będą wykonane. 2. Po drugie, wykonywana instrukcja języka SQL zawiera apostrofy (w języku SQL ciągi znaków umieszczane są w apostrofach). 3. Po trzecie, instrukcja SQL jest dynamicznie konstruowana przez łączenie wpisanych przez użytkowników ciągów znaków. Iniekcja kodu Zamiast wprowadzić swoją nazwę (zmienna Login), użytkownik przykładowej aplikacji internetowej może zaszyć we wpisywanym ciągu znaków instrukcję języka SQL. Jeżeli rezultatem będzie poprawna instrukcja, to zostanie ona wykonana z uprawnieniami administratora serwera baz danych. Punktem wyjścia naszej analizy będzie instrukcja SELECT wykonana w przypadku niepodania ani nazwy użytkownika, ani hasła: SELECT * FROM Pracownicy WHERE login = '' and haslo = '' Gdyby zamiast nazwy użytkownika w zmiennej Login wpisano ciąg znaków ';drop table dane--, serwer baz danych wykonałby następujące instrukcje: SELECT * FROM Pracownicy WHERE login = '';drop table Dane--' and txthaslo = '' Dzięki apostrofowi wpisane wyrażenie będzie zinterpretowane, a nie potraktowane jako ciąg znaków, a więc instrukcja DROP TABLE Dane (w języku SQL znak końca wiersza jest ignorowany) będzie pomyślnie wykonana. Bez tego apostrofu do serwera baz danych zostałyby wysłane następujące instrukcje: SELECT * FROM Pracownicy WHERE login = 'drop table Dane--' and txthaslo = '' a więc wroga instrukcja byłaby użyta do przeszukania tabeli Pracownicy. Ponieważ wszystkie znaki znajdujące się po prawej stronie znaku komentarza (w języku SQL znakiem komentarza są dwa myślniki) są ignorowane, serwer baz danych wykona poprawną instrukcję DROP TABLE dane, a nie błędną DROP TABLE Dane ' and txthaslo = ''. Znajomość konkretnej wersji języka SQL i umiejętne posługiwanie się apostrofem i myślnikami wystarczą do przeprowadzenia skutecznego ataku na niezabezpieczoną aplikację WWW. Aby na przykład odczytać całą zawartość tabeli bazowej, wystarczy zamiast nazwy użytkownika wpisać ciąg znaków 'or 1=1--. W efekcie zostanie wykonana poniższa instrukcja: 8 / 11

SELECT * FROM Pracownicy WHERE login = ''or 1=1--' and txthaslo = '' Ponieważ wartość jednego z argumentów operatora OR (alternatywy logicznej) będzie prawdą (1=1), wartość drugiego (login = '') nie będzie miała wpływu na wynik całego testu. Obrona Obrona przed iniekcją wrogiego kodu polega na sprawdzaniu poprawności danych wprowadzanych przez użytkowników i filtrowaniu wysyłanych do nich informacji. Oprócz tego standardowym środkiem zaradczym jest łączenie się z bazą danych w kontekście konta o jak najmniejszych uprawnieniach jeżeli użytkownik na przykład miałby jedynie prawo do odczytu danych z określonych widoków i do wywołania kilku procedur, to nawet udana iniekcja SQL nie naruszyłaby bezpieczeństwa aplikacji. Formatowanie danych Jeżeli jest to możliwe, ze względów bezpieczeństwa należy zrezygnować z używania w ciągach znaków znaczników języka SQL, przede wszystkim apostrofów i myślników. Niestety, to proste zabezpieczenie może zostać w równie prosty sposób ominięte jeżeli atakujący zorientuje, się w jaki sposób modyfikowane są wprowadzane przez niego dane, zamiast używać apostrofów, posłuży się funkcją CHAR(). Umożliwi mu to nie tylko dodawanie pojedynczych apostrofów (zamiast apostrofu wystarczy wywołać funkcję CHAR(39)), ale np. wstawienie dowolnych ciągów znaków. Co więcej, formatując dane, możemy niekorzystnie wpłynąć na działanie mechanizmów blokujących niepoprawne dane np. jeżeli po sprawdzeniu, czy wyrażenie nie zawiera zastrzeżonych instrukcji języka SQL, usuniemy z niego apostrofy, atakujący może przekazać następujący ciąg znaków: DRO'P T'ABLE Dane i w ten sposób wyzyskać jeden mechanizm zabezpieczeń do pokonania innego zabezpieczenia. Filtrowanie danych Zamiast usuwać z wprowadzonych danych potencjalnie niebezpieczne znaczniki języka SQL i przesyłać do serwera baz danych tak zmodyfikowane ciągi znaków, należy zablokować przesyłanie niepoprawnych danych. Takie rozwiązanie powinno być wykorzystane we wszystkich aplikacjach internetowych. Jeżeli wymagany będzie zwiększony poziom bezpieczeństwa, należy dodatkowo zezwolić na przetwarzanie wyłącznie poprawnych danych. Poniższa funkcja (listing 13.8) zwraca prawdę, jeżeli w podanym ciągu znaków nie występuje apostrof lub myślnik. W przeciwnym razie funkcja zwraca fałsz. Listing 13.8. Funkcja sprawdzająca poprawność danych i jej wywołanie w skrypcie PHP function testpoprawnosci($tekst) { if (preg_match("/[-']/", $tekst)) return false; // znaleziono wystąpienie myślnika lub apostrofu else return true; // badany ciąg nie zawiera niepożądanych znaków Dodatkowym zabezpieczeniem powinno być ograniczenie maksymalnej długości wprowadzanego ciągu znaków. Chociaż ta technika nie uniemożliwi przeprowadzenia skutecznego ataku, to może go znacznie skomplikować 9 / 11

(listing 13.9). Listing 13.9. Ograniczając rozmiar danych, utrudnimy przeprowadzenie ataku if (strlen($login) <= 15) { // kod budujący instrukcje języka SQL else { // przekierowanie do strony z komunikatem błędu Najbezpieczniejsze rozwiązanie wymaga zdefiniowania wzorca poprawnych danych albo przygotowania listy wszystkich możliwych poprawnych wartości. Z oczywistych względów lista ta nie powinna być przechowywana w tabeli po stronie serwera baz danych, tylko np. w dokumencie XML zapisanym na serwerze WWW. Przechwytywanie komunikatów błędów Zgłaszane przez serwery baz danych wewnętrzne komunikaty błędów są z reguły bardzo dokładne zdecydowanie zbyt dokładne, żeby pokazywać je końcowym użytkownikom. Przeciętny użytkownik i tak nie będzie wiedział, czego one dotyczą, za to atakujący na ich podstawie może poznać strukturę bazy i przechowywane w bazie dane. Wszystkie wyjątki muszą zostać przechwycone przez aplikację WWW, informacje o błędzie (w tym oryginalny komunikat błędu) powinny być zapisane w pliku dziennika, a użytkownicy przekierowani na stronę zawierającą ogólną informację o tym, że wystąpił błąd. Funkcje i procedury składowane Sprawdzanie, czy wprowadzone przez użytkowników dane nie zawierają instrukcji języka SQL, jest czasochłonne i chociaż język SQL składa się zaledwie z dziewięciu podstawowych instrukcji nie gwarantuje stuprocentowego bezpieczeństwa. Prostszym i skuteczniejszym rozwiązaniem jest zrezygnowanie z dynamicznego budowania instrukcji języka SQL z wykorzystaniem danych wprowadzonych przez użytkowników. Zamiast tego wprowadzane przez użytkowników dane powinny być przekazywane do serwera bazodanowego jako parametry wywołania procedur. Na przykład zamiast sprawdzać, czy użytkownik, wykonując poniższą instrukcję, podał poprawny login i hasło: $query = "SELECT COUNT(*) FROM pracownicy WHERE login = '" + $Login + "' and haslo = '" + $Haslo +"'" należy utworzyć funkcję wywoływaną z dwoma parametrami (loginem i hasłem), zwracającą liczbę wierszy spełniających podany warunek (listing 13.10). Listing 13.10. Skrypty PHP powinny jedynie wywoływać funkcje lub procedury. W ten sposób wielokrotnie zmniejszymy ryzyko udanego ataku CREATE FUNCTION logowanie (p1 varchar(50), p2 varchar(50)) 10 / 11

RETURNS tinyint RETURN (SELECT COUNT(*) FROM pracownicy WHERE login = p1 AND haslo = p2); Od teraz zapisany w skrypcie PHP kod SQL jedynie wywołuje funkcje i nie jest dynamicznie konstruowany (i nie ma możliwości zaszycia w nim wrogiej instrukcji SQL): $query = "SELECT logowanie ($Login, $Haslo)"; Ograniczenie uprawnień Niekorzystanie z rozbudowanych modeli zabezpieczeń baz danych jest niestosowaniem się do podstawowej strategii minimalizacji ryzyka wyzyskania istniejącej technologii do zabezpieczenia aplikacji. Tematem książki nie jest administrowanie bazami danych, ani ich programowanie, dlatego ograniczę się do odesłania Czytelnika do poświęconych tym zagadnieniom pozycji czas przeznaczony na poznanie używanego serwera baz danych z pewnością zwróci się z nawiązką. 11 / 11