SQL Injection/Insertion, Jak zapobiec włamaniu na stronę. |
SQL Injection/Insertion, Jak zapobiec włamaniu na stronę. |
24.11.2004, 23:13:57
Post
#1
|
|
Grupa: Zarejestrowani Postów: 190 Pomógł: 0 Dołączył: 12.02.2004 Skąd: Poznań Ostrzeżenie: (0%) |
Pytania o streszczenie wątku, posty z "genialnymi" skryptami nadającymi się tylko na przedszkole i inne tego typu, będą bez ostrzeżenia usuwane przez moderatorów.
To mówiłem ja, Jarząbek... znaczy nospor dnia 2007-12-10 ------------------------------------------------------------------------------- SQL Injection (zwane też "SQL Insertion") to (rzekomo) najprostszy sposób włamu na stronę. Spowodowany jest on niepełnym sformułowaniem zapytań do MySQL. Przykład. Dajemy na stronie możliwość edycji profilu. Zapytanie do SQL wygląda następująco:
Osoba włamująca się na stronę umieszcza całkiem prosty, odpowiedni ciąg znaków/poleceń w dowolnym polu edycji tego profilu, który wygląda np. tak (dla zmiany hasła użytkownika o dowolnie wybranym, przez atakującego numerze ID):
W taki oto prosty sposób, osoba atakująca zmieniła hasło użytkownikowi o ID=1 (zazwyczaj administrator). W podobny sposób można również wyciągnąć dowolne dane z tabeli SQL. W każdym razie. Poszperałem, pomyślałem i zebrałem wszystko do kupy. Zamieszczam to tutaj razem, oraz proszę o rozbudowanie tego topica, gdyż nie znalazłem na tym forum więcej informacji o "SQL Injection". Oto co możemy dokonać: 1. Możemy sformułować nasze zapytanie do SQL tak:
2. Przy wstawianiu numerów ID do zapytań należy stosować tzw. rzutowanie typów:
3. Przy wstawianiu tekstów, należy wyciąć niebezpieczne znaki przy pomocy funkcji:
Może nie ma tego dużo, ale jest to już jakaś podstawa do zabezpieczenia strony/skryptu przed prostym i niezwykle niebezpiecznym, SQL Injection. Proszę osoby obeznane w tym temacie, aby dopisały tu własne propozycje metod zabezpieczenia się przed tym atakiem. Ten post edytował Najki 14.02.2008, 10:04:12 -------------------- |
|
|
24.11.2004, 23:34:40
Post
#2
|
|
Grupa: Zarejestrowani Postów: 657 Pomógł: 2 Dołączył: 15.08.2003 Skąd: Łódź Ostrzeżenie: (0%) |
Cytat(Najki @ 2004-11-25 00:13:57) Oto co możemy dokonać: 1. Możemy sformułować nasze zapytanie do SQL tak:
2. Numer ID warto ustawiać w sposób $_GET['id'], lub $_POST['id'], można też ustawić go w nast. sposób:
Może nie ma tego dużo, ale jest to już jakaś podstawa do zabezpieczenia strony/skryptu przed prostym i niezwykle niebezpiecznym, SQL Injection. Proszę osoby obeznane w tym temacie, aby dopisały tu własne propozycje metod zabezpieczenia się przed tym atakiem. punkt 1. twojego "zabezpieczenia" nie ma nic do rzeczy z rzeczywistym bezpieczeństwem przynajmniej wg mnie punkt 2. ja stosuje po prostu addslashes() i filtruje dane z POST GET COOKIE itd. tzn jak ma byc liczba do liczba a nie string stosujac gotowe skrypty ala phpbb itd. dopisuje zawsze w jakims glownym pliku usuwanie s url-a wystapien wyrazow "<script>" i "UNION" co zabezpiecza przez script kiddie -------------------- |
|
|
25.11.2004, 00:06:02
Post
#3
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) |
Z tego co wiem to mysql nie wykonuje zapytan typu "zapyta1;zapyt2" od sstrony php wiec tego nei masz sie co bac... co do filtrowania danych...
mysql_escape_string" title="Zobacz w manualu PHP" target="_manual |
|
|
25.11.2004, 00:22:22
Post
#4
|
|
Grupa: Zarejestrowani Postów: 190 Pomógł: 0 Dołączył: 12.02.2004 Skąd: Poznań Ostrzeżenie: (0%) |
Cytat(Vengeance @ 2004-11-25 00:34:40) punkt 1. twojego "zabezpieczenia" nie ma nic do rzeczy z rzeczywistym bezpieczeństwem przynajmniej wg mnie Gdzieś znalazłem informację, że niby jednak to ma pomóc (głównie chodzi o średnik tam też o średnik na końcu zapytania) Cytat(Vengeance @ 2004-11-25 00:34:40) punkt 2. ja stosuje po prostu addslashes() i filtruje dane z POST GET COOKIE itd. tzn jak ma byc liczba do liczba a nie string Czy czasem $_POST, $_GET i $_COOKIE nie mają automatycznie dodawanych slash'y ? Cytat(Vengeance @ 2004-11-25 00:34:40) stosujac gotowe skrypty ala phpbb itd. dopisuje zawsze w jakims glownym pliku usuwanie s url-a wystapien wyrazow "<script>" i "UNION" co zabezpiecza przez script kiddie Tak będzie OK? (nie znam się na wyrażeniach regularnych, a chciałbym, aby w tym topicu wszystko było jasno opisane, co by nikt problemów nie miał)
-------------------- |
|
|
25.11.2004, 08:48:38
Post
#5
|
|
Grupa: Zarejestrowani Postów: 560 Pomógł: 0 Dołączył: 15.07.2003 Skąd: Kwidzyn Ostrzeżenie: (0%) |
zabezpieczenie w stylu:
to jak juz powiedziano zadne zabezpieczenie a pozatym zmnijsza wydajnosc zapytania, umieszczanie wartosci liczbowych w momiedzy " " powiduje iz MySQL mysli ze ma do czynienia ze znakami (stringami) i niepotzrebnie musi konwertowac typy. Przylacze sie do tego co juz powiedziano, uzywac Zmiennych globalnych, i filtrowac wszystko, to co ma byc liczba to konwertowac na liczbe np: a to co ma byc stringiem dodawac slashe (addslashes). Podstawowa zasada to nie ufac nikomu i spodziewac sie najgorszego! budowac aplikacje tak by wytrzymaly wybuch nuklearny w jednym ze swoich projektw zrobilem petle na foreach ktora z kazdego elemenu tablicy ($_GET, $_POST, $_COOKIE) zamieniala ewentualn wystapienia wyrazen takich jak "SELECT, UPDATE, INSERT, DELETE, WHERE AND" dodajac do nich np twarda spacje lub jakis inny znak co powodowalo ze ew. zapytanie bylo by z gory obarczone bledem. coprawda rozwiazanie takie nie jest eleganckie bo wszystkie wystapienia tych wyrazeni byly zamieniane nawet jesli ktos nie mial zlych intencji ale sa one bardzo zadko uzywane w naszym slownictwie a dodanie np. twardej spacji praktycznie niczego nie zmienia w wygladzie takiego komentarza, posta etc. -------------------- |
|
|
6.12.2004, 09:23:12
Post
#6
|
|
Grupa: Zarejestrowani Postów: 90 Pomógł: 2 Dołączył: 3.12.2004 Ostrzeżenie: (0%) |
Cytat(Kinool @ 2004-11-25 07:48:38) to co ma byc stringiem dodawac slashe (addslashes) nie rozumiem dlaczego wszyscy piszą o addslashes, przecież php automatycznie dodaje slashe do wszystkich zmiennych $_GET i $_POST i włamanie opisane przez Najki
nie ma prawa zadziałać. Czy mógłby ktoś wyjaśnić mi tą sytuację? |
|
|
6.12.2004, 09:29:56
Post
#7
|
|
Grupa: Zarejestrowani Postów: 190 Pomógł: 0 Dołączył: 12.02.2004 Skąd: Poznań Ostrzeżenie: (0%) |
Owszem dodaje, ale chyba tylko, gdy na serwerze jest włączone magic_quotes_gpc ?
A jeśli nie to jakim prawem kolega mi się włamał? -------------------- |
|
|
6.12.2004, 12:32:14
Post
#8
|
|
Grupa: Przyjaciele php.pl Postów: 2 335 Pomógł: 6 Dołączył: 7.03.2002 Ostrzeżenie: (0%) |
Dodam jeszcze te dwa linki:
http://www.nextgenss.com/papers/SecondOrderCodeInjection.pdf http://hacking.pl/download.php?file=get&id=113 |
|
|
26.02.2005, 17:20:37
Post
#9
|
|
Grupa: Zarejestrowani Postów: 117 Pomógł: 0 Dołączył: 24.05.2004 Skąd: krakow Ostrzeżenie: (10%) |
Temat ciekawy, ale w zasadzie nie wiem jeszcze co moglbym zrobic w swojej aplikacji aby uniemozliwic taki atak i aby bylo to zrobione w profesjonalny sposob. Gdyby ktos mogl zerknac na kod i pomoc mi.
Oto kod ktory sluzy do sprawdzenia hasla i nazwy usera:
a to kod funkcji wykonujacej to sprawdzenie:
Chcialbym uniknac mozliwosci wlamania, poprzez wpisanie kodu SQL do pola haslo i uzytkownik:) -------------------- |
|
|
26.02.2005, 21:45:06
Post
#10
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) |
przyklad:
wywołanie normalne: Kod news.php?id=1 news.php?id=25 itd wywołanie zmodyfikowane przez kogostam np. Kod news.php?id=1;DROP%20TABLE%20news; zabezpieczenie? ja znalazlem pare... 1. dodanie id2
2. wymuszenie typu
3. mysql_escape_string
ale mam wrazenie ze to dalej nie o to biega... z tych 3 które przedstawilem to pierwsze wydaje mi sie być najrozsądniejsze... |
|
|
26.02.2005, 23:41:07
Post
#11
|
|
Grupa: Zarejestrowani Postów: 853 Pomógł: 25 Dołączył: 27.08.2003 Skąd: Katowice Ostrzeżenie: (0%) |
Cytat(ActivePlayer @ 2005-02-26 21:45:06) ale mam wrazenie ze to dalej nie o to biega... z tych 3 które przedstawilem to pierwsze wydaje mi sie być najrozsądniejsze... osobiscie uwazam ze dosc dobrym rozwiazaniem jest odpowiednie zarządzanie uprawnieniami, np. stworzyc konto dla www, gdzie moga byc tylko SELECT, INSERT, UPDATE, ewentualnei DELETE druga sprawa, czy probowales w praktyce wykonac przedstawione przez ciebie polecenie? standardowo (nie jestem pewny czy da sie to przestawic tak zeby bylo inaczej) przez mysql_querynie wykonasz dwóch zapytań -------------------- "If debugging is the process of removing bugs, then programming must be the process of putting them in..."
sobstel.org |
|
|
27.02.2005, 14:44:07
Post
#12
|
|
Grupa: Zarejestrowani Postów: 657 Pomógł: 2 Dołączył: 15.08.2003 Skąd: Łódź Ostrzeżenie: (0%) |
przez mysql_query() nie. ale funckje postgreSQL już to dopuszczają :/
Dlatego userzy tego drugiego mają większy problem. Co do zabezpieczenia, nie wiem czym się tak przejmujecie? ;] Ja stosuje jedynie addslashes() oraz usuwam slowo 'UNION' ze zmiennych -------------------- |
|
|
27.02.2005, 14:49:14
Post
#13
|
|
Grupa: Zarejestrowani Postów: 640 Pomógł: 44 Dołączył: 8.02.2004 Ostrzeżenie: (0%) |
dość często jest WHERE coś = liczba gdzie coś jest polem auto_increment i ma wartości liczbowe.. wystarczy przed wykonaniem zapytania sprawdzić czy is_numeric parametr dla Where
-------------------- |
|
|
27.02.2005, 17:45:48
Post
#14
|
|
Grupa: Zarejestrowani Postów: 193 Pomógł: 0 Dołączył: 14.09.2003 Skąd: Brodnica (koło Torunia) Ostrzeżenie: (0%) |
Ja do liczb stosuje najczęściej ereg" title="Zobacz w manualu PHP" target="_manual (zwłaszcza w UPDATE, w grze MMORPG). Wtedy mam pewność że osoba która wpisze np -1230 nie wyrządzi mi żadnych szkód. A zabezpieczanie skryptów można trenować na wspomnianym przeze mnie wyżej ExoFusion. Jak ktoś go tak zabezpieczy, że nie będzie żadnych (no, może nie żadnych, a prawie żadnych) błędów to będzie się miał czym pochwalić (ja znałem 2 gry na 10 które były w miarę zabezpieczone, ale i tak padły - właśnie przez SQL Injection)
-------------------- |
|
|
28.02.2005, 03:21:48
Post
#15
|
|
Grupa: Zarejestrowani Postów: 71 Pomógł: 1 Dołączył: 3.10.2004 Ostrzeżenie: (0%) |
Cytat Ja do liczb stosuje najczęściej ereg (zwłaszcza w UPDATE, w grze MMORPG). Wtedy mam pewność że osoba która wpisze np -1230 nie wyrządzi mi żadnych szkód. A zabezpieczanie skryptów można trenować na wspomnianym przeze mnie wyżej ExoFusion. Jak ktoś go tak zabezpieczy, że nie będzie żadnych (no, może nie żadnych, a prawie żadnych) błędów to będzie się miał czym pochwalić (ja znałem 2 gry na 10 które były w miarę zabezpieczone, ale i tak padły - właśnie przez SQL Injection) Hmmm.... wykonanie ereg zajmuje nieco czasu (jak to wyrażeń regularnych). Chyba jednak lepiej się nieco przyłożyć i pobawić kombinacją is_numeric(), is_integer(), intval() i warunkami. Chyba każdy wie jakiego mniej więcej zakresu się spodziewa? Jak nie chcesz liczb ujemnych to po porostu wycinasz je warunkiem i już… Po co z armatą na muchy;-) Pozdrawiam Marcin Staniszczak |
|
|
1.03.2005, 17:20:41
Post
#16
|
|
Grupa: Zarejestrowani Postów: 657 Pomógł: 2 Dołączył: 15.08.2003 Skąd: Łódź Ostrzeżenie: (0%) |
@MStaniszczak: podobnież "is_numeric(), is_integer(), intval()" nie są zawsze dobrym wyjściem. Gdzieś czytałem, iż Zend Engine działa tak, iż te funkcje sprawdzają tylko typ zmiennej. Może to doprowadzać do przekłamań, dlatego niektórzy właśnie stosują eregi (co w tamtym artykule także polecano).
-------------------- |
|
|
1.03.2005, 23:15:12
Post
#17
|
|
Grupa: Zarejestrowani Postów: 71 Pomógł: 1 Dołączył: 3.10.2004 Ostrzeżenie: (0%) |
@Vengeance:
Więc działa to tak: is_numeric() - sprawdza czy cos co podałeś jako argument jest cyfrą. Dokładniej czy nie ważne czy cyfra jest stringiem ('123') czy cyfrą (123) czy cyfrą ułamkową (123.123). Jeśli jest cyfrą zwraca true; is_integer() - zwraca true TYLKO wtedy gdy parametr: a) jest cyfra b) jest typu integer (czyli dla '123' nie zwróci true) c) jest cyfrą CAŁKOWITĄ (czyli dla 123.123 nei zwróci true). WSZYSTKIE te punkty muszą być spełnione jednocześnie intval() - nic nie sprawdza... Zamienia parametr na integera (jesli zaczyna się od cyfry). Czyli:
powoduje przepisanie do $i wartości 123 typu INTEGER.
działa podobnie - w $i otrzymujemy INTEGER-a o wartości 123. Dodatkowo intval() ignoruje początkowe białe znaki i oczywiście poprawnie obsługuję znaki +/- przed cyfrą. W przypadku niepoprawnego parametru podanego do intval:
zwraca 0 (czyli w przykładzie $i otrzymuje wartość 0). I NIE MA ODSTPSTW OD TYCH REGÓŁ. Zamieszanie może powstać gdy się nie wie jak te funkcje działają (jest ich więcej - to tylko 3 z całej grupy). Ale to tak jak z operatorami... Zobacz co da w wyniku:
Pozdrawiam Marcin Staniszczak Ten post edytował MStaniszczak 2.03.2005, 03:09:57 |
|
|
2.03.2005, 22:22:51
Post
#18
|
|
Grupa: Zarejestrowani Postów: 657 Pomógł: 2 Dołączył: 15.08.2003 Skąd: Łódź Ostrzeżenie: (0%) |
@MStaniszczak: ja tam nie wiem Mówie tylko co czytałem. Skoro ktoś to dostrzegł w kodzie Zend Engine (może go analizowałeś, ja nie) to miał jakieś powody by tak twierdzić Może już to poprawili albo coś. Przytaczam tylko swoją "wiedzę" na ten temat, choc sam także używam is_integer() itp.
-------------------- |
|
|
2.03.2005, 22:43:20
Post
#19
|
|
Grupa: Zarejestrowani Postów: 71 Pomógł: 1 Dołączył: 3.10.2004 Ostrzeżenie: (0%) |
@Vengeance: Ano analizowałem Zend Engina dość dokładnie (jeszcze raz mnie to czeka).
Oto funkcja odpowiedzialna za is_numeric (która nie jest częścią Zend Engine-u): Kod PHP_FUNCTION(is_numeric) { zval **arg; int result; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) { WRONG_PARAM_COUNT; } switch (Z_TYPE_PP(arg)) { case IS_LONG: case IS_DOUBLE: RETURN_TRUE; break; case IS_STRING: result = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), NULL, NULL, 0); if (result == IS_LONG || result == IS_DOUBLE) { RETURN_TRUE; } else { RETURN_FALSE; } break; default: RETURN_FALSE; break; } } A to np. is_string: Kod PHP_FUNCTION(is_string) { php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING); } do tego php_is_type: Kod static void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) { pval **arg; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only one argument expected"); RETURN_FALSE; } if (Z_TYPE_PP(arg) == type) { if (type == IS_OBJECT) { zend_class_entry *ce; ce = Z_OBJCE_PP(arg); if (!strcmp(ce->name, INCOMPLETE_CLASS)) { RETURN_FALSE; } } if (type == IS_RESOURCE) { char *type_name; type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC); if (!type_name) { RETURN_FALSE; } } RETURN_TRUE; } else { RETURN_FALSE; } } A is_integer, is_double, is_real ma jeszcze ładniejszą postać (sam sprawdź). To nie może działać źle - używaj bez obaw;-) Pozdrawiam Marcin Staniszczak |
|
|
3.03.2005, 17:09:35
Post
#20
|
|
Grupa: Zarejestrowani Postów: 47 Pomógł: 0 Dołączył: 25.01.2004 Skąd: Świętochłowice Ostrzeżenie: (0%) |
W PHPBB też jest coś takiego używane, ale - znowu - nie prościej użyć rzutowania typów? Ostatnio zrobiłem coś takiego na zmiennej $id z GET'a i nawet jeśli dałem id=3fk5 to jeśli zrzutowałem to na (int) otrzymywałem 35. Chyba o to wam chodzi, nie?
-------------------- “Twój czas jest ograniczony, więc nie marnuj go żyjąc tak jak inni. Nie daj się znaleźć w potrzasku przez dogmaty, którymi żyją. Nie ulegaj opiniom, które zagłuszą twój wewnętrzny głos. I najważniejsze, miej odwagę pójść za twoim sercem i intuicją. Wszystko inne jest mniej ważne.”
Steve Jobs |
|
|
Wersja Lo-Fi | Aktualny czas: 21.09.2024 - 03:48 |