ASP.NET MS11-100: comment modifier la limite du nombre maximal de valeurs de formulaire publiées?

196

Microsoft (29-22-2011) a récemment publié une mise à jour pour corriger plusieurs graves failles de sécurité dans le .NET Framework. L'un des correctifs introduits par MS11-100 atténue temporairement une attaque DoS potentielle impliquant des collisions de tables de hachage. Il semble que ce correctif brise les pages qui contiennent beaucoup de données POST. Dans notre cas, sur les pages qui ont de très grandes listes de cases à cocher. Pourquoi en serait-il ainsi?

Certaines sources non officielles semblent indiquer que MS11-100 place une limite de 500 sur les articles publiés. Je ne trouve pas de source Microsoft qui confirme cela. Je sais que l'état d'affichage et d'autres fonctionnalités du cadre absorbent une partie de cette limite. Y a-t-il un paramètre de configuration qui contrôle cette nouvelle limite? Nous pourrions abandonner l'utilisation des cases à cocher, mais cela fonctionne plutôt bien pour notre situation particulière. Nous aimerions également appliquer le patch car il protège contre d'autres choses désagréables.

Source non officielle discutant de la limite de 500:

Le bulletin corrige le vecteur d'attaque DOS en fournissant une limite au nombre de variables pouvant être soumises pour une seule requête HTTP POST. La limite par défaut est de 500, ce qui devrait être suffisant pour les applications Web normales, mais suffisamment bas pour neutraliser l'attaque, comme l'ont décrit les chercheurs en sécurité en Allemagne.

EDIT: code source avec exemple de limite (qui semble être 1 000 et non 500) Créez une application MVC standard et ajoutez le code suivant à la vue d'index principale:

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

Ce code fonctionnait avant le patch. Ça ne marche pas après. L'erreur est:

