ASP.NET MS11-100: ¿cómo puedo cambiar el límite en el número máximo de valores de formulario publicados?

196

Microsoft recientemente (29-12-2011) lanzó una actualización para abordar varias vulnerabilidades de seguridad graves en .NET Framework. Una de las soluciones introducidas por MS11-100 mitiga temporalmente un posible ataque DoS que involucra colisiones de tablas hash. Parece que esta solución rompe páginas que contienen muchos datos POST. En nuestro caso, en páginas que tienen listas de casillas de verificación muy grandes. Por qué sería este el caso?

Algunas fuentes no oficiales parecen indicar que MS11-100 establece un límite de 500 en artículos de devolución. No puedo encontrar una fuente de Microsoft que confirme esto. Sé que View State y otras características del marco consumen parte de este límite. ¿Hay alguna configuración que controle este nuevo límite? Podríamos dejar de usar casillas de verificación, pero funciona bastante bien para nuestra situación particular. También nos gustaría aplicar el parche porque protege contra otras cosas desagradables.

Fuente no oficial que discute el límite de 500:

El boletín corrige el vector de ataque de DOS al proporcionar un límite al número de variables que se pueden enviar para una sola solicitud HTTP POST. El límite predeterminado es 500, que debería ser suficiente para las aplicaciones web normales, pero lo suficientemente bajo como para neutralizar el ataque como lo describen los investigadores de seguridad en Alemania.

EDITAR: Código fuente con ejemplo de límite (que parece ser 1,000, no 500) Cree una aplicación MVC estándar y agregue el siguiente código a la vista del índice principal:

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

Este código funcionó antes del parche. No funciona después. El error es:

[InvalidOperationException: la operación no es válida debido al estado actual del objeto.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded () +82 System.Web.HttpValueCollection.FillFromEncodedBytes (Byteding)
. HttpRequest.FillInFormCollection () +307

colitio
fuente
¿Qué tal hacer un poco de trabajo preliminar adicional y publicar la sección donde dice específicamente 500.
OO
3
Esa es la cosa. No hay sección (de Microsoft). Solo de comentaristas no oficiales que pueden o no saber de qué están hablando. Publiqué un enlace y un fragmento de todos modos.
colitio
1
@ Andrew: La única "lista de selección múltiple" que se me ocurre sería ListBox con SelectionMode establecido en Multiple. De hecho, esto podría publicar múltiples valores. Sin embargo, la pregunta menciona "listas desplegables". Entonces esperemos cualquier comentario del autor de la pregunta.
Wiktor Zychla
1
Una pregunta reciente sobre este tema determinó que la solución mitigaba el DOS al limitar el número de publicaciones.
John Saunders
1
Consulte support.microsoft.com/kb/2661403 para obtener detalles sobre esto.

Respuestas:

275

Intente agregar esta configuración en web.config. Acabo de probar esto en .NET 4.0 con un proyecto ASP.NET MVC 2 y con esta configuración su código no arroja:

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

Eso debería funcionar ahora (después de haber aplicado la actualización de seguridad) para cambiar el límite.


Todavía no había actualizado mi máquina, así que usando Reflector verifiqué la clase HttpValueCollection y no tenía el ThrowIfMaxHttpCollectionKeysExceededmétodo:

ingrese la descripción de la imagen aquí

Instalé KB2656351 (actualización para .NET 4.0), volví a cargar los ensamblajes en Reflector y apareció el método:

ingrese la descripción de la imagen aquí

Entonces ese método es definitivamente nuevo. Utilicé el desmontaje opción en Reflector y, por lo que puedo ver en el código, comprueba una configuración de aplicación:

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

Si no encuentra el valor en el archivo web.config, lo establecerá en 1000 in System.Web.Util.AppSettings.EnsureSettingsLoaded(una clase estática interna):

 _maxHttpCollectionKeys = 0x3e8;

Además, Alexey Gusarov tuiteó sobre esta configuración hace dos días:

Y aqui hay una respuesta oficial de un Q&A con Jonathan Ness (Gerente de Desarrollo de Seguridad, MSRC) y Pete Voss (Gerente Senior de Comunicaciones de Respuesta, Computación Confiable):

P: ¿AppSettings.MaxHttpCollectionKeys es el nuevo parámetro que contiene el número máximo de entradas de formulario?

R: sí lo es.

Michiel van Oosterhout
fuente
25
Maravilloso. Este es el tipo de respuestas que me hacen amar stackoverflow
colithium
44
Realmente ayudó, ojalá tuviera otra cuenta para poder dar +2 :)
misha
1
¿Se puede actualizar esto en applicationhost.config para todo el servidor? o machine.config?
andryuha
1
¿Alguna forma de controlar este límite en un nivel por página? (También preguntado aquí y aquí .)
Mike Guthrie
1
Algunas personas han sugerido revisar la página web, ya que no debe contener tantos campos de formulario. Pero teníamos un escenario muy válido para este error: el carrito de compras en uno de los sitios de comercio electrónico de nuestro cliente tenía muchos artículos y teníamos este error registrado cuando estaba accediendo a la página. En tales casos, anular el valor máximo es la mejor opción.
Ankur-m
18

