ASP.NET MS11-100: como posso alterar o limite do número máximo de valores de formulário postados?

196

Recentemente, a Microsoft (29-12-2011) lançou uma atualização para solucionar várias vulnerabilidades graves de segurança no .NET Framework. Uma das correções introduzidas pelo MS11-100 mitiga temporariamente um possível ataque de DoS envolvendo colisões de tabelas de hash. Parece que essa correção quebra as páginas que contêm muitos dados do POST. No nosso caso, em páginas que possuem listas de caixas de seleção muito grandes. Por que isso seria o caso?

Algumas fontes não oficiais parecem indicar que o MS11-100 coloca um limite de 500 em itens de postagem. Não consigo encontrar uma fonte da Microsoft que confirme isso. Eu sei que o View State e outros recursos da estrutura consomem parte desse limite. Existe alguma configuração que controla esse novo limite? Poderíamos deixar de usar caixas de seleção, mas funciona muito bem para nossa situação específica. Também gostaríamos de aplicar o patch, pois ele protege contra outras coisas desagradáveis.

Fonte não oficial discutindo o limite de 500:

O boletim corrige o vetor de ataque do DOS, fornecendo um limite para o número de variáveis ​​que podem ser enviadas para uma única solicitação HTTP POST. O limite padrão é 500, o que deve ser suficiente para aplicativos da Web normais, mas ainda baixo o suficiente para neutralizar o ataque, conforme descrito pelos pesquisadores de segurança na Alemanha.

EDIT: Código-fonte com exemplo de limite (que parece ser 1.000, e não 500) Crie um aplicativo MVC padrão e adicione o seguinte código à exibição principal do índice:

@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 funcionou antes do patch. Não funciona depois. O erro é:

[InvalidOperationException: operação não é válida devido ao estado atual do objeto.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded () +82 System.Web.HttpValueCollection.FillFromEncodedBytes (Byte [] bytes, Encoding1.de)
. HttpRequest.FillInFormCollection () +307

colítio
fonte
Que tal fazer algum trabalho braçal adicional e postar a seção onde ele diz especificamente 500.
OO
3
Essa e a coisa. Não há seção (da Microsoft). Apenas de comentaristas não oficiais que podem ou não saber do que estão falando. Publiquei um link e um snippet de qualquer maneira.
colithium
1
@ Andrew: A única "lista de seleção múltipla" que posso pensar seria o ListBox com SelectionMode definido como Multiple. Isso realmente poderia postar vários valores. No entanto, a pergunta menciona "listas suspensas". Vamos aguardar os comentários do autor da pergunta.
Wiktor Zychla
1
Uma pergunta recente sobre esse tópico determinou que a correção mitigava o DOS limitando o número de postagens.
John Saunders
1
Consulte support.microsoft.com/kb/2661403 para obter detalhes sobre isso.

Respostas:

275

Tente adicionar essa configuração no web.config. Acabei de testar isso no .NET 4.0 com um projeto ASP.NET MVC 2 e com essa configuração seu código não lança:

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

Isso deve funcionar agora (depois de você aplicar a atualização de segurança) para alterar o limite.


Ainda não havia atualizado minha máquina, portanto, usando o Reflector, verifiquei a classe HttpValueCollection e ela não tinha o ThrowIfMaxHttpCollectionKeysExceededmétodo:

insira a descrição da imagem aqui

Instalei o KB2656351 (atualização para o .NET 4.0), recarreguei os assemblies no Reflector e o método apareceu:

insira a descrição da imagem aqui

Então esse método é definitivamente novo. Usei a opção Desmontar no Reflector e, pelo que posso ver no código, verifica um AppSetting:

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

Se não encontrar o valor no arquivo web.config, ele será definido como 1000 in System.Web.Util.AppSettings.EnsureSettingsLoaded(uma classe estática interna):

 _maxHttpCollectionKeys = 0x3e8;

Além disso, Alexey Gusarov twittou sobre essa configuração há dois dias:

E aqui está uma resposta oficial de uma sessão de perguntas e respostas com Jonathan Ness (gerente de desenvolvimento de segurança, MSRC) e Pete Voss (gerente sênior de comunicações de resposta, Trustworthy Computing):

P: AppSettings.MaxHttpCollectionKeys é o novo parâmetro que contém o número máximo de entradas de formulário?

A: Sim é.

Michiel van Oosterhout
fonte
25
Maravilhoso. Estes são o tipo de respostas que me faz amar stackoverflow
colithium
4
Ele realmente ajudou, eu gostaria de ter uma outra conta para que eu pudesse dar 2 :)
Misha
1
isso pode ser atualizado em applicationhost.config para todo o servidor? ou machine.config?
andryuha
1
Alguma maneira de controlar esse limite em um nível por página? (Também perguntou aqui e aqui .)
Mike Guthrie
1
Algumas pessoas sugeriram a revisão da página da Web, pois ela não deve conter muitos campos de formulário. Mas tivemos um cenário muito válido para esse erro - o carrinho de compras em um site de comércio eletrônico de nossa cliente tinha muitos itens e esse erro foi registrado quando ela estava acessando a página. Nesses casos, substituir o valor máximo é a melhor opção.
Ankur-m
18

