ASP.NET MS11-100: как я могу изменить лимит на максимальное количество опубликованных значений формы?

Недавно Microsoft (12-29-2011) выпустила обновление для устранения ряда серьезных уязвимостей безопасности в .NET Framework. Одно из исправлений, введенных MS11-100, временно смягчает потенциальную атаку DoS с участием столкновений с хэш-таблицами. Похоже, это исправление разбивает страницы, содержащие много данных POST. В нашем случае на страницах с очень большими списками флажков. Почему это так?

Некоторые неофициальные источники, по-видимому, указывают на то, что MS11-100 помещает лимит 500 на объекты обратной передачи. Я не могу найти источник Microsoft, который подтверждает это. Я знаю, что View State и другие функциональные возможности удовлетворяют некоторым из этих ограничений. Есть ли какой-либо параметр конфигурации, который контролирует этот новый предел? Мы могли бы отказаться от использования флажков, но это хорошо работает для нашей конкретной ситуации. Мы также хотели бы применить патч, потому что он защищает от других неприятных вещей.

Неофициальный источник, обсуждая ограничение 500:

Бюллетень фиксирует вектор атаки DOS, предоставляя ограничение на количество переменных, которые могут быть отправлены для одного HTTP POST запрос. Предел по умолчанию - 500, который должен быть достаточным для нормального веб-приложения, но все же достаточно низкие, чтобы нейтрализовать атаку как описанных исследователями безопасности в Германии.

EDIT: Исходный код с примером предела (который, как представляется, равен 1000, а не 500) Создайте стандартное приложение MVC и добавьте следующий код в основное представление индекса:

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

Этот код работал перед патчем. После этого он не работает. Ошибка:

[InvalidOperationException: операция недействительна из-за текущей состояние объекта.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded() +82 System.Web.HttpValueCollection.FillFromEncodedBytes(байты [] байты, кодировка кодирования) +111
System.Web.HttpRequest.FillInFormCollection() +307

Ответ 1

Попробуйте добавить этот параметр в web.config. Я просто протестировал это на .NET 4.0 с проектом ASP.NET MVC 2, и с этой настройкой ваш код не бросает:

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

Это должно работать теперь (после того, как вы применили обновление безопасности), чтобы изменить лимит.


Я еще не обновил свою машину, поэтому с помощью Reflector я проверил класс HttpValueCollection и не имел метода ThrowIfMaxHttpCollectionKeysExceeded:

enter image description here

Я установил KB2656351 (обновление для .NET 4.0), перезагрузил сборки в Reflector и появился способ:

enter image description here

Итак, этот метод определенно нова. Я использовал параметр "Разборка" в Reflector, и из того, что я могу сказать по коду, он проверяет AppSetting:

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

Если он не найдет значение в файле web.config, он установит его в 1000 в System.Web.Util.AppSettings.EnsureSettingsLoaded (внутренний статический класс):

 _maxHttpCollectionKeys = 0x3e8;

Кроме того, Алексей Гусаров написал твиттер об этой настройке два дня назад:

И здесь является официальным ответом от Q & A с Джонатаном Нессом (Security Development Manager, MSRC) и Пит Восс (старший менеджер по связям с коммуникациями, надежные вычисления ):

Q: Является ли AppSettings.MaxHttpCollectionKey новым параметром, который содержит максимальное количество записей в форме?

A: Да, это так.

Ответ 2

Для тех из вас, кто по-прежнему использует .NET 1.1, этот параметр не настроен с помощью web.config - это параметр реестра (подсказка шляпы к michielvoo, так как я обнаружил это через Reflector так же, как он нашел ответ). Ниже приведен пример MaxHttpCollectionKeys to 5000 в 32-разрядных версиях Windows:

Windows Registry Editor Version 5.00

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

Для 64-разрядной версии Windows установите ключ под Wow6432Node:

Windows Registry Editor Version 5.00

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

Ответ 3

Я просто хочу добавить свои $0.02 для людей, видящих странность.

Если ваше приложение задерживает информацию о странице в ASP.NET ViewState и превышает порог веб-сервера, вы столкнетесь с этой проблемой. Вместо того, чтобы сразу применить проблему исправления web.config, вы можете сначала взглянуть на оптимизацию кода.

Просмотрите исходный код и найдите более 1000 скрытых полей в представлении, и у вас возникли проблемы.

Ответ 4

ThrowIfMaxHttpCollectionKeysExceeded() также добавлен в System.Web.HttpCookieCollection.

Похоже, когда вызывается HttpCookieCollection.Get(), он внутренне вызывает HttpCookieCollection.AddCookie(), который затем вызывает 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);
    }
}

Что мы видим, так это то, что через пару часов сайт становится все медленнее и медленнее, пока он не начнет бросать InvalidOperationExcpetion. Затем мы перерабатываем приложение, которое исправляет проблему в течение нескольких часов.