- W empik go
Zabezpieczenie aplikacji internetowych w .NET - ebook
Zabezpieczenie aplikacji internetowych w .NET - ebook
Dla kogo jest ta książka
Ta książka jest kierowana dla osób programujących w .NET Core i .NET. Przeznaczona głównie dla juniorów i „midów”. Ale wierzę, że niejeden senior też znajdzie w niej coś ciekawego.
Książka zdecydowanie NIE JEST dla osób zajmujących się bezpieczeństwem aplikacji, administratorów ani hakerów.
Przykłady
Tworząc tę pracę, napisałem kilka projektów w .NET6, które ilustrują niektóre ataki i pokazują jak się przed nimi uchronić. Powinieneś pobrać ten kod i przeglądać go razem z książką. Solucja została stworzona w Visual Studio 2022. Kody znajdują się na GitHubie: https://github.com/AdamJachocki/Attacks
Motywacja
Często jest tak, że to jakiś szczegół decyduje o tym, czy aplikacja jest podatna na pewne ataki, czy nie. Najczęściej błędy popełniają juniorzy, ale u seniorów też zdarzyło mi się pewne rzeczy wychwycić podczas code review.
Sam kiedyś szukałem przystępnej wiedzy na temat podstawowego zabezpieczania aplikacji. Niestety nie udało mi się znaleźć żadnego dobrego opracowania ani konkretnych przykładów z opisami.
Gdy wchodzi się w świat aplikacji internetowych, na każdym rogu można spodziewać się ataku. I tu rodzą się pytania – czy moja aplikacja jest zabezpieczona? Czy rozumiem zagrożenia? Czy piszę bezpieczny kod? Czy tworzę głupie dziury?
Ta książka oczywiście nie wyczerpuje tematu, bo to studnia bez dna. Natomiast odpowiada na podstawowe pytania. Sam .NET ma sporo zabezpieczeń wbudowanych w siebie. Do tego stopnia, że musiałem pominąć kilka ataków, ponieważ w tej wersji (.NET 6) nie udało się ich przeprowadzić (np. Cross-Site-Scripting). Niemniej jednak .NET6 nie uchroni Cię przed wszystkim. Możesz sam wpakować się w dość poważne kłopoty.
Mam nadzieję, że ta książka poszerzy wiedzę w temacie i sprawi, że moje jak i Twoje aplikacje będą z założenia bardziej bezpieczne niż kiedykolwiek.
Po lekturze proponuję zrobić code review wybranych aplikacji, które utrzymujesz.
Kategoria: | Poradniki |
Zabezpieczenie: |
Watermark
|
ISBN: | 978-83-947977-0-6 |
Rozmiar pliku: | 244 KB |
FRAGMENT KSIĄŻKI
Cześć, nazywam się Adam Jachocki. Programuję od siódmego roku życia (1991 r), odkąd dorwałem się do książki „Atari BASIC dla dzieci”. Już wtedy wiedziałem, co będę w życiu robił.
Zawodowo zajmuję się programowaniem od 2005 roku. Przeszedłem przez wiele technologii, kilka języków i różne podejścia.
Jak każdy szanujący się programista, wciąż się rozwijam i uczę. Backend to jest to, co kręci mnie najbardziej.
Od jakiegoś czasu tworzę również bloga https://www.masterbranch.pl, na którym przedstawiam wiedzę głównie z zakresu .NET. Znajdziesz tam artykuły o wbudowanych mechanizmach, jak również bardziej ogólne porady (np. jak tworzyć aplikacje wielojęzyczne). Zapraszam.
Tworzyłem lub współtworzyłem systemy magazynowo-sprzedażowo-lojalnościowe, systemy ERP, RCP i kontroli dostępu. Współtworzyłem też oprogramowanie do obsługi targów, m.in. Camerimage.
Najciekawszym projektem, w którym brałem udział do tej pory był wg mnie multibiometryczny system identyfikacji osób do przeciwdziałania zagrożeniom terrorystycznym, który współtworzyłem razem z Wojskową Akademią Techniczną.WSTĘP
Dla kogo jest ta książka
Ta książka jest kierowana dla osób programujących w .NET Core i .NET. Przeznaczona głównie dla juniorów i „midów”. Ale wierzę, że niejeden senior też znajdzie w niej coś ciekawego.
Książka zdecydowanie NIE JEST dla osób zajmujących się bezpieczeństwem aplikacji, administratorów ani hakerów.
Przykłady
Tworząc tę pracę, napisałem kilka projektów w .NET6, które ilustrują niektóre ataki i pokazują jak się przed nimi uchronić. Powinieneś pobrać ten kod i przeglądać go razem z książką. Solucja została stworzona w Visual Studio 2022. Kody znajdują się na GitHubie: https://github.com/AdamJachocki/Attacks
Słowniczek
Klient – aplikacja, która wysyła żądanie do serwera. To może być np. przeglądarka internetowa.
Żądanie – informacja wysyłana przez klienta do serwera, w celu uzyskania odpowiedzi lub jakiegoś zasobu – np. pliku lub kodu HTML.
Odpowiedź – informacja wysyłana z serwera do klienta na podstawie otrzymanego żądania.
Frontend – część aplikacji internetowej widoczna dla użytkownika.
Backend – część aplikacji internetowej niewidoczna dla użytkownika. Dostępna jedynie na serwerze.
Dziura – inaczej podatność – kod programu (lub błędna konfiguracja), który sprawia, że aplikacja jest podatna na atak hakerski.
Ciasteczko, Cookie – dane przechowywane na komputerze użytkownika. Są wysyłane z żądaniem do serwera. Serwer też może wysłać ciastko do przeglądarki – wtedy przeglądarka powinna je zapisać. Ciastka są wykorzystywane m.in. w mechanizmie zapamiętywania zalogowanego użytkownika.
RESTful API – rodzaj komunikacji pomiędzy klientem a serwerem. Klient za pomocą odpowiednich żądań może działać na zasobach serwera (pobierać je, dodawać, usuwać). W tym kontekście klient jest rzadziej przeglądarką internetową, a zdecydowanie częściej specjalnym oprogramowaniem (zwanym również _api consumer_).
Hosting – usługa polegająca na utrzymywaniu strony na serwerze.
Hostingodawca – firma oferująca usługi hostingowe.
WebApplication – aplikacja internetowa stworzona w VisualStudio z szablonu RazorMVC lub RazorPages. Taka aplikacja domyślnie składa się ze stron prezentowanych użytkownikowi w przeglądarce. Może być to też aplikacja typu SPA (Single Page Application).
WebApi – aplikacja internetowa stworzona w VisualStudio z szablonu WebApi. Taka aplikacja domyślnie jest RESTowym API.
Potok – middleware pipeline – kolejność obsługi żądania przez komponenty. Potok konfiguruje się domyślnie w metodzie _Configure_ klasy _Startup_ w .NetCore.
ORM – Object Relational Mapper – to mechanizm, który mapuje rekordy bazodanowe na modele w Twojej aplikacji i na odwrót. Przykładami ORMów są: Entity Framework (Core), nHibernate, Dapper. Są to darmowe biblioteki, z którymi warto się zapoznać tworząc aplikacje bazodanowe.
Motywacja
Często jest tak, że to jakiś szczegół decyduje o tym, czy aplikacja jest podatna na pewne ataki, czy nie. Najczęściej błędy popełniają juniorzy, ale u seniorów też zdarzyło mi się pewne rzeczy wychwycić podczas _code review_.
Sam kiedyś szukałem przystępnej wiedzy na temat podstawowego zabezpieczania aplikacji. Niestety nie udało mi się znaleźć żadnego dobrego opracowania ani konkretnych przykładów z opisami.
Gdy wchodzi się w świat aplikacji internetowych, na każdym rogu można spodziewać się ataku. I tu rodzą się pytania – czy moja aplikacja jest zabezpieczona? Czy rozumiem zagrożenia? Czy piszę bezpieczny kod? Czy tworzę głupie dziury?
Ta książka oczywiście nie wyczerpuje tematu, bo to studnia bez dna. Natomiast odpowiada na podstawowe pytania. Sam .NET ma sporo zabezpieczeń wbudowanych w siebie. Do tego stopnia, że musiałem pominąć kilka ataków, ponieważ w tej wersji (.NET 6) nie udało się ich przeprowadzić (np. _Cross-Site-Scripting_). Niemniej jednak .NET6 nie uchroni Cię przed wszystkim. Możesz sam wpakować się w dość poważne kłopoty.
Mam nadzieję, że ta książka poszerzy wiedzę w temacie i sprawi, że moje jak i Twoje aplikacje będą z założenia bardziej bezpieczne niż kiedykolwiek.
Po lekturze proponuję zrobić _code review_ wybranych aplikacji, które utrzymujesz.OPEN REDIRECT
To kolejny ciekawy atak. Jeśli strona jest napisana niepoprawnie, to pozwala na wykradanie danych logowania w bardzo prosty sposób. A wszystko przez próbę ułatwienia życia.
Przykładowe projekty:
- 8-OpenRedirect-Fake
- 8-OpenRedirect-Genuine
Geneza
Wyobraź sobie, że trafiłeś na jakiś bardzo ciekawy artykuł w wyszukiwarce. Klikasz i widzisz komunikat mówiący o tym, że musisz się zalogować, żeby artykuł przeczytać.
Logujesz się do serwisu, bo akurat masz tam konto. I teraz mogą zadziać się dwie rzeczy:
- Zostaniesz przekierowany na stronę główną, co spowoduje zapewne atak szału, ponieważ będziesz musiał znowu wyszukać ten artykuł w czeluściach Internetu.
- Zostaniesz przekierowany do artykułu – super, tego chcemy.
Ja zdecydowanie wolę opcję drugą. Jest wygodniejsza. Ale daje podatność.
Jak działa open redirect?
Żeby to zrozumieć, zastanówmy się najpierw jak działa przekierowanie po logowaniu.
Załóżmy, że wchodzisz na stronę _www.example.com/super-artykul_. Strona _example.com_ widzi, że nie jesteś zalogowany, więc automatycznie przekierowuje Cię na stronę logowania, dodając do adresu parametr, np.:
www.example.com/login?return_url=/super-artykul
Dzięki temu serwis wie, że po poprawnym zalogowaniu ma Cię przekierować na stronę _/super-artykul_.
A teraz przemyślmy taki scenariusz. Otrzymujesz maila, który wygląda zupełnie jak wiadomość z banku o treści:
Dzień dobry,
_w związku z aktualizacją naszej polityki prywatności_ (albo super tajnego prawa bankowego)_, prosimy Cię o zweryfikowanie i ewentualną aktualizację Twoich danych osobowych. Zaloguj się i sprawdź poprawność danych: https://www.prawdziwy-bank.pl?return_url=https://prawdziwy-bankk.pl_
Zwróć uwagę na adres, na który ma być przekierowanie po logowaniu: _prawdziwy-bankk_ -> (podwójne ‘k’ na końcu) wygląda jak domena banku, ale nią nie jest.
Logujesz się. Teraz następuje przekierowanie do złej strony (zamiast do strony serwisu), która wygląda dokładnie tak samo jak strona prawdziwego serwisu i widzisz komunikat o niepoprawnym logowaniu. Logujesz się drugi raz – wracasz na stronę prawdziwego serwisu.
O tym ataku możesz się nigdy nie dowiedzieć. Możesz się dowiedzieć też dopiero po długim czasie. A atakujący posiada dane do Twojego konta. Jak to zrobić?
Do ataku!
Tym razem musisz uruchomić dwa projekty jednocześnie. Aby to zrobić, w Visual Studio w okienku _SolutionExplorer_, __ kliknij prawym klawiszem myszy na SOLUCJĘ i z menu wybierz _Properties_. W okienku, które się pojawi, wybierz zakładkę _CommonProperties -> Startup Project_. Teraz możesz wybrać dwa projekty startowe – to będzie _8-OpenRedirect-Fake_ i _8-OpenRedirect-Genuine_. Ustaw ich akcję na Start:
Projekty są już skonfigurowane w odpowiedni sposób.
Strona przykładowego banku otworzy się pod adresem: _https://localhost:8000_, natomiast strona kradnąca dane pod: _https://localhost:9000_. Potraktuj to jako dwa zupełnie inne adresy, jak np. _https://prawdziwy-bank.pl_ i _https://prawdziwy-bankk.pl_ (podwójne „k” na końcu)
Teraz po prostu wciśnij F5, żeby uruchomić te aplikacje (aplikacja oszukanego banku uruchomi się w tle, żeby wszystko odbyło się w jednym oknie przeglądarki).
Zobaczysz przykładową stronę jakiegoś banku z formularzem do logowania. Zwróć uwagę na to, co jest w pasku adresu przeglądarki. Zobaczysz tam adres: _https://localhost:8000/?return_url=https%3A%2F%2Flocalhost%3A9000_
Adres zawiera parametr _return_url_ – to jest url, na który zostaniesz przekierowany po poprawnym logowaniu. Ten adres jest symulacją, jakbyś kliknął na oszukany link.
Jak widzisz, w tym przypadku mamy pełny zewnętrzny adres http. Jeśli zdekodujesz sobie znaki specjalne, zobaczysz jako wartość tego parametru: _https://localhost:9000_
To jest adres drugiej strony, którą uruchomiłeś – strony kradnącej dane.
Spójrzmy teraz w kod logowania na stronie banku:
public async Task
{
if (!ModelState.IsValid)
return Page();
//symulacja logowania
bool loginResult = await LoginUser(LoginData);
if (loginResult)
return RedirectUserAfterValidLogin(ReturnUrl);
else
return RedirectToPage();
}
Logujemy użytkownika. Następnie, po prawidłowym logowaniu (co w przypadku tego testu zawsze jest prawdą), następuje przekierowanie na stronę wskazaną w parametrze _ReturnUrl_:
IActionResult RedirectUserAfterValidLogin(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl))
return RedirectToPage("/Index");
else
return Redirect(returnUrl);
}
Wpisz teraz do formularza jakikolwiek login i hasło i wciśnij przycisk zaloguj.
Logowanie powiodło się, zostałeś przekierowany do strony kradnącej hasła. A jak ta strona wygląda? Dokładnie tak, jak strona _Twojego Banku_.
Widzisz komunikat o niepoprawnym logowaniu, więc automatycznie logujesz się jeszcze raz – tyle że tym razem przekazujesz swoje dane logowania atakującemu (projekt _8-OpenRedirect-Fake_) – bo jesteś w formularzu na stronie hakera:
public async Task
{
Console.WriteLine("User: " + LoginData.UserName);
Console.WriteLine("Hasło: " + LoginData.Password);
return Redirect("https://localhost:8000");
}
Atakujący zapisuje sobie Twoje dane logowania i przekierowuje Cię z powrotem na stronę banku – na której już jesteś zalogowany (bo zalogowałeś się chwilę wcześniej).
Sprytne, prawda?
Jak uniknąć podatności?
Spójrz jeszcze raz, jak jest zrobione przekierowanie na prawdziwej stronie banku:
IActionResult RedirectUserAfterValidLogin(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl))
return RedirectToPage("/Index");
else
return Redirect(returnUrl);
}
Problemem tutaj jest metoda _Redirect_, która pozwala na przekierowanie na DOWOLNY adres – w tym przekierowanie do zewnętrznego serwisu.
Przy logowaniu musisz się upewnić, że nie przekierowujesz użytkownika do zewnętrznego serwisu. Możesz to zrobić na dwa sposoby:
- Nie stosuj metody _Redirect_, chyba że chcesz przekierować jawnie użytkownika na adres zewnętrzny
- Użyj metody _RedirectToPage_ (lub _RedirectToView_ w MVC) zamiast _Redirect_ – Metoda _RedirectToPage_ przekieruje Cię tylko na stronę wewnętrzną. W takim przypadku spróbowałaby przekierować na: _https://localhost:8000/https://localhost:9000_ i dostałbyś błąd 404.
- Upewnij się, że adres na który przekierowujesz jest wewnętrznym:
if (Url.IsLocalUrl(ReturnUrl))
return Redirect(ReturnUrl);
else
return Redirect("/Index");
Ja w swoich rozwiązaniach stosuję zawsze _RedirectToPage_ (_RedirectToView_). To jest po prostu wygodne.