Bądź czujny: funkcje PHP i WordPress, które mogą sprawić, że Twoja witryna stanie się niebezpieczna

Opublikowany: 2022-03-10
Krótkie podsumowanie ↬ Przed wdrożeniem nowej wtyczki w WordPressie dobrze jest mieć przy sobie listę funkcji, które można łatwo wykorzystać. Przyjrzyjmy się bliżej niektórym funkcjom, których możesz i powinieneś używać w ramach szerszej strategii bezpieczeństwa.

Bezpieczeństwo witryny WordPress (lub dowolnej) to problem wielowymiarowy. Najważniejszym krokiem, jaki każdy może podjąć, aby upewnić się, że witryna jest bezpieczna, jest pamiętanie, że żaden pojedynczy proces ani metoda nie wystarczy, aby upewnić się, że nic złego się nie wydarzy. Ale są rzeczy, które możesz zrobić, aby pomóc. Jednym z nich jest bycie czujnym, w kodzie, który piszesz i kodzie innych, które wdrażasz, pod kątem funkcji, które mogą mieć negatywne konsekwencje. W tym artykule omówimy dokładnie te: funkcje, o których programista WordPress powinien jasno pomyśleć przed użyciem.

Sam WordPress zapewnia sporą bibliotekę funkcji, z których niektóre mogą być niebezpieczne. Poza tym istnieje wiele funkcji PHP, z których programista WordPress (PHP) będzie korzystał z pewną częstotliwością, która może być niebezpieczna.

Wszystkie te funkcje mają legalne i bezpieczne zastosowania, ale są to również funkcje, które mogą ułatwić nadużycie kodu do złych celów. Omówimy rzeczy, które najprawdopodobniej są przyczyną luki w zabezpieczeniach i dlaczego musisz na nie uważać. Najpierw omówimy funkcje PHP w Twoim kodzie, które źli aktorzy mogą wykorzystać do zła, a następnie porozmawiamy o funkcjach PHP specyficznych dla WordPressa, które również mogą powodować bóle głowy.

Funkcje PHP, na które należy uważać

Jak powiedzieliśmy, PHP zawiera wiele łatwych w użyciu funkcji. Niektóre z tych funkcji są znane z łatwości, z jaką ludzie mogą robić z nimi złe rzeczy. Wszystkie te funkcje mają właściwe zastosowanie, ale uważaj na to, jak ich używasz i jak działa inny kod, który wciągniesz do projektu.

Zakładamy, że masz już wyłączone magiczne cudzysłowy i globalne rejestry, jeśli twoja wersja PHP je obsługuje. Były domyślnie wyłączone w PHP 5 i nowszych, ale mogły zostać włączone w wersjach poniżej 5.4. Niewielu hostów na to pozwoliło, ale nie sądzę, aby artykuł dotyczący bezpieczeństwa PHP był naprawdę kompletny bez ich włączenia.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Lub wzmianka, że ​​PHP 5.6 jest ostatnią wersją 5.x, która wciąż obsługuje zabezpieczenia. Powinnaś przynajmniej na tym być. Powinieneś mieć plan przejścia na PHP 7 przed zakończeniem obsługi 5.6 pod koniec 2018 roku.

Potem będziesz miał do czynienia z kilkoma ryzykownymi funkcjami. Zaczynając od…

extract to złe wieści, szczególnie w dniu $_POST lub podobnym

Na szczęście użycie funkcji extract w PHP w dużej mierze wypadło z łask. Sednem jego użycia było to, że można go uruchomić na tablicy danych, a pary klucz-wartość stałyby się żywymi zmiennymi w kodzie. Więc

 $arr = array( 'red' => 5 ); extract($arr); echo $red; // 5

pracowałbym. To jest fajne, ale jest też naprawdę niebezpieczne, jeśli wyodrębniasz $_GET , $_POST itp. W takich przypadkach zasadniczo odtwarzasz sam problem register_globals : atakujący z zewnątrz może łatwo zmienić wartości zmiennych, dodając ciąg zapytania lub pola formularza. Najlepsze rozwiązanie jest proste: nie używaj extract .

Jeśli tworzysz tablicę, którą wyodrębniasz samodzielnie, użycie extract , nie jest szczególnym problemem bezpieczeństwa, aw niektórych przypadkach może być przydatne. Ale wszystkie jego zastosowania powodują problem zdezorientowania przyszłych czytelników. Tworzenie tablicy i wywoływanie extract jest bardziej mylące niż samo deklarowanie zmiennych. Dlatego zachęcam do ręcznego składania deklaracji, chyba że jest to całkowicie niewykonalne.