Para aqueles que ainda usam o .NET 1.1, essa configuração não é configurada via web.config - é uma configuração de registro (dica para michielvoo, pois eu só descobri isso no Reflector da mesma maneira que ele encontrou a resposta). O exemplo abaixo define MaxHttpCollectionKeys5000 em edições de 32 bits do Windows:

Windows Registry Editor Version 5.00

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

Para uma edição do Windows de 64 bits, defina a chave no Wow6432Node:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
terranwannabe
fonte
Você tem alguma informação sobre se 5000 é um valor razoavelmente seguro em relação ao ataque DoS que essa correção de segurança deve mitigar? Nós estamos olhando usando o mesmo valor de 5000, mas não consigo encontrar qualquer informação sobre a relação entre o número de valores e tempo de CPU consumidos por solicitação em um ataque ...
Tao
4

Eu só quero adicionar meus US $ 0,02 aqui para as pessoas que vêem a estranheza.

Se o seu aplicativo esconder informações da página no ASP.NET ViewState e exceder o limite do servidor da Web, você encontrará esse problema. Em vez de aplicar o problema de correção web.config imediatamente, convém otimizar seu código primeiro.

Visualize o código-fonte e procure mais de 1000 campos ocultos no estado de exibição, e você terá seu problema.

Capricho sem olhos
fonte
Mais de 1000 campos do estado? Não há apenas um campo ViewState no formulário. O valor é o que aumenta à medida que o número de campos do formulário aumenta.
Ankur-m
3

ThrowIfMaxHttpCollectionKeysExceeded()também foi adicionado ao System.Web.HttpCookieCollection.

Parece que quando HttpCookieCollection.Get()é chamado, está chamando internamente HttpCookieCollection.AddCookie(), que então está chamando 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);
    }
}

O que estamos vendo é que, durante um período de algumas horas, o site fica progressivamente mais lento e com erros, até começar a lançar o InvalidOperationExcpetion. Em seguida, reciclamos o pool de aplicativos, que corrige o problema por mais algumas horas.

Joshua Barker
fonte
O limite de contagem de cookies é uma boa captura; Para a lentidão e problemas que você descreve, você sabe se ele realmente tem algo a ver com a contagem de cookies nas solicitações? Você verificou as solicitações do cliente que está recebendo? (é a sua aplicação propositadamente fazendo algo com um grande número de cookies?)
Tao
1
acontece que tínhamos um CookieProvider personalizado que estava capturando incorretamente uma referência de singleton para a coleção Request.Cookies na inicialização do aplicativo e, em cada solicitação subsequente, verificaria se um ou mais cookies existiam na coleção de cookies estática ... como você pode ver no código acima, .Net ADDS esse cookie por padrão, se não for encontrado. Então, com o tempo, à medida que cada usuário acessava o sistema, vários cookies foram sendo adicionados a essa coleção singleton ... e, como o site foi projetado para funcionar com ou sem cookies, esse bug nunca foi identificado (até agora)
Joshua Barker