ASP.NET MS11-100: how can I change the limit on the maximum number of posted form values?
Asked Answered
K

5

196

Microsoft recently (12-29-2011) released an update to address several serious security vulnerabilities in the .NET Framework. One of the fixes introduced by MS11-100 temporarily mitigates a potential DoS attack involving hash table collisions. It appears this fix breaks pages that contain a lot of POST data. In our case, on pages that have very large checkbox lists. Why would this be the case?

Some non-official sources seem to indicate that MS11-100 places a limit of 500 on postback items. I can't find a Microsoft source that confirms this. I know that View State and other framework features eat up some of this limit. Is there any configuration setting that controls this new limit? We could switch away from using checkboxes but it works rather well for our particular situation. We'd also like to apply the patch because it protects against some other nasty things.

Unofficial source discussing the 500 limit:

The bulletin fixes the DOS attack vector by providing a limit to the number of variables that can be submitted for a single HTTP POST request. The default limit is 500 which should be enough for normal web applications, but still low enough to neutralize the attack as described by the security researchers in Germany.

EDIT: Source code with example of limit (which appears to be 1,000, not 500) Create a standard MVC app and add the following code to the main index view:

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

This code worked before the patch. It doesn't work after. The error is:

[InvalidOperationException: Operation is not valid due to the current state of the object.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded() +82 System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding) +111
System.Web.HttpRequest.FillInFormCollection() +307

Kayleigh answered 30/12, 2011 at 21:0 Comment(11)
How about doing some additional legwork and post the section where it says specifically 500.Eleanor
That's the thing. There is no section (from Microsoft). Just from unofficial commentators which may or may not know what they're talking about. I posted a link and snippet anyway.Kayleigh
@AndrewBarber There was a link to the official bulletin in the original post, I added another.Kayleigh
are they multi select lists? Would the number of items come close to 500?Godsend
It doesn't matter how many items your dropdown contains in the browser. The POST always sends only a selected value. This means that to pass the limit of 500 variables you'd have to have 500 dropdowns. Maybe then they limit the size of the postback, not the number of variables?Cothurnus
@WiktorZychla Is that the case with a multi select list, though?Godsend
@WiktorZychla That is what I thought as well. I got a clarifying note from the person who reported the problem. It was on a page with multi select CHECKBOXES which do generate a posback value per checkbox.Kayleigh
@Andrew: The only "multi select list" I can think of would be the ListBox with SelectionMode set to Multiple. This indeed could possibly post multiple values. However, the question mentions "dropdown lists". Let's then wait for any comments from the question author.Cothurnus
@colithium: understood. Unfortunately, multiselect checkboxes of course do post multiple values.Cothurnus
A recent question on this topic determined that the fix mitigated the DOS by limiting the number of posts.Oilskin
See support.microsoft.com/kb/2661403 for details on this.Aestheticism
S
277

Try adding this setting in web.config. I just tested this on .NET 4.0 with an ASP.NET MVC 2 project and with this setting your code doesn't throw:

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

That should work now (after you have applied the security update) to change the limit.


I hadn't updated my machine yet, so using Reflector I checked the HttpValueCollection class, and it didn't have the ThrowIfMaxHttpCollectionKeysExceeded method:

enter image description here

I installed KB2656351 (update for .NET 4.0), reloaded the assemblies in Reflector and the method appeared:

enter image description here

So that method is definitely new. I used the Disassemble option in Reflector, and from what I can tell from the code it checks an AppSetting:

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

If it doesn't find the value in the web.config file, it will set it to 1000 in System.Web.Util.AppSettings.EnsureSettingsLoaded (an internal static class):

 _maxHttpCollectionKeys = 0x3e8;

Also, Alexey Gusarov tweeted about this setting two days ago:

And here is an official answer from a Q&A with Jonathan Ness (Security Development Manager, MSRC) and Pete Voss (Sr. Response Communications Manager, Trustworthy Computing):

