Jak zabezpieczyćzęnych przed włamaniem za pomocą dopisania fragmentu kodu w formularzu


[MySQL][PHP] Jak zabezpieczyć bazę danych przed włamaniem za pomocą dopisania fragmentu kodu w formularzu?

0x01 graphic

Chcesz stworzyć bezpieczne połączenie z dowolną bazą danych, aby uniknąć ataku na serwer, przejęcia lub zniszczenia danych z bazy.

0x01 graphic

Niewiele osób zdaje sobie sprawę, jak łatwo można oszukać wiele skryptów i formularzy, które odwołują się do baz danych. Źle napisane procedury do odczytu rekordów, autoryzacji czy wybierania danych są wystarczającym narzędziem, dzięki któremu można wykraść dane, a także wykonać polecenia umożliwiające w skrajnych przypadkach przejęcie kontroli nad bazą danych lub nawet całym serwerem.

Większość osób korzysta z baz danych nieświadomie, nie wie więc, że pewna konstrukacja zapytań może powodować bardzo poważne szkody. Zobacz jak wygląda atak na bazę danych i jak można zabezpieczyć się przed takimi włamaniami.

Załóżmy sobie przykładową bazę danych. Niech zawiera dwa pola - imię i nazwisko. Wpiszmy też kilka rekordów...

imie nazwisko

Jan1 Kowalski1

Jan2 Kowalski2

Jan3 Kowalski3

Jan4 Kowalski4

Jan5 Kowalski5

Zamiast imienia i nazwiska może to być hasło i login oczywiście. Mamy też formularz, który umożliwia wpisanie imienia. Po wpisaniu prawidłowego imienia zobaczymy odpowiadające mu nazwisko. Przykład prosty, ale czytelny. Sprawdźmy jak można odczytać wszystkie imiona i nazwiska bez znajomości imion. Po prostu dokonamy "włamania"...

Jak się włamać?

W PHP zapytanie może wyglądać w poniższy sposób, gdzie zmienna $pole1 zawiera wartość wpisaną do formularza.

<?

$sql="SELECT * FROM ludzie where imie='$pole1'";

?>

Zamiast budować formularz, możemy od razu wywołać stronę zawierającą wartość tego pola poprzez przekazanie parametru z wartością:

http://strona.com/index.php?pole1=jan1

Wynik jest prosty do przewidzenia:

<?

$sql="SELECT * FROM ludzie where imie='jan1'";

?>

czyli pojawi się nam jeden rekord:

Jan1 Kowalski1

Jeżeli będziemy wpisywać inne imiona niż są podane w bazie danych nie zobaczymy żadnych rekordów. Wystarczy jednak zmodyfikować nieco zapytanie, aby zobaczyć zawartość całej bazy! Tym razem zamiast imienia napiszmy w zapytaniu/formularzu coś takiego:

' or 1=1 --'

lub coś takiego:

' or 1=1 #

a więc pytanie będzie wyglądać tak:

index.php?pole1='%20or%201=1%23

