W mechanizmach kryptograficznych wykorzystywanych w ASP.NET wykryty został błąd. Microsoft opublikował stosowny dokument: Vulnerability in ASP.NET Could Allow Information Disclosure. Informacje na temat tej podatności są nieco chaotyczne, ale z kontekstu można przypuszczać, że pozwala ona nie tylko na rozszyfrowanie danych i ustalenie klucza, którym zostały zaszyfrowane.
Wyrocznia w ASP.NET
Brzmi groźnie, bo jest to duży problem. W ASP.NET wykorzystywany jest między innymi __VIEWSTATE (patrz: Understanding ASP.NET View State), który jest ciekawym celem ataku. Nie chodzi nawet o ujawnienie danych, ale o możliwość ich modyfikacji.
Sposób zabezpieczenia __VIEWSTATE definiują parametry (patrz: pages Element (ASP.NET Settings Schema)):
- enableViewStateMac
- viewStateEncryptionMode
Domyślnie __VIEWSTATE nie musi być szyfrowany, natomiast jest zabezpieczony przez HMAC. Z tego powodu dane, choć mogą być podglądnięte, nie mogą być modyfikowane. Z samym __VIEWSTATE było trochę problemów wcześniej. Warto wspomnieć o:
- ASP.NET __VIEWSTATE crypto validation prone to replay attacks,
- Unencrypted view state in ASP.NET 2.0 could leak sensitive information,
Tym razem atak pozwala na więcej. Po odzyskaniu klucza atakujący jest w stanie nie tylko odczytać dane, ale również je zmodyfikować. Dobrze opisuje to ten fragment z agendy (Padding oracles everywhere):
Finally we demonstrate the attacks against real world applications. We use the Padding Oracle attack to decrypt data and use CBC-R to encrypt our modifications. Then we abuse components present in every ASP.NET installation to forge authentication tickets and access applications with administration rights. (...)
A tu przykładowy atak:
Zastanawiam się jeszcze nad proponowanymi w dokumencie Microsoftu obejściami problemu. Dla .NET Framework 3.5 RTM i starszych zalecane jest ustawienie statycznej strony błędów, dla nowszych natomiast strony dynamicznej, która zawiera kod generujący losowe opóźnienie. Czy to oznacza, że w nowszych wersjach .NET Framework poza wskazówką w komunikacie błędu jest również potencjał na timing attack? Jest to dość istotna kwestia, bo wykorzystanie "standardowych" stron błędów, nie tylko w ASP.NET, jest zwyczajowo raportowane jako podatność. Przy okazji warto odgrzebać temat timing attacks na OpenID i OAuth: Ataki czasowe na OpenID i OAuth (Twitter, Digg i Wikipedia podatne na atak), oraz komentarz Gynvaela.
Jeśli ktoś nie bardzo jest w stanie sobie wyobrazić do czego może prowadzić możliwość modyfikacji danych, zapraszam do mojego starego przykładu: Lekcja 17: Wyzwanie II, a w szczególności do wyjaśnienia sposobu obsługi sesji.
UPDATE: Dobrze mi się wydawało, że jest potencjał na timing attack, świadczy o tym ten wpis:
error message setting is irrelevant. no error? there's always HTTP status. always the same HTTP status? there's always big timing different
ScotGu uważa jednak, że różnica w czasie przetwarzania żądania we wszystkich trzech przypadkach jest na tyle mała, że timing attack jest mało prawdopodobny. Zwłaszcza po dodaniu niewielkiego losowego opóźnienia. Dalej nie rozumiem, dlaczego w przykładach losowe opóźnienie zalecane jest w nowszych wersjach .NET Framework, a w starszych "wystarczy" statyczna strona błędu.
> poza wskazówką w komunikacie błędu jest również
> potencjał na timing attack?
Opierając się na informacjach z http://www.gdssecurity.com/l/b/2010/09/14/automated-padding-oracle-attacks-with-padbuster/ jest możliwość ataku timingowego - w przypadku, kiedy po deszyfracji (tryb CBC) framework nie wykryje odpowiedniego bajtu/bajtów z paddingiem w ostatnim bloku, rzuca wyjątek. Gdy bajt ma odpowiednią wartość, do danych dostaje się aplikacja (i po walidacji odrzuca śmieciowe dane), co dodaje swój narzut czasowy.
Natomiast interesuje mnie co innego - w przytoczonym artykule jest informacja, że do zaszyfrowanych danych jest na początku doklejany plaintextem IV (co jest słabością wykorzystaną przez omawiane narzędzie). Czy tak rzeczywiście jest w ASP.NET? Czy w praktyce IV jest zmienny (jednorazowy) i przekazywany jawnie razem z ciphertextem, czy to tylko jakiś przykład konkretnej aplikacji? Ktoś zna mechanizm ASP.NETa pod tym kątem?
Druga sprawa - teoretycznie żądanie do ASP.NET może trafić na inny serwer (load balancing) i ten inny serwer musi być w stanie rozszyfrować otrzymane dane. Z tego co pamiętam w takim przypadku na wszystkich serwerach konfiguruje się te same klucze. A co do IV to jest szansa, że jest doklejany plaintextem na początku. Tak wynika z przykładu w tekście, który podałeś w linku.
Jeśli ktoś uważa, że za dużo opóźnień wprowadza sam Internet - polecam http://rdist.root.org/2010/01/07/timing-independent-array-comparison/
Dla .NET w wersjach 1.0 do 3.5, również można użyć dynamicznej strony błędów (.aspx'a) jednakże nic nie możemy poradzić na timing attack, ponieważ w sytuacji zaistnienia błędu na serwerze (np. wyjątku CryptographicException ) zawsze następuje przekierowanie(redirect 302) na stronę błędu więc atakujący jest w stanie zmierzyć czas wykonania pierwotnego requestu przed redirectem i nic z tym nie możemy zrobić. Jednakże od .NET 3.5 sp1 istnieje możliwość pokazania dowolnej strony błędu (dynamicznej czy statycznej) bez redirect'a .Dodając do takiej strony błędu skrypt generujący losowe opóźnienia skutecznie minimalizujemy szansę na skuteczny timing attack. Najważniejsze jednak jest to, żeby zawsze zwracać jedną, tą samą stronę błędu, niezależnie od rodzaju (kodu) tego błędu .