[InvalidOperationException: l'opération n'est pas valide en raison de l'état actuel de l'objet.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded () +82 System.Web.HttpValueCollection.FillFromEncodedBytes (Byte [] byteWeb, Encod System [11 octets), Encod System [11 octets], Encod System [11 octets]
. HttpRequest.FillInFormCollection () +307

colithium
la source
Que diriez-vous de faire quelques travaux supplémentaires et d'afficher la section où il est dit spécifiquement 500.
OO
3
C'est ca le truc. Il n'y a pas de section (de Microsoft). Juste des commentateurs non officiels qui peuvent ou non savoir de quoi ils parlent. J'ai quand même publié un lien et un extrait de code.
colithium
1
@Andrew: La seule "liste à sélection multiple" à laquelle je pense serait le ListBox avec SelectionMode réglé sur Multiple. Cela pourrait en effet éventuellement afficher plusieurs valeurs. Cependant, la question mentionne des "listes déroulantes". Attendons ensuite les commentaires de l'auteur de la question.
Wiktor Zychla
1
Une question récente sur ce sujet a déterminé que le correctif atténuait le DOS en limitant le nombre de publications.
John Saunders
1
Voir support.microsoft.com/kb/2661403 pour plus de détails à ce sujet.

Réponses:

275

Essayez d'ajouter ce paramètre dans web.config. Je viens de tester cela sur .NET 4.0 avec un projet ASP.NET MVC 2 et avec ce paramètre, votre code ne renvoie pas:

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

Cela devrait fonctionner maintenant (après avoir appliqué la mise à jour de sécurité) pour modifier la limite.


Je n'avais pas encore mis à jour ma machine, donc en utilisant Reflector j'ai vérifié la classe HttpValueCollection, et elle n'avait pas la ThrowIfMaxHttpCollectionKeysExceededméthode:

entrez la description de l'image ici

J'ai installé KB2656351 (mise à jour pour .NET 4.0), rechargé les assemblys dans Reflector et la méthode est apparue:

entrez la description de l'image ici

Cette méthode est donc définitivement nouvelle. J'ai utilisé l' option Désassembler dans Reflector, et d'après ce que je peux dire du code, il vérifie un AppSetting:

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

S'il ne trouve pas la valeur dans le fichier web.config, il la mettra à 1000 dans System.Web.Util.AppSettings.EnsureSettingsLoaded(une classe statique interne):

 _maxHttpCollectionKeys = 0x3e8;

De plus, Alexey Gusarov a tweeté à propos de ce paramètre il y a deux jours:

Et voici une réponse officielle d'un Q&A avec Jonathan Ness (Security Development Manager, MSRC) et Pete Voss (Sr. Response Communications Manager, Trustworthy Computing):

Q: AppSettings.MaxHttpCollectionKeys est-il le nouveau paramètre qui contient le nombre maximal d'entrées de formulaire?

R: Oui, c'est ça.

Michiel van Oosterhout
la source
25
Merveilleux. Voilà le genre de réponses qui me font aimer stackoverflow
colithium
4
Cela m'a vraiment aidé, j'aurais aimé avoir un autre compte pour pouvoir donner +2 :)
misha
1
cela peut-il être mis à jour dans applicationhost.config pour l'ensemble du serveur? ou machine.config?
andryuha
1
Est-il possible de contrôler cette limite au niveau de la page? (Également demandé ici et ici .)
Mike Guthrie
1
Certaines personnes ont suggéré de revoir la page Web car elle ne devrait pas contenir ces nombreux champs de formulaire. Mais nous avons eu un scénario très valable pour cette erreur - le panier dans l'un des sites de commerce électronique de notre client avait beaucoup d'articles et nous avons enregistré cette erreur lorsqu'elle accédait à la page. Dans de tels cas, remplacer la valeur maximale est la meilleure option.
Ankur-m
18

Pour ceux d'entre vous qui utilisent encore .NET 1.1, ce paramètre n'est pas configuré via web.config - c'est un paramètre de registre (chapeau à michielvoo, car je n'ai découvert cela via Reflector que de la même manière qu'il a trouvé la réponse). L'exemple ci-dessous est défini MaxHttpCollectionKeyssur 5000 sur les éditions 32 bits de Windows:

Windows Registry Editor Version 5.00

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

Pour une édition Windows 64 bits, définissez la clé sous le Wow6432Node:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
terranwannabe
la source
Avez-vous des informations indiquant si 5000 est une valeur raisonnablement sûre par rapport à l'attaque DoS que ce correctif de sécurité est censé atténuer? Nous cherchons à utiliser la même valeur de 5000, mais je ne trouve aucune information sur la relation entre le nombre de valeurs et le temps processeur consommé par demande dans une attaque ...
Tao
4

Je veux juste ajouter mes 0,02 $ ici pour les gens qui voient la bizarrerie.

Si votre application cache des informations de page dans ASP.NET ViewState et dépasse le seuil du serveur Web, vous allez rencontrer ce problème. Plutôt que d'appliquer immédiatement le problème de correction de web.config, vous voudrez peut-être commencer par optimiser votre code.

Affichez la source et recherchez plus de 1000 champs cachés dans l'état d'affichage, et vous avez votre problème.

Caprice sans yeux
la source
1000+ champs viewstate? N'y a-t-il pas un seul champ ViewState sur le formulaire. La valeur est ce qui augmente à mesure que le nombre de champs de formulaire augmente.
Ankur-m
3

ThrowIfMaxHttpCollectionKeysExceeded()a également été ajouté au System.Web.HttpCookieCollection.

Il ressemble à quand HttpCookieCollection.Get()est appelé, il appelle en interne HttpCookieCollection.AddCookie(), qui appelle ensuite 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);
    }
}

Ce que nous voyons, c'est que sur une période de quelques heures, le site Web devient progressivement plus lent et plus bogué, jusqu'à ce qu'il commence à lancer le InvalidOperationExcpetion. Nous recyclons ensuite le pool d'applications, qui corrige le problème pendant quelques heures de plus.

Joshua Barker
la source
La limite de nombre de cookies est une bonne prise; Pour le ralentissement et le bug que vous décrivez, savez-vous si cela a réellement quelque chose à voir avec le nombre de cookies dans les demandes? Avez-vous vérifié les demandes des clients que vous recevez? (votre application fait-elle délibérément quelque chose avec un grand nombre de cookies?)
Tao
1
il se trouve que nous avions un CookieProvider personnalisé qui saisissait de manière incorrecte une référence singleton à la collection Request.Cookies au démarrage de l'application, puis à chaque demande suivante, il vérifierait si un ou plusieurs cookies existaient dans la collection de cookies statique ... comme vous pouvez le voir dans le code ci-dessus, .Net AJOUTE ce cookie par défaut s'il n'est pas trouvé. Ainsi, au fil du temps, chaque utilisateur accédant au système, divers cookies ont été ajoutés à cette collection singleton ... et puisque le site a été conçu pour fonctionner avec ou sans cookies, ce bug n'a jamais été identifié (jusqu'à présent)
Joshua Barker