ASP.NET MS11-100: jak mogę zmienić limit maksymalnej liczby wysyłanych wartości formularza?

196

Firma Microsoft niedawno (12-29-2011) wydała aktualizację mającą na celu usunięcie kilku poważnych luk w zabezpieczeniach systemu .NET Framework. Jedna z poprawek wprowadzonych przez MS11-100 tymczasowo ogranicza potencjalny atak DoS obejmujący kolizje tabeli mieszającej. Wygląda na to, że ta poprawka rozbija strony zawierające dużo danych POST. W naszym przypadku na stronach, które mają bardzo duże listy pól wyboru. Dlaczego miałoby tak być?

Niektóre nieoficjalne źródła wydają się wskazywać, że MS11-100 nakłada limit 500 na przedmioty z późniejszym opóźnieniem. Nie mogę znaleźć źródła Microsoft, które to potwierdza. Wiem, że View State i inne funkcje ramowe pochłaniają część tego limitu. Czy jest jakieś ustawienie konfiguracji, które kontroluje ten nowy limit? Możemy zrezygnować z używania pól wyboru, ale działa to całkiem dobrze w naszej konkretnej sytuacji. Chcielibyśmy również zastosować łatkę, ponieważ chroni ona przed innymi nieprzyjemnymi rzeczami.

Nieoficjalne źródło omawiające limit 500:

Biuletyn naprawia wektor ataku DOS, określając limit liczby zmiennych, które można przesłać dla pojedynczego żądania HTTP POST. Domyślny limit to 500, co powinno wystarczyć na normalne aplikacje internetowe, ale wciąż wystarczająco niskie, aby zneutralizować atak, jak opisali badacze bezpieczeństwa w Niemczech.

EDYCJA: Kod źródłowy z przykładem limitu (który wydaje się być 1000, a nie 500) Utwórz standardową aplikację MVC i dodaj następujący kod do głównego widoku indeksu:

@using (Html.BeginForm()) 
{
    <fieldset class="fields">
        <p class="submit">
            <input type="submit" value="Submit" />
        </p>

        @for (var i = 0; i < 1000; i++)
        {
            <div> @Html.CheckBox("cb" + i.ToString(), true) </div>
        } 
    </fieldset>
}

Ten kod działał przed łatką. Po tym nie działa. Błąd jest następujący:

[InvalidOperationException: Operacja jest niepoprawna z powodu bieżącego stanu obiektu.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded () +82 System.Web.HttpValueCollection.FillFromEncodedBytes (kodowanie bajtowe [1])
. HttpRequest.FillInFormCollection () +307

kolithium
źródło
Co powiesz na odrobinę dodatkowej pracy nóg i opublikuj sekcję, w której jest napisane konkretnie 500.
OO
3
To jest myśl. Nie ma sekcji (od Microsoft). Tylko od nieoficjalnych komentatorów, którzy mogą, ale nie muszą wiedzieć, o czym mówią. Mimo to opublikowałem link i fragment kodu.
colithium
1
@Andrew: Jedyną „listą wielokrotnego wyboru”, jaką mogę wymyślić, byłby ListBox z SelectionMode ustawionym na Wiele. To rzeczywiście może potencjalnie zaksięgować wiele wartości. Jednak w pytaniu wspomniano o „listach rozwijanych”. Poczekajmy więc na wszelkie komentarze autora pytania.
Wiktor Zychla,
1
Ostatnie pytanie na ten temat ustaliło, że poprawka zmniejszyła DOS, ograniczając liczbę postów.
John Saunders,
1
Szczegółowe informacje na ten temat można znaleźć na stronie support.microsoft.com/kb/2661403 .

Odpowiedzi:

275

Spróbuj dodać to ustawienie w pliku web.config. Właśnie przetestowałem to na .NET 4.0 z projektem ASP.NET MVC 2 i przy tym ustawieniu twój kod nie rzuca:

<appSettings>
  <add key="aspnet:MaxHttpCollectionKeys" value="1001" />
</appSettings>

To powinno działać teraz (po zastosowaniu aktualizacji zabezpieczeń), aby zmienić limit.


Nie zaktualizowałem jeszcze komputera, więc za pomocą Reflectora sprawdziłem klasę HttpValueCollection i nie miałem ThrowIfMaxHttpCollectionKeysExceededmetody:

wprowadź opis zdjęcia tutaj

Zainstalowałem KB2656351 (aktualizacja .NET 4.0), ponownie załadowałem zestawy w Reflector i pojawiła się metoda:

wprowadź opis zdjęcia tutaj

Ta metoda jest zdecydowanie nowa. Użyłem opcji Disassemble w Reflector i z tego, co mogę stwierdzić po kodzie, sprawdza AppSetting:

if (this.Count >= AppSettings.MaxHttpCollectionKeys)
{
  throw new InvalidOperationException();
}

Jeśli nie znajdzie wartości w pliku web.config, ustawi ją na 1000 in System.Web.Util.AppSettings.EnsureSettingsLoaded(wewnętrzna klasa statyczna):

 _maxHttpCollectionKeys = 0x3e8;

Również Aleksiej Gusarow napisał na Twitterze o tym ustawieniu dwa dni temu:

I tu jest oficjalną odpowiedź z Q & A z Jonathan Ness (bezpieczeństwo Development Manager MSRC) i Pete Voss (s Response Communications Manager, Trustworthy Computing):

P: Czy AppSettings.MaxHttpCollectionKeys nowy parametr, który zawiera maksymalną liczbę pozycji formularza?

Odp .: Tak, to prawda.

Michiel van Oosterhout
źródło
25
Wspaniale. To są takie odpowiedzi, które sprawiają, że uwielbiam
przepełnienie stosu
4
To naprawdę pomogło, chciałbym mieć inne konto, abym mógł dać +2 :)
misha
1
czy można to zaktualizować w applicationhost.config dla całego serwera? lub machine.config?
andryuha
1
Jakiś sposób kontrolować ten limit na poziomie strony? (Pytany także tutaj i tutaj .)
Mike Guthrie
1
Niektóre osoby sugerują przejrzenie strony internetowej, ponieważ nie powinna ona zawierać tak wielu pól formularza. Ale mieliśmy bardzo ważny scenariusz dla tego błędu - koszyk w jednej z witryn eCommerce naszego klienta zawierał wiele przedmiotów i ten błąd był rejestrowany, gdy uzyskiwała dostęp do strony. W takich przypadkach przesłonięcie wartości maksymalnej jest najlepszą opcją.
Ankur-m
18