Wygląda niewinnie (%20 to spacje, %23 to #), ale w zapytaniu SQL przybierze taką postać:

<?

$sql="SELECT * FROM ludzie where imie='' or 1=1 #';

?>

A to nie jest już niewinne zapytanie, ponieważ wybierze z bazy (a może nawet wyświetli na ekranie) wszystkie rekordy...

Dodatkowy kod działa bardzo prosto - zamyka cudzysłów dla pola imie, dodaje warunek logiczny or 1=1, który zawsze jest spełniony, więc baza danych zwraca wszystkie rekordy, a na końcu za pomocą znaku # traktuje dalsze pytanie jako komentarz i ignoruje zamknięcie średnika. W innych bazach komentarzem może być np. -- (dwa średniki).

Oczywiście atak nie jest możliwy na każdą bazę danych i w każdych warunkach. PHP automatycznie dodaje do każdego cudzysłowu poprzedzający go slash \, więc jest on niegroźny i traktowany jako tekst.

Jeżeli jednak korzystasz z różnych funkcji zmieniających zawartość pola i usuwających slashe, chociażby wykorzystując stripslashes(), Twoja baza stoi przed poważnym zagrożeniem.

Ze względów bezpieczeństwa nie pokażę jak można przejąć kontrolę nad bazą danych, a w skrajnie niekorzystnych przypadkach jest to możliwe. Odczytując zawartość baz danych w łatwy sposób można poznać hasła, dane teleadresowe firm, numery kart kredytowych czy inne informacje, które nie powinny być dostępne dla zwykłego użytkownika. W efekcie niewinny błąd może spowodować bardzo poważne konsekwencje i ogromne straty.

Jak się bronić?

Opisany atak jest groźny tylko wtedy gdy usuwamy slashe, więc przed wysłaniem zapytania do bazy danych należy znowu dodać ukośniki przed cydzysłowami za pomocą funkcji addslashes():

<?

$pole1 = addslashes($pole1);

?>

Przede wszystkim pytania należy przetestować. A więc wyświetlić na ekranie, jak będzie wyglądało zapytanie w ostatecznej formie i jakie dane zwróci baza. Oczywiście test polega na wpisaniu innych niż spodziewane parametry, aby przekonać się czy baza jest odporna chociażby na podane kombinacje znaków:

' or 1=1 #

" or 1=1 #

or 1=1 #

' or 1=1 --

" or 1=1 --

" or 1=1 --"

or 1=1 --

' or 'a'='a

" or "a"="a

') or ('a'='a

Kolejną sprawą jest sprawdzenie typów danych. Jeżeli oczekujesz np. cyfr, a ktoś wpisuje litery, nie powinno zostać wykonane zapytanie SQL. Podobnie gdy ktoś wpisuje liczby, a oczekujesz danych tekstowych (bez liczb).

<?

$dane=$_GET["pole1"];

if (ereg("^-?[0-9][0-9]*(\.[0-9])?[0-9]*$",$dane)) echo "To jest liczba!";

else echo "To nie jest liczba!";

?>

Powyższe wyrażenie rozróżnia liczby całkowite i rzeczywiste, również ze znakiem minus.

W prosty sposób można pobrane z formularza wartości przekonwertować do określonego typu za pomocą rzutowania typów, np. dla integer będzie to (int).

<?

$liczba = (int) $_GET["pole1"]; // pole1 = "123de5"

echo $liczba; // wynik: 123

$liczba = (int) $_GET["pole1"]; // pole1 = "1235"

echo $liczba; // wynik: 1235

$liczba = (int) $_GET["pole1"]; // pole1 = "123.91"

echo $liczba; // wynik: 123

?>

Łatwo można sie też upewnić, czy dana jest określonego typu, przykładem również niech będzie liczba typu integer.

<?

$liczba=1223.17;

if (is_int($liczba)) echo "To jest liczba typu integer";

else echo "To nie jest liczba typu integer!";

?>

Jeżeli to możliwe, niech w pytaniu SQL nie znajdują sie parametry wprowadzane z formularzy. Możesz odseparować pytanie od danych z formularza za pomocą instrukcji warunkowych (oczywiście, jeżeli kombinacji nie jest wiele):

<?

if ($pole1=="czerwony") $sql="SELECT * FROM auta where kolor='czerwony'";

if ($pole1=="czarny") $sql="SELECT * FROM auta where kolor='czarny'";

?>

Możesz też kasować z zapytań SQL następujące ciągi znaków:

'

"

;

#

--

select

drop

insert

delete

Taka ochrona powinna dać Ci poczucie bezpieczeństwa i uodpornić bazę danych na opisaną formę ataku.



Wyszukiwarka

Podobne podstrony:
Jak ustrzec się przed nierzetelnością Klienta za usługi hotelowe, Hotelarstwo, Hotel
Jak zabezpieczyć się przed przesiąkaniem gruntu
Jak zabezpieczyć bitumiczne pokrycia dachowe przed degradacją, Budownictwo1
Jak zabezpieczyć się przed wielokrotnym wykonywaniem kodu po odświeżeniu strony, PHP Skrypty
Jak zabezpieczyć własne strony przed pobieraniem ich programami do ściągania całych witryn, PHP Skry
Badanie uk�ad�w zabezpiecze� przed przeciazeniem(1)
PANSTWO I JEDNOSTKA W PERSPEKTYWIE FILOZOFICZNO-HISTORYCZNEJ, _Pa?stwo- to poj?cie nieod??cznie zwi?
Jak zabezpieczyć swój komputer przed wirusami
2010 05 Jak się zabezpieczyć przed utratą danych
Jak zabezpieczyc się przed niebezpieczeństwem w czasie OOBE
Jak zabezpieczyć dane przed kopiowaniem na pendrive
Jak zabezpieczyć sprzęt przed deszczem
Instrumenty zabezpieczajace przed ryzykiem w warunkach kryzysu ryzyko kursowe i opcje walutowe
21 Wykonywanie zabezpieczeń przed korozją biologiczną i działaniem ognia
Pracownicze ubezpieczenia grupowe jako forma zabezpieczenia przed utratą wartości kapitału ludzkiego
05 5 Weksel jako zabezpieczenie umowy o odpowiedzialności materialnej za powierzone mienie

więcej podobnych podstron