Para aquellos de ustedes que todavía usan .NET 1.1, esta configuración no está configurada a través de web.config: es una configuración de registro (hat tip to michielvoo, ya que solo descubrí esto a través de Reflector de la misma manera que encontró la respuesta). El siguiente ejemplo se establece MaxHttpCollectionKeysen 5000 en las ediciones de Windows de 32 bits:

Windows Registry Editor Version 5.00

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

Para una edición de Windows de 64 bits, configure la clave debajo del nodo Wow6432:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
terranwannabe
fuente
¿Tiene alguna información sobre si 5000 es un valor razonablemente seguro con respecto al ataque DoS que se supone que esta solución de seguridad debe mitigar? Estamos buscando usar el mismo valor 5000, pero no puedo encontrar ninguna información sobre la relación entre el número de valores y el tiempo de CPU consumido por solicitud en un ataque ...
Tao
4

Solo quiero agregar mis $ 0.02 aquí para las personas que ven la rareza.

Si su aplicación oculta información de la página en ASP.NET ViewState y supera el umbral del servidor web, se encontrará con este problema. En lugar de aplicar el problema de solución web.config de inmediato, es posible que desee echar un vistazo a la optimización de su código primero.

Ver código fuente, y buscar más de 1000 campos ocultos de estado de vista, y tiene su problema.

Capricho sin ojos
fuente
Más de 1000 campos de estado de vista? ¿No hay un solo campo ViewState en el formulario? El valor es lo que aumenta a medida que aumenta el número de campos de formulario.
Ankur-m
3

ThrowIfMaxHttpCollectionKeysExceeded()también se ha agregado a la System.Web.HttpCookieCollection.

Parece que cuando HttpCookieCollection.Get()se llama, está llamando internamente HttpCookieCollection.AddCookie(), que luego está llamando 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);
    }
}

Lo que estamos viendo es que durante un período de un par de horas, el sitio web se vuelve progresivamente más lento y con errores, hasta que comienza a arrojarse InvalidOperationExcpetion. Luego reciclamos el grupo de aplicaciones, que soluciona el problema por unas horas más.

Joshua Barker
fuente
El límite de recuento de cookies es una buena captura; Para la desaceleración y el error que describe, ¿sabe si realmente tiene algo que ver con el recuento de cookies en las solicitudes? ¿Verificó las solicitudes de clientes que está recibiendo? (¿su aplicación está haciendo algo a propósito con un gran número de cookies?)
Tao
1
Resulta que teníamos un CookieProvider personalizado que estaba tomando incorrectamente una referencia única a la Solicitud. Colección de cookies al iniciar la aplicación, luego, en cada solicitud posterior, verificaría si existían una o más cookies dentro de la colección de cookies estáticas ... como puede ver en el código anterior, .Net AGREGA esa cookie por defecto si no se encuentra. Entonces, con el tiempo, a medida que cada usuario accedía al sistema, se agregaron varias cookies a esta colección única ... y dado que el sitio fue diseñado para funcionar con o sin cookies, este error nunca fue identificado (hasta ahora)
Joshua Barker