Jeśli musisz użyć extract na danych wejściowych użytkownika, powinieneś zawsze używać flagi EXTR_SKIP . To nadal powoduje problem z pomyłką, ale eliminuje możliwość zmiany wstępnie ustawionych wartości przez złośliwego użytkownika z zewnątrz za pomocą prostego ciągu zapytania lub modyfikacji formularza internetowego. (Ponieważ „przeskakuje” już ustawione wartości.)

eval jest złem”, ponieważ arbitralny kodeks jest przerażający

eval w PHP i prawie każdym innym języku, który go obsługuje, jest zawsze wysoko na listach takich jak ta. I nie bez powodu. Oficjalna dokumentacja PHP na PHP.net mówi to całkiem szczerze:

UWAGA : Konstrukcja języka eval() jest bardzo niebezpieczna, ponieważ umożliwia wykonanie dowolnego kodu PHP. Dlatego odradza się jego stosowanie. Jeśli dokładnie sprawdziłeś, że nie ma innej opcji niż użycie tej konstrukcji, zwróć szczególną uwagę, aby nie przekazywać do niej żadnych danych dostarczonych przez użytkownika bez wcześniejszego sprawdzenia poprawności.

eval pozwala na uruchamianie dowolnego ciągu w twoim programie tak, jakby był to kod PHP. Oznacza to, że jest to przydatne w przypadku „metaprogramowania”, w którym budujesz program, który sam może zbudować program. Jest to również bardzo niebezpieczne, ponieważ jeśli kiedykolwiek pozwolisz, aby dowolne źródła (takie jak pole tekstowe na stronie internetowej) były natychmiast przekazywane do twojego eval ciągu znaków, nagle sprawiłeś, że złośliwy atakujący może zrobić prawie wszystko, co może PHP zrobić na swoim serwerze. Obejmuje to oczywiście łączenie się z bazą danych, usuwanie plików i prawie wszystko, co ktoś może zrobić po SSH na maszynie. To jest złe.

Jeśli musisz użyć eval w swoim programie, powinieneś zrobić wszystko, aby upewnić się, że nie pozwalasz na przekazywanie do niego dowolnych danych wejściowych użytkownika. A jeśli musisz zezwolić dowolnym użytkownikom na dostęp do danych wejściowych w celu eval , ogranicz to, co mogą zrobić, za pomocą czarnej listy poleceń, których nie pozwalasz im uruchamiać, lub (lepiej, ale o wiele trudniej zaimplementować) białej listy, która zawiera tylko polecenia, które uważaj za bezpieczne. Co więcej, zezwalaj tylko na niewielką liczbę określonych zmian parametrów, takich jak tylko zweryfikowane liczby całkowite.

Ale zawsze pamiętaj o tym wierszu od Rasmusa Lerdorfa, założyciela PHP:

"Jeżeli odpowiedź `eval()` jest odpowiedzią, prawie na pewno zadajesz złe pytanie."

Wariacje na temat eval

Istnieje, oprócz dobrze znanego eval , wiele innych sposobów, w jakie PHP historycznie obsługiwało ciągi-oceniane-jako kod. Dwa, które są najbardziej odpowiednie dla programistów WordPressa, to preg_replace z modyfikatorem /e i create_function . Każdy działa trochę inaczej, a preg_replace po PHP 5.5.0 w ogóle nie działa. (PHP 5.5 i starsze wersje nie otrzymują już oficjalnych aktualizacji bezpieczeństwa, dlatego najlepiej ich nie używać.)

/e Modyfikatory w wyrażeniu regularnym są również „złe”

Jeśli używasz PHP 5.4.x lub starszego, powinieneś zwracać uwagę na wywołania PHP preg_replace , które kończą się na e. To może wyglądać tak:

 $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );) $html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)

PHP oferuje różne sposoby „ogrodzenia” w wyrażeniu regularnym, ale podstawową rzeczą, na którą chcesz zwrócić uwagę, jest „e” jako ostatni znak pierwszego argumentu preg_replace . Jeśli tam jest, w rzeczywistości przekazujesz cały znaleziony segment jako argument do wbudowanego PHP, a następnie eval go. Ma to dokładnie te same problemy, co eval , jeśli pozwalasz, aby dane wejściowe użytkownika trafiały do ​​Twojej funkcji. Przykładowy kod można zastąpić, używając zamiast tego preg_replace_callback . Zaletą tego jest to, że napisałeś swoją funkcję, więc atakującemu trudniej jest zmienić to, co jest oceniane. Więc napisałbyś powyższe jako:

 // uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html ); // uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html ); // uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html ); // uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html ); // uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html );

