Jeśli chodzi o wiele przydatnych odpowiedzi, mam nadzieję, że dodam trochę wartości temu wątkowi.
Wstrzyknięcie SQL to atak, który można wykonać za pomocą danych wejściowych użytkownika (danych wejściowych, które użytkownik wypełnił, a następnie wykorzystał w zapytaniach). Wzorce wstrzykiwania SQL są poprawną składnią zapytań, którą możemy nazwać: złe zapytania z niewłaściwych powodów i zakładamy, że może być zła osoba, która próbuje uzyskać tajne informacje (omijając kontrolę dostępu), które wpływają na trzy zasady bezpieczeństwa (poufność) , integralność i dostępność).
Teraz naszym celem jest zapobieganie zagrożeniom bezpieczeństwa, takim jak ataki polegające na wstrzykiwaniu SQL, zadawanie pytań (jak zapobiegać atakom polegającym na wstrzykiwaniu SQL za pomocą PHP), być bardziej realistycznym, filtrowanie lub usuwanie danych wejściowych ma miejsce w przypadku korzystania z danych wprowadzanych przez użytkownika wewnątrz takie zapytanie, użycie PHP lub innego języka programowania nie jest prawdą lub, jak zaleca więcej osób, aby korzystać z nowoczesnych technologii, takich jak przygotowane oświadczenie lub inne narzędzia, które obecnie obsługują zapobieganie wstrzykiwaniu SQL, uważają, że te narzędzia nie są już dostępne? Jak zabezpieczyć aplikację?
Moje podejście przeciwko iniekcji SQL to: czyszczenie danych wejściowych użytkownika przed wysłaniem ich do bazy danych (przed użyciem ich w dowolnym zapytaniu).
Filtrowanie danych (konwersja niebezpiecznych danych na bezpieczne dane)
Weź pod uwagę, że PDO i MySQLi nie są dostępne. Jak możesz zabezpieczyć swoją aplikację? Czy zmuszasz mnie do korzystania z nich? Co z innymi językami innymi niż PHP? Wolę przedstawiać ogólne pomysły, ponieważ można je wykorzystać dla szerszych granic, a nie tylko dla konkretnego języka.
- Użytkownik SQL (ograniczenie uprawnień użytkownika): najczęstsze operacje SQL to (WYBIERZ, AKTUALIZACJA, WSTAW), po co więc nadawać uprawnienia UPDATE użytkownikowi, który go nie wymaga? Na przykład strony logowania i wyszukiwania używają tylko SELECT, więc po co używać użytkowników DB na tych stronach z wysokimi uprawnieniami?
ZASADA: nie twórz jednego użytkownika bazy danych dla wszystkich uprawnień. Dla wszystkich operacji SQL możesz utworzyć swój schemat, taki jak (deluser, selectuser, updateuser) jako nazwy użytkownika dla łatwego użycia.
Zobacz zasadę najmniejszych uprawnień .
Filtrowanie danych: przed zbudowaniem dowolnego zapytania użytkownika należy je zweryfikować i przefiltrować. Dla programistów ważne jest zdefiniowanie niektórych właściwości dla każdej zmiennej wprowadzanej przez użytkownika:
typ danych, wzorzec danych i długość danych . Pole, które jest liczbą pomiędzy (xiy), musi być dokładnie sprawdzone przy użyciu ścisłej reguły, a dla pola, które jest łańcuchem (tekstem): przypadek ma wzór, na przykład nazwa użytkownika musi zawierać tylko niektóre znaki, powiedz [a-zA-Z0-9_-.]. Długość waha się między (x i n), gdzie x i n (liczby całkowite, x <= n).
Reguła: tworzenie dokładnych filtrów i reguł sprawdzania poprawności to dla mnie najlepsze praktyki.
Użyj innych narzędzi: tutaj również zgodzę się z tobą, że przygotowane oświadczenie (sparametryzowane zapytanie) i procedury składowane. Wadą jest to, że te sposoby wymagają zaawansowanych umiejętności, które nie istnieją dla większości użytkowników. Podstawową ideą jest tutaj rozróżnienie między zapytaniem SQL a danymi używanymi w środku. Oba podejścia można zastosować nawet w przypadku niebezpiecznych danych, ponieważ dane wprowadzone przez użytkownika tutaj nie dodają niczego do pierwotnego zapytania, takiego jak (dowolny lub x = x).
Aby uzyskać więcej informacji, przeczytaj OWASP SQL Injection Prevention Cheat Sheet .
Teraz, jeśli jesteś zaawansowanym użytkownikiem, zacznij używać tej obrony, jak chcesz, ale dla początkujących, jeśli nie mogą szybko wdrożyć procedury składowanej i przygotowali instrukcję, lepiej filtrować dane wejściowe, na ile mogą.
Wreszcie, rozważmy, że użytkownik wysyła ten tekst poniżej, zamiast wpisywać swoją nazwę użytkownika:
[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'
Dane wejściowe można sprawdzić wcześniej bez przygotowanej instrukcji i procedur przechowywanych, ale dla pewności korzystanie z nich rozpoczyna się po filtrowaniu i weryfikacji danych użytkownika.
Ostatnim punktem jest wykrycie nieoczekiwanego zachowania, które wymaga większego wysiłku i złożoności; nie jest to zalecane w przypadku zwykłych aplikacji internetowych.
Nieoczekiwane zachowanie w powyższych danych wejściowych użytkownika to SELECT, UNION, IF, SUBSTRING, BENCHMARK, SHA i root. Po wykryciu tych słów możesz uniknąć wprowadzania danych.
AKTUALIZACJA 1:
Użytkownik skomentował, że ten post jest bezużyteczny, OK! Oto, co zapewnił OWASP.ORG :
Podstawowa obrona:
Opcja nr 1: Wykorzystanie przygotowanych instrukcji (sparametryzowane zapytania)
Opcja nr 2: Zastosowanie procedur przechowywanych
Opcja nr 3: Ucieczka od wszystkich danych dostarczonych przez użytkownika
Dodatkowe zabezpieczenia:
Wymuszenie: Najmniejszy przywilej
Wykonaj również: Sprawdzanie poprawności danych na białej liście
Jak zapewne wiesz, roszczenie do artykułu powinno być poparte ważnym argumentem, przynajmniej jednym odniesieniem! W przeciwnym razie jest to uważane za atak i złe roszczenie!
Aktualizacja 2:
Z podręcznika PHP, PHP: Przygotowane instrukcje - Podręcznik :
Ucieczka i wstrzyknięcie SQL
Związane zmienne będą automatycznie usuwane przez serwer. Serwer wstawia wartości specjalne w odpowiednich miejscach do szablonu instrukcji przed wykonaniem. Na serwerze należy podać wskazówkę dotyczącą typu zmiennej powiązanej, aby utworzyć odpowiednią konwersję. Aby uzyskać więcej informacji, zobacz funkcję mysqli_stmt_bind_param ().
Automatyczne zmiany wartości na serwerze są czasem uważane za funkcję bezpieczeństwa zapobiegającą wstrzykiwaniu SQL. Taki sam poziom bezpieczeństwa można uzyskać przy użyciu nieprzygotowanych instrukcji, jeśli wartości wejściowe są odpowiednio zabezpieczone znakami ucieczki.
Aktualizacja 3:
Utworzyłem przypadki testowe, aby dowiedzieć się, w jaki sposób PDO i MySQLi wysyłają zapytanie do serwera MySQL podczas korzystania z przygotowanej instrukcji:
ChNP:
$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));
Dziennik zapytań:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
189 Quit
MySQLi:
$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();
Dziennik zapytań:
188 Prepare SELECT * FROM awa_user WHERE username =?
188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\''
188 Quit
Oczywiste jest, że przygotowane oświadczenie ucieka również od danych, nic więcej.
Jak wspomniano również w powyższym oświadczeniu,
Automatyczne zmiany wartości na serwerze są czasem uważane za funkcję bezpieczeństwa zapobiegającą wstrzykiwaniu SQL. Taki sam poziom bezpieczeństwa można osiągnąć przy użyciu nieprzygotowanych instrukcji, jeśli wartości wejściowe są odpowiednio zabezpieczone znakami ucieczki
Dlatego dowodzi to, że sprawdzanie poprawności danych, takie jak, intval()
jest dobrym pomysłem na wartości całkowite przed wysłaniem dowolnego zapytania. Ponadto zapobieganie złośliwym użytkownikom przed wysłaniem zapytania jest poprawnym i prawidłowym podejściem .
Proszę zobaczyć to pytanie, aby uzyskać więcej szczegółów: PDO wysyła surowe zapytanie do MySQL, podczas gdy Mysqli wysyła przygotowane zapytanie, oba dają ten sam wynik
Bibliografia:
- Ściągawka SQL Injection
- Zastrzyk SQL
- Bezpieczeństwo informacji
- Zasady bezpieczeństwa
- Walidacji danych