Wstrzyknięcie SQL to prosty wektor ataku, który jest nadal bardzo powszechny. Powodem tego jest brak łatki dla głupi. Dlaczego tak mówisz? Weźmy na przykład JAVA, żeby zobrazować:
Załóżmy, że taka tabela istnieje w bazie danych:
Następnie użyj tabeli akcji JDBC:
Powyższy kod jest często używany przez niektórych programistów. Wyobraźmy sobie sytuację, w której parametr userId to "3; użytkownik tabeli drop; Wykonywane polecenie SQL wygląda następująco:
Po skompilowaniu i uruchomieniu bazy danych tabela użytkownika jest usuwana. Voila, prosty atak z SQL injection zaczyna działać! Wynika to z faktu, że powyższy kod nie spełnia specyfikacji programowania.
Gdy programujemy zgodnie ze specyfikacją, wstrzyknięcie SQL praktycznie nie istnieje. Podobnie jestPierwszy sposób na uniknięcie wstrzyknięcia SQL: instrukcje wstępnie skompilowane, kod jest następujący:
Dlaczego w powyższym kodzie nie istnieje SQL injection? Ponieważ użyto prekompilowanego polecenia, prekompilowane zostanie ustawione "select name from user where id= ?" Instrukcja jest kompilowana wcześniej, więc wystarczy ją zastąpić parametrami wejściowymi tylko podczas wykonywania? Tymczasowe są w porządku. W pierwszym przypadku niezgodności program zapisuje polecenie SQL i kompiluje je z treścią przekazaną przez użytkownika, co jest właśnie problemem.
Oprócz używania wstępnie skompilowanych instrukcji, istnieje druga opcjaSposoby unikania ataków z wtryskiem SQL: procedury przechowywane。 Procedura przechowywana to zbiór instrukcji SQL wykonujących określoną funkcję, skompilowanych i przechowywanych w bazie danych, a użytkownik może ją wykonać, wywołując procedurę przechowywaną i podając parametr (jeśli procedura ma parametry), co pozwala również uniknąć ataków typu SQL injection
Odpowiadająca procedura przechowywana w powyższym kodzie wygląda następująco:
Oczywiście użytkownicy mogą także sprawdzać znaki na frontendzie, co jest sposobem na uniknięcie SQL injection: na przykład dla parametru userId powyżej użytkownik sprawdzi średnik i wyświetli błąd. Jednak najbardziej podstawowym powodem jest to, że ataki SQL injection istnieją, ponieważ aplikacje nie korzystają z najmniejszych uprawnień przy uzyskiwaniu dostępu do baz danych. Wygląda na to, że wszyscy korzystali z konta root, aby uzyskać dostęp do bazy danych.
Jak więc MyBatis unika ataków z pomocą SQL injection? Albo weźmy użytkownika tabeli powyżej jako przykład: Załóżmy, że plik mapper to:
Odpowiadające pliki Java to:
Można zobaczyć, że parametr wejściowy to userId typu String, gdy przekazujemy userId="34; użytkownik tabeli drop; Następnie drukowane oświadczenie brzmi:
Niezależnie od wpisanego userID, jego instrukcja SQL wygląda tak. Wynika to z faktu, że mybatis używa wstępnie skompilowanych instrukcji w implementacji. Gdy baza danych wykonuje to zdanie, bezpośrednio używa prekompilowanego polecenia, a następnie zastępuje zastępcze na przechodzący userId? Po prostu biegnij. Najpierw wymienić zastępcze? Proces kompilacji jest wykonywany, więc nie ma miejsca na przetrwanie SQL injection.
Jak więc MyBatis robi prekompilację SQL? W rzeczywistości klasa PreparedStatement jest używana na dole frameworka. Klasa PreparedStaement nie tylko unika wstrzyknięcia SQL, ale także oszczędza (N-1) czasu kompilacji, gdy to samo polecenie SQL jest wykonywane N razy, co zwiększa efektywność.
Jeśli zmienisz powyższe stwierdzenie na:
Gdy wpisujemy userId="34; użytkownik tabeli drop; Następnie drukowane oświadczenie brzmi:
Obecnie mybatis nie używa wstępnie skompilowanych instrukcji, najpierw zszywa ciągi tekstów, a następnie wykonuje kompilację, co dokładnie tak działa SQL injection.
Dlatego podczas pisania instrukcji mapowania mybatis staraj się używać formatu "#{xxx}". Jeśli musisz używać parametrów takich jak "${xxx}", musisz je ręcznie filtrować, aby zapobiec atakom SQL injection.
|