Dla tych z was, którzy nadal używają .NET 1.1, to ustawienie nie jest konfigurowane przez web.config - jest to ustawienie rejestru (wskazówka dla Michielvoo, ponieważ odkryłem to tylko przez Reflector w ten sam sposób, w jaki znalazł odpowiedź). Poniższy przykład ustawia MaxHttpCollectionKeysna 5000 w 32-bitowych wersjach systemu Windows:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388

W 64-bitowej wersji systemu Windows ustaw klucz pod węzłem Wow6432Node:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
terranwannabe
źródło
Czy masz jakieś informacje, czy 5000 jest względnie bezpieczną wartością w odniesieniu do ataku DoS, który ta poprawka bezpieczeństwa ma złagodzić? Patrzymy na użycie tej samej wartości 5000, ale nie mogę znaleźć żadnych informacji na temat związku między liczbą wartości a czasem procesora zużywanym na żądanie w ataku ...
Tao
4

Chcę tylko dodać tutaj 0,02 USD za osoby, które widzą dziwność.

Jeśli aplikacja ukrywa informacje o stronie w ASP.NET ViewState i przekracza próg serwera WWW, napotkasz ten problem. Zamiast od razu rozwiązać problem z web.config, możesz najpierw spróbować zoptymalizować swój kod.

Wyświetl źródło i poszukaj ponad 1000 ukrytych pól stanu wyświetlania, a masz problem.

Kaprys bez oczu
źródło
Ponad 1000 pól stanu? Czy w formularzu nie ma tylko jednego pola ViewState. Wartość wzrasta wraz ze wzrostem liczby pól formularza.
Ankur-m
3

ThrowIfMaxHttpCollectionKeysExceeded()został również dodany do System.Web.HttpCookieCollection.

Wygląda na to, że kiedy HttpCookieCollection.Get()jest wywoływany, to dzwoni wewnętrznie HttpCookieCollection.AddCookie(), a następnie dzwoni ThrowIfMaxHttpCollectionKeysExceeded().

public HttpCookie Get(string name)
{
    HttpCookie cookie = (HttpCookie) base.BaseGet(name);
    if ((cookie == null) && (this._response != null))
    {
        cookie = new HttpCookie(name);
        this.AddCookie(cookie, true);
        this._response.OnCookieAdd(cookie);
    }
    return cookie;
}

internal void AddCookie(HttpCookie cookie, bool append)
{
    this.ThrowIfMaxHttpCollectionKeysExceeded();
    this._all = null;
    this._allKeys = null;
    if (append)
    {
        cookie.Added = true;
        base.BaseAdd(cookie.Name, cookie);
    }
    else
    {
        if (base.BaseGet(cookie.Name) != null)
        {
            cookie.Changed = true;
        }
        base.BaseSet(cookie.Name, cookie);
    }
}

Widzimy, że w ciągu kilku godzin strona staje się coraz wolniejsza i bardziej błędna, dopóki nie zacznie się rzucać InvalidOperationExcpetion. Następnie przetwarzamy pulę aplikacji, co rozwiązuje problem przez kilka godzin.

Joshua Barker
źródło
Limit liczby plików cookie to dobry połów; W przypadku opisywanego spowolnienia i błędów, czy wiesz, czy rzeczywiście ma to coś wspólnego z liczbą plików cookie w żądaniach? Czy sprawdziłeś otrzymywane żądania klientów? (czy twoja aplikacja celowo robi coś z dużą liczbą ciasteczek?)
Tao
1
okazuje się, że mieliśmy niestandardowego CookieProvider, który niepoprawnie pobierał odwołanie singletonowe do kolekcji Request.Cookies podczas uruchamiania aplikacji, a następnie przy każdym kolejnym żądaniu sprawdzał, czy w statycznej kolekcji plików cookie istnieje jeden lub więcej plików cookie ... jak widać z powyższego kodu .NET ADDS domyślnie zapisuje ten plik cookie, jeśli go nie znaleziono. Z czasem, gdy każdy użytkownik uzyskiwał dostęp do systemu, do tej kolekcji singletonów dodawano różne pliki cookie ... a ponieważ witryna została zaprojektowana do pracy z plikami cookie lub bez nich, ten błąd nigdy nie został zidentyfikowany (do tej pory)
Joshua Barker,