ASP.NET MS11-100: Wie kann ich das Limit für die maximale Anzahl der veröffentlichten Formularwerte ändern?

196

Microsoft hat kürzlich (29.12.2011) ein Update veröffentlicht, um mehrere schwerwiegende Sicherheitslücken in .NET Framework zu beheben. Eine der von MS11-100 eingeführten Korrekturen verringert vorübergehend einen potenziellen DoS-Angriff mit Hash-Tabellenkollisionen. Es scheint, dass dieser Fix Seiten bricht, die viele POST-Daten enthalten. In unserem Fall auf Seiten mit sehr großen Kontrollkästchenlisten. Warum sollte das so sein?

Einige nicht offizielle Quellen scheinen darauf hinzuweisen, dass MS11-100 ein Limit von 500 für Postback-Artikel festlegt. Ich kann keine Microsoft-Quelle finden, die dies bestätigt. Ich weiß, dass View State und andere Framework-Funktionen einen Teil dieser Grenze verschlingen. Gibt es eine Konfigurationseinstellung, die dieses neue Limit steuert? Wir könnten von der Verwendung von Kontrollkästchen abweichen, aber es funktioniert ziemlich gut für unsere spezielle Situation. Wir möchten den Patch auch anwenden, da er vor anderen unangenehmen Dingen schützt.

Inoffizielle Quelle zur Erörterung der 500-Grenze:

Das Bulletin behebt den DOS-Angriffsvektor, indem es die Anzahl der Variablen begrenzt, die für eine einzelne HTTP-POST-Anforderung gesendet werden können. Das Standardlimit liegt bei 500, was für normale Webanwendungen ausreichen sollte, aber immer noch niedrig genug, um den von den Sicherheitsforschern in Deutschland beschriebenen Angriff zu neutralisieren.

BEARBEITEN: Quellcode mit Beispiel für ein Limit (das 1.000 zu sein scheint, nicht 500) Erstellen Sie eine Standard-MVC-App und fügen Sie der Hauptindexansicht den folgenden Code hinzu:

@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>
}

Dieser Code funktionierte vor dem Patch. Es funktioniert danach nicht mehr. Der Fehler ist:

[InvalidOperationException: Der Vorgang ist aufgrund des aktuellen Status des Objekts nicht gültig.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded () +82 System.Web.HttpValueCollection.FillFromEncodedBytes (Byte [] encoding, Enc
. HttpRequest.FillInFormCollection () +307

Colithium
quelle
Wie wäre es mit zusätzlichen Beinarbeit und poste den Abschnitt, in dem speziell 500 steht.
OO
3
Das ist es. Es gibt keinen Abschnitt (von Microsoft). Nur von inoffiziellen Kommentatoren, die vielleicht wissen oder nicht, wovon sie sprechen. Ich habe trotzdem einen Link und einen Ausschnitt gepostet.
Colithium
1
@ Andrew: Die einzige "Mehrfachauswahlliste", die ich mir vorstellen kann, ist die ListBox mit SelectionMode auf Multiple. Dies könnte tatsächlich möglicherweise mehrere Werte veröffentlichen. In der Frage werden jedoch "Dropdown-Listen" erwähnt. Warten wir dann auf Kommentare des Autor der Frage.
Wiktor Zychla
1
Eine kürzlich durchgeführte Frage zu diesem Thema ergab, dass der Fix das DOS durch Begrenzung der Anzahl der Beiträge minderte.
John Saunders
1
Weitere Informationen hierzu finden Sie unter support.microsoft.com/kb/2661403 .

Antworten:

275

Versuchen Sie, diese Einstellung in web.config hinzuzufügen. Ich habe dies gerade unter .NET 4.0 mit einem ASP.NET MVC 2-Projekt getestet und mit dieser Einstellung wirft Ihr Code nicht:

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

Das sollte jetzt funktionieren (nachdem Sie das Sicherheitsupdate angewendet haben), um das Limit zu ändern.


Ich hatte meinen Computer noch nicht aktualisiert, also habe ich mit Reflector die HttpValueCollection-Klasse überprüft und sie hatte nicht die folgende ThrowIfMaxHttpCollectionKeysExceededMethode:

Geben Sie hier die Bildbeschreibung ein

Ich habe KB2656351 (Update für .NET 4.0) installiert , die Assemblys in Reflector neu geladen und die Methode wurde angezeigt :

Geben Sie hier die Bildbeschreibung ein

Diese Methode ist also definitiv neu. Ich habe die Option Disassemble in Reflector verwendet und nach dem, was ich anhand des Codes erkennen kann, wird eine AppSetting überprüft:

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

Wenn der Wert in der Datei web.config nicht gefunden wird, wird er auf 1000 in System.Web.Util.AppSettings.EnsureSettingsLoaded(eine interne statische Klasse) festgelegt:

 _maxHttpCollectionKeys = 0x3e8;

Außerdem hat Alexey Gusarov vor zwei Tagen über diese Einstellung getwittert:

Und hier ist eine offizielle Antwort von einem Q & A mit Jonathan Ness (Sicherheitsentwicklungsmanager, MSRC) und Pete Voss (Senior Response Communications Manager, Trustworthy Computing):

F: Ist AppSettings.MaxHttpCollectionKeys der neue Parameter, der die maximale Anzahl von Formulareinträgen enthält?

A: Ja, das ist es.

Michiel van Oosterhout
quelle
25
Wunderbar. Dies sind die Antworten, die mich dazu bringen,
Stackoverflow zu
4
Es hat wirklich geholfen, ich wünschte ich hätte einen anderen Account, damit ich +2 geben könnte :)
Mischa
1
Kann dies in applicationhost.config für den gesamten Server aktualisiert werden? oder machine.config?
Andryuha
1
Gibt es eine Möglichkeit, dieses Limit pro Seite zu steuern? (Auch hier und hier gefragt .)
Mike Guthrie
1
Einige Leute haben vorgeschlagen, die Webseite zu überprüfen, da sie diese vielen Formularfelder nicht enthalten sollte. Wir hatten jedoch ein sehr gültiges Szenario für diesen Fehler: Der Warenkorb auf einer der E-Commerce-Websites unserer Kunden enthielt viele Artikel, und dieser Fehler wurde protokolliert, als sie auf die Seite zugegriffen hat. In solchen Fällen ist das Überschreiben des Maximalwerts die beste Option.
Ankur-m
18

Für diejenigen unter Ihnen, die noch .NET 1.1 verwenden, wird diese Einstellung nicht über web.config konfiguriert - es handelt sich um eine Registrierungseinstellung (ein Tipp für michielvoo, da ich dies nur über Reflector auf die gleiche Weise herausgefunden habe, wie er die Antwort gefunden hat). Das folgende Beispiel ist MaxHttpCollectionKeysin 32-Bit-Editionen von Windows auf 5000 festgelegt:

Windows Registry Editor Version 5.00

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

Legen Sie für eine 64-Bit-Windows-Edition den Schlüssel unter dem Wow6432-Knoten fest:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
terranwannabe
quelle
Haben Sie Informationen darüber, ob 5000 ein relativ sicherer Wert in Bezug auf den DoS-Angriff ist, den diese Sicherheitsupdates abschwächen sollen? Wir versuchen, denselben Wert von 5000 zu verwenden, aber ich kann keine Informationen über die Beziehung zwischen der Anzahl der Werte und der pro Anforderung bei einem Angriff verbrauchten CPU-Zeit finden ...
Tao
4

Ich möchte hier nur meine $ 0,02 für Leute hinzufügen, die die Verrücktheit sehen.

Wenn Ihre Anwendung Seiteninformationen in ASP.NET ViewState speichert und den Schwellenwert für den Webserver überschreitet, tritt dieses Problem auf. Anstatt das Problem mit der Behebung von web.config sofort anzuwenden, sollten Sie zunächst einen Blick auf die Optimierung Ihres Codes werfen.

Zeigen Sie die Quelle an und suchen Sie nach mehr als 1000 versteckten Feldern im Ansichtsstatus. Sie haben Ihr Problem.

Augenlose Laune
quelle
1000+ Viewstate-Felder? Gibt es nicht nur ein ViewState-Feld im Formular? Der Wert nimmt mit zunehmender Anzahl der Formularfelder zu.
Ankur-m
3

ThrowIfMaxHttpCollectionKeysExceeded()wurde auch hinzugefügt System.Web.HttpCookieCollection.

Es sieht so aus, als würde HttpCookieCollection.Get()es angerufen, es ruft intern an und ruft HttpCookieCollection.AddCookie()dann an 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);
    }
}

Was wir sehen, ist, dass die Website über einen Zeitraum von ein paar Stunden immer langsamer und fehlerhafter wird, bis sie anfängt, die zu werfen InvalidOperationExcpetion. Anschließend recyceln wir den App-Pool, wodurch das Problem noch einige Stunden behoben wird.

Joshua Barker
quelle
Das Limit für die Anzahl der Cookies ist ein guter Fang. Wissen Sie, ob die von Ihnen beschriebene Verlangsamung und Fehlerhaftigkeit tatsächlich etwas mit der Anzahl der Cookies in den Anfragen zu tun hat? Haben Sie die Kundenanfragen überprüft, die Sie erhalten? (Tut Ihre App absichtlich etwas mit einer großen Anzahl von Cookies?)
Tao
1
Es stellte sich heraus, dass wir einen benutzerdefinierten CookieProvider hatten, der beim Start der App fälschlicherweise einen Singleton-Verweis auf die Request.Cookies-Sammlung abrief. Bei jeder nachfolgenden Anfrage wurde überprüft, ob ein oder mehrere Cookies in der statischen Cookie-Sammlung vorhanden waren ... wie Sie dem obigen Code entnehmen können, fügt .Net dieses Cookie standardmäßig hinzu, wenn es nicht gefunden wird. Im Laufe der Zeit, als jeder Benutzer auf das System zugegriffen hat, wurden dieser Singleton-Sammlung verschiedene Cookies hinzugefügt ... und da die Website für die Verwendung mit oder ohne Cookies konzipiert wurde, wurde dieser Fehler (bis jetzt) ​​nie identifiziert
Joshua Barker