Najważniejsze zagadnienia, które musisz znać
5 godz. 53 min · JavaScript · Full-stack i Programowanie
Adam GospodarczykPrzesyłanie oraz transformacja danych to jeden z najważniejszych elementów działania każdej aplikacji. Dobre zrozumienie tego w jaki sposób odbywa się ten proces, daje równocześnie lepsze zrozumienie całej struktury oraz podejmowania decyzji projektowych. W tym kursie znajdziesz lekcje, które pozwolą Ci uporządkować wiedzę na temat protokołu HTTP oraz formatów wymiany danych.
REST oraz GraphQL to nadal nieodłączone zagadnienia tematu wymiany informacji w kontekście aplikacji webowych. Pomimo tego, że ich koncepcje zwykle są bardzo dobrze opisane w różnych źródłach, tak ich wykorzystanie "na produkcji" potrafi sprawić problemy. W szczególności gdy weźmiemy pod uwagę, wyjątki oraz fakt, że nie każda aplikacja będzie wymagać implementacji REST czy GraphQL w 100%. W tym kursie znajdziesz wiele praktycznych wskazówek związanych z pracą z REST API oraz wprowadzenie do pracy z GraphQL.
Niektóre błędy w aplikacji są bardzo pożądane, w szczególności gdy jasno informują użytkownika o tym, co się wydarzyło oraz o tym, co może z tym zrobić. Pomimo tego, że w wielu przypadkach opracowanie komunikatów leży w rękach osoby odpowiedzialnej za copywriting (i/lub ux writing), tak sama implementacja tych komunikatów odbywa się po stronie kodu. Nie rzadko okazuje się, że poprawna i skuteczna walidacja danych oraz obsługa błędów nie jest oczywista w "produkcyjnych" sytuacjach. W tym kursie znajdziesz najczęściej spotykane problemy oraz sposoby ich rozwiązania.
Bazy danych są praktycznie nieodłączną częścią każdej aplikacji. W roli full-stacka prędzej czy później przyjdzie Ci z nimi pracować a nie rzadko nawet projektować oraz rozbudowywać ich struktury. W tym kursie znajdziesz informacje o bazach danych, które pozwolą Ci je zrozumieć oraz od razu poznać użyteczne techniki, które pomogą Ci w pracy z nimi, zarówno na produkcji jak i w środowisku lokalnym czy testowym.
Nie wszystkie informacje w aplikacji są publiczne. Niektóre wprost nie mogą takie być. Z tego powodu niezbędne są sposoby na to aby poznać a potem weryfikować tożsamość użytkownika, by na jej podstawie przydzielać mu dostęp wyłącznie do zasobów, do których odczytywania posiada uprawnienia. Istnieje wiele technik, które umożliwiają zarządzanie dostępem do danych i w tym kursie poznasz najważniejsze z nich. Dowiesz się nie tylko w jaki sposób zabezpieczać dane ale poznasz też najpopularniejsze sposoby na to aby te zabezpieczenia łamać i obchodzić. Mając świadomość takiej możliwości, będziesz w stanie lepiej podejmować decyzje o tym jak projektować dostęp do informacji.
Istnieją problemy charakterystyczne dla niemal każdej aplikacji. W związku z ich powszechnością, istnieje też szereg rozwiązań lub sposobów na to, aby możliwie zredukować ich następstwa. Na przestrzeni lekcji tego kursu zobaczysz wiele przykładów, które pomogą Ci w codziennej pracy a niekiedy nawet, pozwolą uniknąć błędów, których konsekwencje nie zawsze występują natychmiast.
Kurs powstał z myślą o osobach, które chcą rozwijać się w roli full-stack web developera / developerki, przeprowadzając przez najważniejsze zagadnienia z obszaru wymiany, transformacji oraz przechowywania informacji w aplikacji oraz pomiędzy aplikacjami. Jeżeli potrzebujesz zobaczyć szeroką perspektywę tego, w jaki sposób dane przepływają pomiędzy różnymi częściami aplikacji, lub ugruntować swoją wiedzę na ten temat, to ten kurs jest miejscem, którego szukasz.
Bezpieczeństwo aplikacji webowych to bez
wątpienia bardzo istotny i jednocześnie rozległy temat.
Z tego powodu nie jesteśmy w stanie pokryć
go całkowicie, ale mam nadzieję, że widzisz to jak na przestrzeni wszystkich
lekcji i opracowanych przeze mnie materiałów.
Staram się przynajmniej zwracać uwagę na
pewne obszary, o których po prostu trzeba pamiętać.
Najciekawsze w tym wszystkim jest to, że te najczęstsze problemy dotyczące błędów
security wynikają nie tyle ze skomplikowanych rodzajów ataków, tylko po
prostu z ludzkiej pomyłki bądź w wyniku zaniedbania.
Mowa tutaj np.
o niezabezpieczonych ścieżkach, bądź też
nie ustawianiu odpowiednich limitów dla wprowadzanych przez użytkownika pól.
O tym wszystkim już do tej pory mówiliśmy.
Natomiast istnieje jeszcze rodzaj ataków,
które można przeprowadzić w sposób celowy, a dodatkowo w tym wszystkim trzeba
wykorzystać mniej lub bardziej złożone techniki ataku.
Mam tutaj na myśli przede wszystkim ataki typu C, strefy oraz XSS.
Jeżeli chodzi o ten pierwszy, to mowa tutaj o sytuacji, w której użytkownik jest
w jakiś sposób zmuszony bądź bardziej zachęcony jakimś podstępem do tego, aby
podjąć działanie, którego efektem z kolei jest wykonanie jakiejś niepożądanej akcji.
Przykładem może być zachęcenie użytkownika
do tego, aby przeszedł do konkretnej strony i tym samym nieświadomie wykonał
operację, którą normalnie musiałby wykonać np.
za pomocą formularza.
Tutaj akurat w tym przypadku mówimy o kliknięciu w link.
Natomiast jak pewnie wiesz, przykładowo obrazki pobierane są również z pomocą
zapytania typu GET, do którego można przekazać parametry.
Oznacza to, że użytkownik często nawet nie musi w nic klikać, tylko po prostu przejść
na stronę, na której pozornie wyświetli się jakiś obrazek.
Natomiast pod parametr Cel zostanie
podstawiony taki oto link, który pozwoli nie doprowadzić do tej niepożądanej akcji.
Tego rodzaju ataki działają również w
sytuacji, gdy mamy do czynienia z zapytaniami typu post.
Po prostu wtedy użytkownik zostaje
przekierowany do strony, w której faktycznie osadzony jest jakiś formularz,
który wysyłany jest z pomocą prostego kodu JavaScript.
Na koniec dnia zatem chodzi tutaj wyłącznie o to, aby w jakiś sposób
doprowadzić do sytuacji, w której użytkownik podejmie jakieś działanie,
które uruchomi akcję przygotowaną w taki sposób, jak gdyby wykonał ją samodzielnie.
Z tą różnicą, że w tym przypadku np.
parametry podstawione są w sposób, którego nie spodziewa się użytkownik.
I tutaj, jeżeli chodzi o zabezpieczenie się przed tego rodzajem ataków jest
wykorzystanie autoryzacji opartej o local storage bądź session storage.
W takiej sytuacji, nawet jeżeli użytkownik przypadkowo wczyta obrazek z podstawionym
w ten sposób linkiem, to w żaden sposób nie wykona się tutaj kod JavaScript, który
będzie odpowiedzialny za to, aby dołączyć odpowiednie informacje np.
token j wt, który znajduje się chociażby w Local Storage.
Zatem pierwszym sposobem przeciwdziałania
atakom CSS jest po prostu uwierzytelnienie naszego połączenia za pomocą danych
przekazywanych w formie nagłówka za pomocą JavaScriptu.
Drugim sposobem jest też wykorzystanie ciasteczek, które również z pomocą
JavaScriptu przekazywane są w celu uwierzytelnienia połączenia.
Takie ciasteczko w przypadku REST API oczywiście nie może być klasyczną sesją,
która jest przechowywana po stronie serwera.
Ze względu na to, że wtedy naruszamy jedną z fundamentalnych zasad, to jest.
Czyli oczywiście Styles.
Teoretycznie więc okazuje się, że najlepszym sposobem zabezpieczenia się
przed atakami CSS jest wykorzystanie sposobów uwierzytelnienia np.
Jamesa Web Token, które po prostu zostają
za każdym razem przez JavaScript dołączane do naszego zapytania.
W takiej sytuacji przeglądarka nie jest w stanie tego samodzielnie zrobić i tym
samym ataki takie jak wejście na ten link nie będą tutaj skuteczne.
Jednocześnie, jak być może już wiesz, w momencie, gdy mamy do czynienia z
aplikacją, która wykorzystuje sesję, informacja o niej dołączana jest
automatycznie przez przeglądarkę do każdego zapytania.
Podobnie zresztą dzieje się w momencie, gdy przekazujemy token jw
z pomocą ciasteczka, które ma włączone flagę http only.
Oznacza to, że w obu tych przypadkach jesteśmy narażeni na ten rodzaj ataków.
I teraz przykładowo jeżeli przejdziemy
sobie do dokumentacji frameworka Laravel, w przypadku którego
zwykle domyślnie wykorzystywane są sesje do tego, aby uwierzytelnić połączenie.
I z tego powodu ten framework domyślnie wykorzystuje tzw.
tokeny CSS, które zabezpieczają przed tego rodzaju atakiem.
Taki token należy dołączyć np.
do meta tagu bądź bezpośrednio do formularza, który jest osadzane w widoku.
W zależności od potrzeby taki token albo
trafia właśnie do formularza w formie ukrytego pola, które wysyłany jest na
serwer lub też ewentualnie tak jak w tym przykładzie, token odczytywany jest z tagu
meta, a jego zawartość przesyłana jest razem z nagłówkiem.
Oznacza to, że nawet jeżeli mamy tutaj z
sytuacją, w której użytkownik wchodzi na stronę, która próbuje wykonać takie oto
zapytanie, to w takim przypadku token, o którym mówimy tutaj nie jest dostępny i
tym samym próba wykonania tego zapytania nie powiedzie się.
Dodatkowo oczywiście taki token może teoretycznie zostać wykradzione i z tego
powodu on również posiada datę wygaśnięcia.
W ten sposób jesteśmy zabezpieczeni na ten rodzaj ataków.
Jednocześnie nawet przygotowując się do tego materiału, zastanawiałem się, czy
jest sens wykorzystywać ten token w przypadku.
REST API, gdzie wykorzystujemy i ciasteczko z flagą http only.
Okazuje się, że zdania są w tym temacie mocno podzielone.
Jedni mówią, że w takim przypadku istnieje
taka potrzeba, a drudzy wręcz przeciwnie mówią, że jest to całkowicie nie wymagane.
Jak dokładnie jest? Niestety dość trudno mi odpowiedzieć.
Jednocześnie w tym wszystkim trafiłem na
świetną stronę, na której możemy poczytać sobie między innymi o tego rodzaju atakach
oraz sposobach zabezpieczania się przed nimi.
W skrócie okazuje się, że w przypadku REST
API warto wykorzystać przechowywanie tokena właśnie w Local Storage i tym samym
narazić się na ataki typu XSS, o których powiemy za chwilę, ale jednocześnie
zabezpieczyć się na ewentualność ich wystąpienia.
Z drugiej jednak strony spotkałem się z
komentarzami takimi jak ten, które mówią jasno o tym, że w przypadku jw.
Należy wykorzystać bezpieczne połączenie
HTTPS oraz dodatkowo przekazywać ten token właśnie w formie niedostępnej z poziomu
JavaScriptu, czyli za pomocą ciasteczka HTTP z dodatkową flagą Secure.
Mało tego, należy tutaj dodać
uwzględnienie zabezpieczenia kod, o którym mówiliśmy w jednej z poprzednich lekcji.
Zatem pamiętaj proszę o tym, aby w
momencie gdy konfigurujesz swój serwer wykorzystać np.
middleware Helmet do tego, aby
automatycznie dodać zestaw wymaganych nagłówków w kontekście security, no i
oczywiście poprawnie skonfigurować kod tak aby nie doszło do sytuacji, w której można
wykonać zapytanie do naszej aplikacji z poziomu jakiejś zewnętrznej domeny.
Jednocześnie pamiętaj proszę o tym, że w
niektórych przypadkach chcemy doprowadzić do sytuacji, w której zewnętrzna domena
będzie musiała kontaktować się z naszą aplikacją.
W związku z tym, jak widzisz odpowiedź na pytanie w jaki sposób przechowywać tokeny
czy też w ogóle uwierzytelnić połączenie, bynajmniej nie jest tutaj oczywista.
I uwierz mi, że pomimo tego, że spędziłem kilka dni nad tym, aby dotrzeć do różnych
materiałów, które pozwoliłyby mi jasno odpowiedzieć na to, który sposób należy
wybrać, w jakiej sytuacji tak naprawdę sytuacja jest tutaj zbyt skomplikowana.
Ale jednocześnie na koniec tej lekcji
podzielę się z Tobą moimi wnioskami, opartymi również o moje doświadczenie.
Tymczasem przejdźmy do drugiego rodzaju ataku, jakim jest XSS, czyli jakiś sposób
na wykonanie złośliwego kodu, którego stroną może być np.
wykradzenie tokenu uwierzytelniające.
Przykładowo, jeżeli w ramach Local
Strategy bądź Session Storage przechowujemy Flash token, taki kod może
doprowadzić do sytuacji, w której ten token zostanie przesłany do atakującego.
Dzięki temu on będzie mógł wykorzystać ten
token, a następnie działać jak normalnie zalogowany użytkownik.
Podobnie jak w przypadku poprzedniego
ataku, mówimy tutaj o sytuacji, w której użytkownik najczęściej jakimś podstępem
zachęcany jest do tego, aby kliknąć w stronę, która zawiera zmodyfikowany kod,
który w tym przypadku wykonuje jakieś złośliwe działanie.
No i tutaj w tej sytuacji zabezpieczeniem się przed tego rodzajem ataków jest np.
wykorzystanie tego http only kuki, czyli
takiego, które nie jest dostępne z poziomu kodu JavaScript, bądź też ewentualnie
sesji, w przypadku których również możemy zabezpieczyć się na taki rodzaj ataków.
Jednocześnie wybierając ten sposób, jak pamiętasz, narażamy się na ataki CSS,
przed którymi również musimy się zabezpieczyć.
Zasadniczo jednak, jeżeli chodzi o ataki
dotyczące złośliwych skryptów, należy przede wszystkim upewnić się, że nie ufamy
użytkownikowi, który wprowadza jakiekolwiek dane do naszej aplikacji.
Czyli tak jak już powtarzałem
wielokrotnie, za każdym razem upewniamy się, że przykładowo użytkownik może
przesłać wyłącznie dane, których się spodziewamy i dodatkowo zweryfikujemy ich
typ oraz na rzucimy różnego rodzaju ograniczenia, np.
dotyczące długości.
W ten sposób minimalizujemy ryzyko tego,
że złośliwy skrypt faktycznie wykona się z powodzeniem.
Dodatkowo mamy również mechanizmy takie
jak Sanity, czyli po prostu usuwanie pozornie
niebezpiecznych znaków z danych przesyłanych przez użytkownika.
Najprostszym możliwym przykładem jest moment dodawania komentarza, w której
użytkownik mógłby wpisać kod JavaScript, który w momencie, gdy trafi w sposób
bezpośredni do naszego serwera, a następnie wyświetlony innym użytkownikom
właśnie w formie komentarza, zadziała tak, że nie wyświetli się w formie tekstu,
tylko zostanie wykonane przez przeglądarkę.
Oczywiście przed czymś takim musimy się odpowiednio zabezpieczyć.
I ostatecznie, tak jak powiedziałem, możemy jeszcze rozważyć wykorzystanie http
only kuki i tutaj uwzględnić przy tym ewentualną ekspozycję na ataki CSS.
Zanim przejdziemy do podsumowania, dodam
jeszcze, że całkiem dobrym pomysłem jest przejrzenie zarówno wcześniej wspomnianego
przeze mnie linku, jak i innych materiałów dotyczących sposobów ataków.
Im lepiej będziemy je rozumieć, tym lepiej
będziemy rozumieć sposoby zabezpieczenia się przed nimi.
I tutaj mamy przykładowo listę styli,
petów, kodu, które w różnych sytuacjach mogą okazać się niebezpieczne.
Nabywając wiedzę na ich temat możemy podejmować lepsze decyzje dotyczące
uwierzytelnienia, połączenia i sposobów zabezpieczenia się przed takimi atakami.
Jednocześnie jeżeli chciałbym podsumować teraz tą całą lekcję, powiedziałbym tak,
że w momencie gdy masz do czynienia z aplikacją wykorzystującą sesja, koniecznie
wykorzystaj token CSS do tego, aby zabezpieczyć.
Sposób uwierzytelnienia.
Z kolei w momencie, gdy wykorzystujesz REST API możesz albo podobnie jak ja w
większości przypadków wykorzystać ciasteczko http only z dodatkową flagą
secure oraz odpowiednim dbaniem o nagłówki i te najbardziej wymagane aktywności
związane z kontrolą danych wprowadzanych przez użytkownika.
Ewentualnie, jeżeli ten sposób nie jest
dla Ciebie właściwy, pamiętaj proszę o tym, że możesz przechowywać ciastko w
Local Storage bądź Session Storage, natomiast wtedy już definitywnie musisz
uwzględnić zabezpieczenie się przed atakami XSS.
No to teraz mam nadzieję, że ta lekcja i to, co powiedziałem, przynajmniej zwrócić
Twoją uwagę właśnie na ten obszar dotyczący różnego rodzaju ataków, na które
może zostać narażona Twoja aplikacja, jest tutaj?
Nie.
Niewykluczone, że przyjdzie Ci się mierzyć z mojej strony.
Zachęcam Cię do tego, aby przeglądać sobie
materiały dotyczące różnego rodzaju ataków i też form zabezpieczeń.
Potem wykorzystując tą wiedzę możesz zestawić to z potrzebami Twojej aplikacji
oraz wykorzystywanym przez Ciebie sposobem komunikacji.
W ten sposób będziesz dążyć do tego, aby zminimalizować ryzyko ataku, bądź też
ewentualnie w momencie, gdy wystąpi skutecznie uniemożliwić jego sukces.
Oczywiście w tym wszystkim polecam jeszcze warstwę monitorowania swojej aplikacji, w
tym wykorzystania systemu logów do tego, aby nie tylko przeciwdziałać, ale również
w momencie, gdy ewentualny atak wystąpi, być w stanie namierzyć jego źródło i
poradzić sobie z ewentualnymi konsekwencjami.
Tymczasem dzięki za uwagę i zapraszam Cię do kolejnej lekcji.