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

196

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

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

Неофициальный источник, обсуждающий лимит 500:

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

РЕДАКТИРОВАТЬ: Исходный код с примером лимита (который выглядит как 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 + кодировка байтов [1]. Encoding. Кодирование байтов [1]
. HttpRequest.FillInFormCollection () +307

colithium
источник
Как насчет того, чтобы проделать дополнительную работу и опубликовать раздел, где говорится конкретно 500.
OO
3
Это вещь. Там нет раздела (от Microsoft). Просто от неофициальных комментаторов, которые могут знать или не знать, о чем они говорят. В любом случае я разместил ссылку и фрагмент.
колитиум
1
@Andrew: Единственный «список множественного выбора», о котором я могу думать, это ListBox с SelectionMode, установленным в Multiple. Это действительно может публиковать несколько значений. Однако в вопросе упоминаются «выпадающие списки». Давайте тогда подождем любых комментариев от автора вопроса.
Виктор Зихла
1
Недавний вопрос на эту тему определил, что исправление смягчило DOS, ограничив количество постов.
Джон Сондерс
1
См. Support.microsoft.com/kb/2661403 для подробностей об этом.

Ответы:

275

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

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

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


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

введите описание изображения здесь

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

введите описание изображения здесь

Так что этот метод определенно новый. Я использовал опцию Disassemble в Reflector, и из того, что я могу сказать из кода, он проверяет AppSetting:

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

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

 _maxHttpCollectionKeys = 0x3e8;

Также Алексей Гусаров написал в твиттере об этой настройке два дня назад:

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

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

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

Михель ван Остерхаут
источник
25
Чудесно. Именно такие ответы заставляют меня любить stackoverflow
colithium
4
Это действительно помогло, я хотел бы иметь другую учетную запись, чтобы я мог дать +2 :)
Миша
1
это можно обновить в applicationhost.config для всего сервера? или machine.config?
Андрюха
1
Есть ли способ контролировать этот лимит на уровне страниц? (Также спросили здесь и здесь .)
Майк Гатри
1
Некоторые люди предложили просмотреть веб-страницу, так как она не должна содержать эти поля формы. Но у нас был очень правильный сценарий этой ошибки - в корзине покупок на одном из сайтов электронной коммерции нашего клиента было много товаров, и эта ошибка была зарегистрирована, когда она заходила на страницу. В таких случаях переопределение максимального значения является лучшим вариантом.
Анкур-м,
18

Для тех из вас, кто все еще использует .NET 1.1, этот параметр не настраивается с помощью web.config - это параметр реестра (это совет michielvoo, поскольку я обнаружил это только через Reflector так же, как он нашел ответ). В приведенном ниже примере установлено MaxHttpCollectionKeysзначение 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 установите ключ под узлом Wow6432:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
terranwannabe
источник
Есть ли у вас какая-либо информация о том, является ли значение 5000 достаточно безопасным в отношении DoS-атаки, которое должно устранить это исправление? Мы рассматриваем использование одного и того же значения 5000, но я не могу найти никакой информации о взаимосвязи между количеством значений и временем процессора, затрачиваемым на запрос в атаке ...
Тао
4

Я просто хочу добавить свои 0,02 доллара здесь, чтобы люди увидели странности.

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

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

Каприз безглазый
источник
1000+ полей viewstate? Нет ли в форме только одного поля ViewState. Значение - это то, что увеличивается с увеличением количества полей формы.
Анкур-м,
3

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. Затем мы перезапускаем пул приложений, который устраняет проблему еще на несколько часов.

Джошуа Баркер
источник
Предел количества печенья - хороший улов; Из-за замедления и ошибок, которые вы описываете, знаете ли вы, имеет ли это какое-либо отношение к количеству файлов cookie в запросах? Вы проверяли клиентские запросы, которые вы получаете? (Ваше приложение целенаправленно делает что-то с большим количеством файлов cookie?)
Тао
1
получается, что у нас был собственный CookieProvider, который неправильно захватывал одноэлементную ссылку на коллекцию Request.Cookies при запуске приложения, а затем при каждом последующем запросе проверял бы, существует ли один или несколько файлов cookie в статической коллекции cookie. ... как видно из приведенного выше кода, .Net ДОБАВЛЯЕТ этот cookie по умолчанию, если он не найден. Таким образом, со временем, когда каждый пользователь получал доступ к системе, в эту коллекцию синглтонов добавлялись различные файлы cookie ... и, поскольку сайт был разработан для работы с файлами cookie или без них, эта ошибка никогда не обнаруживалась (до сих пор)
Джошуа Баркер,