Zezwalanie na wprowadzanie przez użytkownika create_function jest również złe…

PHP posiada również funkcję create_function . Jest to obecnie przestarzałe w PHP 7.2, ale było bardzo podobne do eval i miało te same podstawowe wady: pozwalało na przekształcenie ciągu (drugi argument) w wykonywalny PHP. I wiązało się to z tym samym ryzykiem: zbyt łatwo jest przypadkowo dać inteligentnemu crackerowi możliwość zrobienia czegokolwiek na twoim serwerze, jeśli nie będziesz ostrożny.

Ten, jeśli korzystasz z PHP powyżej 5.3, jest nawet łatwiejszy do naprawienia niż preg_replace . Możesz po prostu utworzyć własną anonimową funkcję bez używania ciągów jako pośredników. Jest to zarówno bezpieczniejsze, jak i bardziej czytelne, przynajmniej w moich oczach.

assert jest również eval

assert nie jest funkcją, z której korzysta wielu programistów PHP, zarówno w WordPressie, jak i poza nim. Jego celem jest zapewnienie bardzo lekkich asercji dotyczących warunków wstępnych dla twojego kodu. Ale obsługuje również operację typu eval . Z tego powodu powinieneś być wobec tego równie ostrożny, jak wobec eval . Asercje oparte na ciągach znaków (sedno tego, dlaczego jest to złe) są również przestarzałe w PHP 7.2, co oznacza, że ​​w przyszłości powinno być mniej niepokojące.

Dołączanie plików zmiennych to sposób na możliwe niekontrolowane wykonywanie PHP

Dość dobrze zbadaliśmy, dlaczego eval jest złe, ale coś takiego jak include lub require($filename'.php') może, zwłaszcza gdy $filename jest ustawione z wartości kontrolowanej przez użytkownika, być podobnie złą wiadomością. Powód jest nieco inny niż eval . Nazwy plików zmiennych są często używane do takich rzeczy, jak prosty routing URL-do-pliku w aplikacjach PHP innych niż WordPress. Ale możesz zobaczyć je również w WordPressie.

Sedno problemu include na tym, że gdy dołączasz lub require (lub include_once lub require_once ), powodujesz, że skrypt wykonuje dołączony plik. To mniej więcej koncepcyjnie eval ten plik, chociaż rzadko myślimy o tym w ten sposób.

Jeśli napisałeś wszystkie pliki, które Twoja zmienna może include , i zastanawiałeś się, co się stanie, gdy to zrobi, wszystko w porządku. Ale to zła wiadomość, jeśli nie zastanawiałeś include , co zrobi ing password.php lub wp-config.php . To również zła wiadomość, jeśli ktoś może dodać złośliwy plik, a następnie uruchomić include (chociaż w tym momencie prawdopodobnie masz większe problemy).

