Rozumiem, że NIGDY nie należy ufać wprowadzaniu danych przez użytkownika z formularza, głównie ze względu na możliwość wstrzyknięcia SQL.
Czy dotyczy to jednak również formularza, w którym jedyne dane wejściowe pochodzą z listy rozwijanej (patrz poniżej)?
Zapisuję $_POST['size']
do sesji, która jest następnie używana w całej witrynie do wykonywania zapytań w różnych bazach danych (z rozszerzeniemmysqli
zapytania Select), a każdy zastrzyk SQL na pewno je zaszkodzi (prawdopodobnie upuści).
Nie ma obszaru do wprowadzania danych wejściowych przez użytkownika w celu przeszukiwania baz danych, tylko menu rozwijane.
<form action="welcome.php" method="post">
<select name="size">
<option value="All">Select Size</option>
<option value="Large">Large</option>
<option value="Medium">Medium</option>
<option value="Small">Small</option>
</select>
<input type="submit">
</form>
php
mysql
mysqli
sql-injection
Łachmany
źródło
źródło
<select>
danych wejściowych. Rzeczywiście, nawet mało techniczny użytkownik mógłby dodać dodatkowe opcje za pomocą konsoli przeglądarki. jeśli utrzymasz tablicę z białą listą dostępnych wartości i porównasz z nią dane wejściowe, możesz to złagodzić (i powinieneś, ponieważ zapobiega to niechcianym wartościom)Odpowiedzi:
Możesz zrobić coś tak prostego, jak poniższy przykład, aby upewnić się, że opublikowany rozmiar jest zgodny z oczekiwaniami.
Następnie użyj mysqli_ *, jeśli używasz wersji php> = 5.3.0, którą powinieneś być, aby zapisać wynik. Jeśli zostanie użyty poprawnie, pomoże to w iniekcji sql.
źródło
mysqli_real_escape_string
. Również poprawnie zmieniaj znaczenie wartości podczas ich wyprowadzania (np. Użyj htmlspecialchars () w dokumencie HTML).in_array
celutrue
ścisłego porównania. Nie jestem pewien, co mogło pójść nie tak, ale luźne porównanie jest dość dziwaczne.Tak, musisz się przed tym chronić.
Pozwólcie, że pokażę wam dlaczego, używając konsoli programisty Firefoksa:
Jeśli nie wyczyścisz tych danych, Twoja baza danych zostanie zniszczona. (Może to nie być w pełni poprawna instrukcja SQL, ale mam nadzieję, że udało mi się zrozumieć).
To, że ograniczyłeś opcje dostępne w menu , nie oznacza , że ograniczyłeś dane, które mogę wysłać do twojego serwera.
Jeśli próbowałeś dalej ograniczyć to za pomocą zachowania na swojej stronie, moje opcje obejmują wyłączenie tego zachowania lub po prostu napisanie niestandardowego żądania HTTP do serwera, które i tak imituje ten formularz. Do tego celu służy narzędzie o nazwie curl i myślę, że polecenie przesłania tego wstrzyknięcia SQL i tak wyglądałoby mniej więcej tak:
(To może nie być całkowicie poprawne polecenie zwijania, ale znowu mam nadzieję, że udało mi się zrozumieć.)
Więc powtórzę:
NIGDY nie ufaj wprowadzaniu danych przez użytkownika. ZAWSZE chroń siebie.
Nie zakładaj, że jakiekolwiek dane wejściowe użytkownika są kiedykolwiek bezpieczne. Jest to potencjalnie niebezpieczne, nawet jeśli dotrze w inny sposób niż formularz. Żadne z nich nie jest na tyle wiarygodne, aby zrezygnować z ochrony przed wstrzyknięciami SQL.
źródło
curl
. ZAWSZE oczyszczaj dane wejściowe po stronie serwera !curl
. Ludzie nie rozumieją, że możesz wysłać żądanie HTTP z dowolnego miejsca w dowolne miejsce, używając dowolnego formatu i przekazując dowolne wartości, to serwer musi upewnić się, że żądanie jest prawidłowe przed jego przetworzeniem.Ponieważ oznaczono to pytanie sql-injection, oto odpowiedź dotycząca tego konkretnego rodzaju ataku:
Jak powiedziano w komentarzach, musisz użyć przygotowanych instrukcji dla każdego zapytania zawierającego dowolne zmienne dane, bez wyjątków .
Bez względu na jakiekolwiek elementy HTML!
Ważne jest, aby zrozumieć, że zapytania SQL muszą być odpowiednio sformatowane, niezależnie od jakichkolwiek czynników zewnętrznych, czy to danych wejściowych HTML, czy czegokolwiek innego.
Chociaż możesz użyć białej listy sugerowanej w innych odpowiedziach w celu sprawdzania poprawności danych wejściowych, nie powinno to wpływać na żadne działania związane z SQL - muszą one pozostać takie same, bez względu na to, czy sprawdziłeś poprawność danych wejściowych HTML, czy nie. Oznacza to, że nadal musisz używać przygotowanych instrukcji podczas dodawania jakichkolwiek zmiennych do zapytania.
Tutaj możesz znaleźć dokładne wyjaśnienie, dlaczego przygotowane oświadczenia są niezbędne i jak prawidłowo z nich korzystać, a gdzie nie mają zastosowania i co zrobić w takim przypadku: The Hitchhiker's Guide to SQL Injection protection
Również to pytanie zostało oznaczone tagiem mysqli. Zakładam, że głównie przez przypadek, ale i tak muszę Cię ostrzec, że surowe mysqli nie jest odpowiednim zamiennikiem dla starych funkcji mysq_ * . Po prostu dlatego, że zastosowany w starym stylu nie zapewni żadnego bezpieczeństwa. O ile obsługa przygotowanych instrukcji jest bolesna i kłopotliwa, do tego stopnia, że przeciętny użytkownik PHP po prostu nie jest w stanie ich w ogóle wykonać. Tak więc, jeśli brak ORM lub jakaś biblioteka abstrakcji nie jest opcją, wówczas jedynym wyborem jest PDO .
źródło
random
?Tak.
Każdy może sfałszować wartości, które faktycznie są wysyłane -
WIĘC, aby zweryfikować menu rozwijane, możesz po prostu sprawdzić, aby upewnić się, że wartość, z którą pracujesz, znajduje się na liście rozwijanej - coś takiego byłoby najlepszym (najbardziej zdrowo paranoicznym) sposobem:
źródło
Jednym ze sposobów ochrony przed użytkownikami zmieniającymi listy rozwijane za pomocą konsoli jest używanie w nich tylko wartości całkowitych. Następnie możesz sprawdzić, czy wartość POST zawiera liczbę całkowitą i w razie potrzeby użyć tablicy, aby przekonwertować ją na tekst. Na przykład:
Następnie możesz użyć
$size
w swoim zapytaniu ze świadomością, że zawsze będzie zawieraćFALSE
tylko liczbę całkowitą.źródło
filter_input
jeśli nie jest to sprawdzenie po stronie serwera? Nikt nie może publikować niczego poza liczbą całkowitą.filter_input
części również do walidacji, w przeciwnym razie jest tak przydatna jak czajnik czekoladowy dla bezpieczeństwa.Pozostałe odpowiedzi już obejmują to, co musisz wiedzieć. Ale może pomoże to wyjaśnić trochę więcej:
Są dwie rzeczy, które trzeba zrobić:
1. Sprawdź poprawność danych formularza.
Jak jasno pokazuje odpowiedź Jonathana Hobbsa , wybór elementu HTML do danych wejściowych formularza nie zapewnia żadnego niezawodnego filtrowania.
Walidacja jest zwykle przeprowadzana w sposób, który nie zmienia danych, ale pokazuje ponownie formularz, z polami oznaczonymi jako „Popraw to”.
Większość frameworków i systemów CMS ma konstruktory formularzy, które pomagają w tym zadaniu. I nie tylko to, pomagają również przeciwko CSRF (lub „XSRF”), który jest inną formą ataku.
2. Oczyść zmienne / ucieczki w instrukcjach SQL.
.. lub pozwól, aby przygotowane zestawienia zrobiły to za Ciebie.
Jeśli tworzysz (My) instrukcję SQL z dowolnymi zmiennymi, podanymi lub nie przez użytkownika, musisz zmienić znaczenie i zacytować te zmienne.
Ogólnie rzecz biorąc, każda taka zmienna, którą wstawisz do instrukcji MySQL, powinna być albo ciągiem znaków, albo czymś, co PHP może niezawodnie przekształcić w ciąg, który MySQL może przetrawić. Takich jak liczby.
W przypadku łańcuchów musisz wybrać jedną z kilku metod zmiany znaczenia ciągu, co oznacza zastąpienie wszelkich znaków, które miałyby skutki uboczne w MySQL.
Jeśli masz do czynienia z liczbą, możesz pominąć ucieczki i cudzysłowy (dlatego przygotowane instrukcje pozwalają określić typ).
Ważne jest, aby zwrócić uwagę, że zmieniasz znaczenie zmiennych dla instrukcji SQL, a NIE dla samej bazy danych . Baza danych będzie przechowywać oryginalny ciąg, ale instrukcja wymaga wersji z ucieczką.
Co się stanie, jeśli pominiesz jedną z nich?
Jeśli nie korzystasz z weryfikacji formularza , ale oczyszczasz dane wejściowe SQL, możesz zobaczyć różne rodzaje złych rzeczy, ale nie zobaczysz iniekcji SQL! (*)
Po pierwsze, może spowodować, że Twoja aplikacja wejdzie w stan, którego nie planowałeś. Np. Jeśli chcesz obliczyć średni wiek wszystkich użytkowników, ale jeden użytkownik podał „aljkdfaqer” jako wiek, obliczenia nie powiodą się.
Po drugie, może istnieć wiele innych ataków typu injection, które należy wziąć pod uwagę: np. Dane wejściowe użytkownika mogą zawierać kod JavaScript lub inne elementy.
Nadal mogą występować problemy z bazą danych: np. Jeśli pole (kolumna tabeli bazy danych) jest ograniczone do 255 znaków, a łańcuch jest dłuższy. Lub jeśli pole akceptuje tylko liczby, a zamiast tego spróbujesz zapisać ciąg nienumeryczny. Ale to nie jest „wstrzyknięcie”, to po prostu „zawieszenie aplikacji”.
Ale nawet jeśli masz wolne pole tekstowe, w którym zezwalasz na dowolne dane wejściowe bez żadnej walidacji, nadal możesz zapisać to w bazie danych po prostu w ten sposób, jeśli odpowiednio zmienisz jego znaczenie, gdy przechodzi do instrukcji bazy danych. Problem pojawia się, gdy chcesz gdzieś użyć tego ciągu.
(*) albo byłoby to coś naprawdę egzotycznego.
Jeśli nie zmienisz znaczenia zmiennych dla instrukcji SQL , ale sprawdziłeś poprawność danych wejściowych formularza, nadal możesz zobaczyć, że dzieje się źle.
Po pierwsze, ryzykujesz, że kiedy zapiszesz dane do bazy danych i załadujesz je ponownie, nie będą to już te same dane, „zagubione w tłumaczeniu”.
Po drugie, może spowodować nieprawidłowe instrukcje SQL, a tym samym spowodować awarię aplikacji. Np. Jeśli jakakolwiek zmienna zawiera cudzysłów lub znak podwójnego cudzysłowu, w zależności od tego, jakiego typu cudzysłowu używasz, otrzymasz nieprawidłowe wyrażenie MySQL.
Po trzecie, nadal może powodować wstrzykiwanie SQL.
Jeśli dane wejściowe użytkownika z formularzy są już przefiltrowane / zatwierdzone, celowe wstrzyknięcie SQl może być mniej prawdopodobne, JEŚLI dane wejściowe zostaną zredukowane do zakodowanej na stałe listy opcji lub jeśli są ograniczone do liczb. Ale do wstrzyknięcia SQL można użyć dowolnego wpisanego tekstu, jeśli nie zmienisz odpowiednio zmiennych w instrukcjach SQL.
I nawet jeśli w ogóle nie masz danych wejściowych do formularza, nadal możesz mieć ciągi znaków z różnych źródeł: odczytywane z systemu plików, usuwane z Internetu itp. Nikt nie może zagwarantować, że te ciągi są bezpieczne.
źródło
Twoja przeglądarka internetowa nie „wie”, że otrzymuje stronę z php, widzi jedynie html. A warstwa http wie jeszcze mniej. Musisz być w stanie obsłużyć prawie każdy rodzaj danych wejściowych, które mogą przekroczyć warstwę http (na szczęście dla większości wejściowych php już wystąpi błąd). Jeśli próbujesz zapobiec zepsuciu bazy danych przez złośliwe żądania, musisz założyć, że facet po drugiej stronie wie, co robi, i nie ogranicza się do tego, co możesz zobaczyć w przeglądarce w normalnych okolicznościach ( nie wspominając o tym, co możesz majstrować przy narzędziach programistycznych przeglądarki). Więc tak, musisz uwzględnić wszelkie dane wejściowe z menu rozwijanego, ale w przypadku większości danych wejściowych możesz podać błąd.
źródło
Fakt, że ograniczyłeś użytkownika do używania tylko wartości z określonej listy rozwijanej, nie ma znaczenia. Użytkownik techniczny może przechwycić żądanie http wysłane do serwera, zanim opuści jego sieć, zmienić je za pomocą narzędzia takiego jak lokalny serwer proxy, a następnie kontynuować w drodze. Korzystając ze zmienionego żądania, mogą wysyłać wartości parametrów, które nie są tymi, które zostały określone na liście rozwijanej. Deweloperzy muszą mieć nastawienie, że ograniczenia klienta są często bez znaczenia, ponieważ wszystko na kliencie można zmienić. Sprawdzanie poprawności serwera jest wymagane w każdym punkcie wprowadzania danych klienta. Atakujący polegają na naiwności programistów tylko w tym aspekcie.
źródło
Najlepiej jest użyć sparametryzowanego zapytania, aby uniknąć iniekcji SQL. W takim przypadku zapytanie wyglądałoby tak:
Gdy zapytanie, takie jak powyżej, zawiera tekst, który nie jest zweryfikowany pod kątem integralności (dane wejściowe nie są sprawdzane na serwerze) i zawiera kod iniekcji SQL, zostanie on poprawnie obsłużony. Innymi słowy, żądanie spowoduje coś takiego, jak to się dzieje w warstwie bazy danych:
Spowoduje to po prostu wybranie 0 wyników, gdy zwróci, co spowoduje, że zapytanie będzie nieskuteczne, powodując szkody w bazie danych bez potrzeby stosowania białej listy, kontroli weryfikacyjnej lub innych technik. Należy pamiętać, że odpowiedzialny programista zapewni bezpieczeństwo w warstwach i często oprócz parametryzacji zapytań będzie sprawdzać poprawność. Jednak jest bardzo mało powodów, aby nie parametryzować zapytań z punktu widzenia wydajności, a zabezpieczenia dodane przez tę praktykę są dobrym powodem, aby zapoznać się z zapytaniami parametrycznymi.
źródło
Cokolwiek zostanie przesłane z formularza, trafi na serwer jako tekst przez przewody. Nic nie powstrzyma nikogo przed stworzeniem bota, który będzie naśladował klienta lub wpisał go z terminala, jeśli tego chce. Nigdy nie zakładaj, że skoro zaprogramowałeś klienta, będzie on działał tak, jak myślisz. Naprawdę łatwo to sfałszować.
Przykład tego, co może i co się stanie, gdy zaufasz klientowi.
źródło
Haker może całkowicie ominąć przeglądarkę, w tym sprawdzanie formularzy JavaScript, wysyłając żądanie za pomocą usługi Telnet. Oczywiście spojrzy na kod Twojej strony html, aby uzyskać nazwy pól, których musi użyć, ale od tego momentu wszystko mu idzie. Dlatego musisz sprawdzić wszystkie wartości przesłane na serwerze, tak jakby nie pochodziły ze strony html.
źródło