Q: Is AppSettings.MaxHttpCollectionKeys the new parameter that contains the maximum number of form entries?

A: Yes it is.

Sortie answered 30/12, 2011 at 22:58 Comment(8)
Wonderful. These are the kind of answers that make me love stackoverflowKayleigh
It really helped, I wish I had another account so that I could give +2 :)Cankerworm
can this be updated in applicationhost.config for the whole server? or machine.config?Featherweight
In machine.config: yes, in applicationHost.config: noSortie
Fantastic answer, exactly what I needed when I found the same issue.Dashed
Any way to control this limit on a per-page level? (Also asked here and here.)Rigby
Perfect answer. Really appreciate it.Aholla
Some people have suggested reviewing the web page as it shouldn't contain these many form field. But we had a very valid scenario for this error - Shopping cart in one of our client's eCommerce site had a lot of items and we had this error logged when she was accessing the page. In such cases, overriding the max value is the best option.Whiggism
T
18

For those of you still using .NET 1.1, this setting is not configured via web.config - it is a registry setting (hat tip to michielvoo, as I only discovered this through Reflector the same way he found the answer). The example below sets MaxHttpCollectionKeys to 5000 on 32-bit editions of Windows:

Windows Registry Editor Version 5.00

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

For a 64-bit Windows edition, set the key under the Wow6432Node:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\1.1.4322.0]
"MaxHttpCollectionKeys"=dword:00001388
Twoply answered 3/1, 2012 at 19:47 Comment(1)
Do you have any information on whether 5000 is a reasonably-safe value with respect to the DoS attack that this security fix is supposed to mitigate? We're looking at using the same 5000 value, but I can't find any information on the relationship between number of values and CPU time consumed per request in an attack...Fanciful
B
4

I just want to add my $0.02 here for people seeing the weirdness.

If your application stashes page information into ASP.NET ViewState, and exceeds the web server threshold, you're going to run into this problem. Rather than applying the web.config fix problem straight away you might want to take a look at optimizing your code first.

View Source, and look for 1000+ viewstate hidden fields, and you've got your problem.

Barrel answered 10/1, 2012 at 19:1 Comment(1)
1000+ viewstate fields? Isn't there just one ViewState field on the form. The value is what increases as the number of form fields increases.Whiggism
T
4

If you're using ASP.NET CORE you can set this setting inside Startup#ConfigureServices

services.Configure<FormOptions>(options => options.ValueCountLimit = 1000); // you may want to adjust this limit

Reference: StackOverflow

Thigmotaxis answered 15/12, 2020 at 20:10 Comment(0)
T
3

ThrowIfMaxHttpCollectionKeysExceeded() has also been added to the System.Web.HttpCookieCollection.

It looks like when HttpCookieCollection.Get() is called, it's internally calling HttpCookieCollection.AddCookie(), which then is calling 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);
    }
}

What we're seeing is that over a period of a couple of hours the website gets progressively slower and buggier, until it starts throwing the InvalidOperationExcpetion. We then recycle the app-pool, which fixes the issue for a few more hours.

Thermoelectric answered 6/1, 2012 at 17:40 Comment(2)
The cookie count limit is a good catch; For the slowing down and bugginess that you describe, do you know whether it actually has anything to do with cookie counts in the requests? Did you check the client requests you're getting? (is your app purposefully doing something with large numbers of cookies?)Fanciful
it turns out that we had a custom CookieProvider that was incorrectly grabbing a singleton reference to the Request.Cookies collection on app start-up, then on every subsequent request, it would check to see if one or more cookies existed within the static cookie collection... as you can see from the code above, .Net ADDS that cookie by default if it is not found. So over time, as each user was accessing the system, various cookies were being added to this singleton collection... and since the site was designed to work with or without cookies, this bug was never identified (until now)Thermoelectric

© 2022 - 2024 — McMap. All rights reserved.