Rozwiązanie tego nie jest jednak zbyt trudne: twardy kod uwzględnia, kiedy możesz. Jeśli nie możesz, przygotuj białą listę (lepiej) lub czarną listę plików, które można uwzględnić. Jeśli pliki na białej liście (czyli sprawdziłeś, co robi po dodaniu), będziesz wiedzieć, że jesteś bezpieczny. Jeśli nie ma go na Twojej białej liście, Twój skrypt go nie uwzględni. Dzięki tej prostej zmianie jesteś całkiem bezpieczny. Biała lista wyglądałaby mniej więcej tak:

 $white_list = ['db.php', filter.php', 'condense.php'] If (in_array($white_list, $file_to_include)) { include($file_to_include); }

Nigdy nie przekazuj danych wejściowych użytkownika do shell_exec i wariantów

Ten jest duży. shell_exec , system , exec i backticks w PHP pozwalają kodowi komunikować się z podstawową (zwykle Uniksową) powłoką. Jest to podobne do tego, co czyni eval niebezpieczną, ale podwaja się. Podwojony, ponieważ jeśli wpuścisz tutaj nieostrożnie dane wprowadzane przez użytkownika, atakujący nie będzie nawet związany ograniczeniami PHP.

Możliwość uruchamiania poleceń powłoki z PHP może być bardzo przydatna jako programista. Ale jeśli kiedykolwiek wpuścisz tam wkład użytkownika, ma on możliwość ukradkiem zdobycia wielu niebezpiecznych mocy. Posunąłbym się więc do stwierdzenia, że ​​dane wejściowe użytkownika nigdy nie powinny być przekazywane do funkcji typu shell_exec .

Najlepszym sposobem, w jaki mógłbym sobie wyobrazić, by poradzić sobie z tego typu sytuacją, gdyby kusiło Cię, by to zaimplementować, byłoby zapewnienie użytkownikom dostępu do małego zestawu znanych, bezpiecznych, predefiniowanych poleceń powłoki. To może być możliwe do zabezpieczenia. Ale nawet wtedy ostrzegałbym cię, żebyś był bardzo ostrożny.

Uważaj na unserialize ; Automatycznie uruchamia kod

Podstawowe działanie polegające na wywołaniu serialize na żywym obiekcie PHP, przechowaniu gdzieś tych danych, a następnie użyciu tej przechowywanej wartości w celu unserialize tego obiektu do stanu normalnego jest fajne. Jest to również dość powszechne, ale może być ryzykowne. Dlaczego ryzykowne? Jeśli dane wejściowe tego wywołania unserialize nie są całkowicie bezpieczne (powiedzmy, że są przechowywane jako plik cookie, a nie w Twojej bazie danych…), osoba atakująca może zmienić stan wewnętrzny obiektu w sposób, który sprawi, że wywołanie unserialize zrobi coś złego.

Ten exploit jest bardziej ezoteryczny i mniej prawdopodobny do zauważenia niż problem eval . Ale jeśli używasz pliku cookie jako mechanizmu przechowywania danych serializowanych, nie używaj serialize dla tych danych. Użyj czegoś takiego jak json_encode i json_decode . Dzięki tym dwóm PHP nigdy nie wykona automatycznie żadnego kodu.

Najważniejszą luką jest tutaj to, że gdy PHP unserialize ciąg znaków sa do klasy, wywołuje magiczną metodę __wakeup dla tej klasy. Jeśli niesprawdzone dane wejściowe użytkownika mogą być unserialized , coś takiego jak wywołanie bazy danych lub usunięcie pliku w metodzie __wakeup może potencjalnie wskazywać na niebezpieczną lub niepożądaną lokalizację.

unserialize różni się od eval , ponieważ wymaga użycia magicznych metod na obiektach. Zamiast tworzyć własny kod, osoba atakująca jest zmuszona nadużyć już napisanych metod na obiekcie. Zarówno magiczne metody __destruct , jak i __toString na obiektach są również ryzykowne, jak wyjaśnia ta strona Wiki OWASP.

Ogólnie rzecz biorąc, wszystko jest w porządku, jeśli nie używasz w swoich klasach metod __wakeup , __destruct lub __toString . Ale ponieważ później możesz zobaczyć, jak ktoś dodaje je do klasy, dobrym pomysłem jest, aby nigdy nie pozwalać użytkownikowi w pobliżu twoich wywołań do serialize i unserialize oraz przekazywania wszystkich danych publicznych do tego rodzaju użytku, chociaż coś takiego jak JSON ( json_encode i json_decode ) tam, gdzie jest nigdy nie jest automatycznym wykonaniem kodu.

Pobieranie adresów URL za pomocą file_get_contents jest ryzykowne

Powszechną praktyką podczas szybkiego pisania kodu PHP, który musi wywołać zewnętrzny adres URL, jest sięgnięcie do file_get_contents . To szybkie, łatwe, ale nie jest super bezpieczne.

Problem z file_get_contents jest subtelny, ale jest na tyle powszechny, że czasami hosty konfigurują PHP tak, aby nawet nie pozwalać na dostęp do zewnętrznych adresów URL. To ma cię chronić.

Problem polega na tym, że file_get_contents pobierze dla Ciebie strony zdalne. Ale kiedy to robi, nie sprawdza integralności połączenia protokołu HTTPS. Oznacza to, że Twój skrypt może potencjalnie paść ofiarą ataku typu man-in-the-middle, który umożliwiłby atakującemu umieszczenie praktycznie wszystkiego, czego chce, w wynikach strony file_get_contents .

To bardziej ezoteryczny atak. Ale żeby się przed tym uchronić, kiedy piszę nowoczesne (oparte na Composer) PHP, prawie zawsze używam Guzzle do pakowania bezpieczniejszego API cURL. W WordPressie jest to jeszcze prostsze: użyj wp_remote_get . Działa znacznie bardziej konsekwentnie niż file_get_contents i domyślnie sprawdza połączenia SSL. (Możesz to wyłączyć, ale, hm, może nie…) Jeszcze lepiej, ale trochę bardziej irytujące do rozmowy, są wp_safe_remote_get , itp. Działają one identycznie jak funkcje bez safe_ w nazwie, ale sprawią, że upewnij się, że niebezpieczne przekierowania i przekierowania nie zdarzają się po drodze.

Nie ufaj ślepo weryfikacji adresu URL od filter_var

Więc to jest trochę niejasne, więc rekwizyty dla Chrisa Weigmana za wyjaśnienie tego w tym przemówieniu WordCamp. Ogólnie rzecz biorąc, filter_var PHP jest świetnym sposobem na sprawdzanie poprawności lub oczyszczanie danych. (Chociaż nie pomyl się, co próbujesz zrobić…)

Problem tutaj jest dość specyficzny: jeśli próbujesz go użyć, aby upewnić się, że adres URL jest bezpieczny, filter_var nie weryfikuje protokołu. Nie jest to często problem, ale jeśli przekazujesz dane wejściowe użytkownika do tej metody w celu sprawdzenia poprawności i używasz FILTER_VALIDATE_URL , coś takiego jak javascript://comment%0aalert(1) przejdzie. Oznacza to, że może to być bardzo dobry wektor do podstawowego ataku XSS w miejscu, którego się nie spodziewałeś.

W przypadku walidacji adresu URL funkcja esc_url WordPressa będzie miała podobny wpływ, ale przepuszcza tylko dozwolone protokoły. javascript nie znajduje się na domyślnej liście, więc zapewniłby ci bezpieczeństwo. Jednak w przeciwieństwie do filter_var , zwróci pusty ciąg (nie fałsz) dla niedozwolonego protokołu, który jest do niego przekazywany.

Funkcje specyficzne dla WordPress, aby mieć na oku

Oprócz potencjalnie zagrożonych funkcji core-PHP, istnieją pewne funkcje specyficzne dla WordPressa, które mogą być trochę kłopotliwe. Niektóre z nich są bardzo podobne do szeregu niebezpiecznych funkcji wymienionych powyżej, inne są nieco inne.

WordPress unserializes z maybe_unserialize

Ten jest prawdopodobnie oczywisty, jeśli czytasz powyższe. W WordPressie istnieje funkcja o nazwie maybe_unserialize i, jak można się domyślić, w razie potrzeby usuwa z serializacji to, co jest do niej przekazywane.

Nie wprowadza to żadnej nowej luki w zabezpieczeniach, problem polega po prostu na tym, że podobnie jak podstawowa funkcja unserialize , ta może spowodować wykorzystanie podatnego obiektu, gdy nie zostanie on zserializowany.

is_admin nie odpowiada, jeśli użytkownik jest administratorem!

Ta funkcja jest dość prosta, ale funkcja jest niejednoznaczna z nazwy, więc może dezorientować ludzi lub zostać pominięta, jeśli się spieszysz. Zawsze powinieneś sprawdzić, czy użytkownik, który próbuje wykonać akcję w WordPressie, ma prawa i uprawnienia niezbędne do wykonania tej akcji. W tym celu należy użyć funkcji current_user_can .

Ale możesz błędnie pomyśleć, że is_admin powie, czy bieżący użytkownik jest kontem administratora i dlatego powinien móc ustawić opcję używaną przez twoją wtyczkę. Jest to błąd. To, co robi is_admin w WordPressie, zamiast tego informuje, czy bieżące ładowanie strony odbywa się po stronie administracyjnej witryny (w przeciwieństwie do strony frontowej). Tak więc każdy użytkownik, który ma dostęp do strony administracyjnej (takiej jak „Pulpit nawigacyjny”), będzie mógł potencjalnie przejść tę kontrolę. Dopóki będziesz pamiętać, że is_admin dotyczy typu strony, a nie bieżącego użytkownika, wszystko będzie dobrze.

add_query_arg() nie oczyszcza adresów URL

To nie jest takie powszechne, ale kilka lat temu nastąpiła duża fala aktualizacji w ekosystemie WordPressa, ponieważ publiczna dokumentacja dotycząca tych funkcji nie była prawidłowa. Podstawowym problemem jest to, że funkcja add_query_arg (i jej odwrotność remove_query_arg ) nie oczyszcza automatycznie adresu URL witryny, jeśli adres URL nie został do niej przekazany, a ludzie myśleli, że tak. Wiele wtyczek zostało wprowadzonych w błąd przez Kodeks i w rezultacie używało ich w sposób niebezpieczny.

Podstawową rzeczą, którą musieli zrobić, było inaczej: oczyścić wynik wywołania tej funkcji przed jej użyciem. Jeśli to zrobisz, będziesz naprawdę bezpieczny przed atakami XSS, o których myślałeś, że są. To wygląda mniej więcej tak:

 echo esc_url( add_query_arg( 'foo', 'bar' ) );

$wpdb->query() jest otwarty na atak polegający na wstrzykiwaniu SQL

Jeśli wiesz o wstrzykiwaniu SQL, może się to wydawać głupie, a nawet zbędne. Ponieważ chodzi o to, że każdy sposób, w jaki uzyskujesz dostęp do bazy danych (np. używając sterowników bazy danych PHP mysqli lub PDO) w celu tworzenia zapytań do bazy danych, które umożliwiają ataki typu SQL injection.

Powodem, dla którego konkretnie $wpdb->query , jest to, że niektóre inne metody (takie jak insert , delete itp.) w $wpdb zajmują się atakami wstrzykiwania. Dodatkowo, jeśli jesteś przyzwyczajony do wykonywania podstawowych zapytań do bazy danych WordPress za pomocą WP_Query lub podobnego, nie musisz rozważać wstrzykiwania SQL. Dlatego przywołuję to: aby upewnić się, że rozumiesz, atak wstrzykiwania na bazę danych jest możliwy, gdy po raz pierwszy spróbujesz użyć $wpdb do utworzenia własnego zapytania.

Co robić? Użyj $wpdb->prepare() , a następnie $wpdb->query() . Powinieneś również upewnić się, że przygotowałeś się przed innymi metodami „pobierania” $wpdb , takimi jak get_row() i get_var() . W przeciwnym razie Bobby Tables może cię dopaść.

esc_sql nie zabezpiecza Cię przed wstrzyknięciem SQL

Dla większości programistów WordPressa powiedziałbym, że esc_sql nie rejestruje się w żaden sposób, ale powinien. Jak już wspomnieliśmy, przed wykonaniem zapytania do bazy danych powinieneś użyć wpdb->prepare() . To zapewni ci bezpieczeństwo. Ale to kuszące i zrozumiałe, że programista może zamiast tego sięgnąć po esc_sql . I mogą się spodziewać, że będzie bezpiecznie.

Problem polega na tym, że esc_sql nie ma tak solidnych zabezpieczeń przed wstrzyknięciem SQL. To naprawdę wspaniała wersja funkcji add_slashes PHP, której od lat zniechęcano do ochrony bazy danych.

Jest więcej do zrobienia, ale to dobry początek

Bezpieczeństwo to znacznie więcej niż tylko szukanie funkcji w kodzie, które atakujący mogą nadużyć. Na przykład nie omawialiśmy zbyt szczegółowo potrzeby walidacji i oczyszczania wszystkich danych, które otrzymujesz od użytkowników, i unikania ich przed umieszczeniem ich na stronie internetowej (chociaż niedawno opublikowałem artykuł na ten temat: „Ochrona Twojego WordPressa Strona przeciwko atakowi Cross-Site Scripting”). Ale możesz i powinieneś używać tego jako części szerszej strategii bezpieczeństwa.

Trzymanie tej listy łatwych do nadużycia funkcji po swojej stronie podczas końcowej inspekcji przed wdrożeniem nowej wtyczki w WordPress to świetny pomysł. Ale warto również upewnić się, że ufasz bezpieczeństwu hostingu, upewnić się, że użytkownicy mają dobre hasła i wiele więcej.

Najważniejszą rzeczą do zapamiętania w kwestii bezpieczeństwa jest to, że twoje najsłabsze ogniwo jest tym, które ma znaczenie. Dobre praktyki w jednym obszarze wzmacniają ewentualne słabe punkty w innym, ale nigdy nie są w stanie ich całkowicie skorygować. Ale uważaj na te funkcje, a będziesz mieć przewagę nad większością.