Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for form limits & improve configuration via context attributes #12560

Open
wants to merge 1 commit into
base: jetty-12.0.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.docs.programming.security;

import org.eclipse.jetty.ee10.servlet.ServletContextHandler;

public class FormSizeDocs
{
public void example()
{
ServletContextHandler servletContextHandler = new ServletContextHandler();
int maxSizeInBytes = 1024;
int formKeys = 100;
// tag::formSizeConfig[]
servletContextHandler.setMaxFormContentSize(maxSizeInBytes);
servletContextHandler.setMaxFormKeys(formKeys);
// end::formSizeConfig[]
}
}
2 changes: 2 additions & 0 deletions documentation/jetty/modules/programming-guide/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
** xref:troubleshooting/state-tracking.adoc[]
** xref:troubleshooting/component-dump.adoc[]
** xref:troubleshooting/debugging.adoc[]
* Jetty Security
** xref:security/configuring-form-size.adoc[]
* Migration Guides
** xref:migration/94-to-10.adoc[]
** xref:migration/11-to-12.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

[[configuring-form-size]]
= Limiting Form Content

Form content sent to the server is processed by Jetty into a map of parameters to be used by the web application.
This can be vulnerable to denial of service (DOS) attacks since significant memory and CPU can be consumed if a malicious clients sends very large form content or large number of form keys.
Thus, Jetty limits the amount of data and keys that can be in a form posted to Jetty.

The default maximum size Jetty permits is 200000 bytes and 1000 keys.
You can change this default for a particular webapp or for all webapps on a particular Server instance.

== Configuring Form Limits for a Webapp

To configure the form limits for a single web application, the servlet context handler (or webappContext) instance must be configured using the following methods:

[,java,indent=0]
----
include::code:example$src/main/java/org/eclipse/jetty/docs/programming/security/FormSizeDocs.java[tags=formSizeConfig]
----

These methods may be called directly when embedding Jetty, but more commonly are configured from a context XML file or WEB-INF/jetty-web.xml file:

[,xml,subs=attributes+]
----
<Configure class="org.eclipse.jetty.{ee-current}.webapp.WebAppContext">

...

<Set name="maxFormContentSize">200000</Set>
<Set name="maxFormKeys">200</Set>
</Configure>

----

These settings can also be set via the following Context attributes.

- `org.eclipse.jetty.server.Request.maxFormKeys`
- `org.eclipse.jetty.server.Request.maxFormContentSize`

== Configuring Default Form Limits for the Server

The default `maxFormKeys` is 1000 and the default `maxFormContentSize` is 200000.

However, the following system properties can be set to change the default values of this across every context; `org.eclipse.jetty.server.Request.maxFormKeys` and `org.eclipse.jetty.server.Request.maxFormContentSize`.
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ public InvocationType getInvocationType()
public void dump(Appendable out, String indent) throws IOException
{
dumpObjects(out, indent,
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new ClassLoaderDump(getClassLoader()),
Dumpable.named("context " + this, getContext()),
Dumpable.named("handler attributes " + this, getContext().getPersistentAttributes()),
Expand Down Expand Up @@ -2045,6 +2047,44 @@ public void setExtendedListenerTypes(boolean b)
{
_servletContext.setExtendedListenerTypes(b);
}

@Override
public Object getAttribute(String name)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE -> getMaxFormKeys();
case FormFields.MAX_LENGTH_ATTRIBUTE -> getMaxFormContentSize();
default -> super.getAttribute(name);
};
}

@Override
public Object setAttribute(String name, Object attribute)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE ->
{
int oldValue = getMaxFormKeys();
if (attribute == null)
setMaxFormKeys(DEFAULT_MAX_FORM_KEYS);
else
setMaxFormKeys(Integer.parseInt(attribute.toString()));
yield oldValue;
}
case FormFields.MAX_LENGTH_ATTRIBUTE ->
{
int oldValue = getMaxFormContentSize();
if (attribute == null)
setMaxFormContentSize(DEFAULT_MAX_FORM_CONTENT_SIZE);
else
setMaxFormContentSize(Integer.parseInt(attribute.toString()));
yield oldValue;
}
default -> super.setAttribute(name, attribute);
};
}
}

public class ServletContextApi implements jakarta.servlet.ServletContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ClassLoaderDump;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.DumpableCollection;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
Expand Down Expand Up @@ -987,6 +988,8 @@ else if (getBaseResource() != null)
name = String.format("%s@%x", name, hashCode());

dumpObjects(out, indent,
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new ClassLoaderDump(getClassLoader()),
new DumpableCollection("Systemclasses " + name, systemClasses),
new DumpableCollection("Serverclasses " + name, serverClasses),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.DumpableCollection;
import org.eclipse.jetty.util.component.Environment;
import org.eclipse.jetty.util.component.LifeCycle;
Expand Down Expand Up @@ -302,7 +303,10 @@ public void insertHandler(org.eclipse.jetty.server.Handler.Singleton coreHandler
@Override
public void dump(Appendable out, String indent) throws IOException
{
dumpObjects(out, indent, new DumpableCollection("initparams " + this, getInitParams().entrySet()));
dumpObjects(out, indent,
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new DumpableCollection("initparams " + this, getInitParams().entrySet()));
}

public APIContext getServletContext()
Expand Down Expand Up @@ -2861,6 +2865,44 @@ public APIContext getAPIContext()
{
return _apiContext;
}

@Override
public Object getAttribute(String name)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE -> getMaxFormKeys();
case FormFields.MAX_LENGTH_ATTRIBUTE -> getMaxFormContentSize();
default -> super.getAttribute(name);
};
}

@Override
public Object setAttribute(String name, Object attribute)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE ->
{
int oldValue = getMaxFormKeys();
if (attribute == null)
setMaxFormKeys(DEFAULT_MAX_FORM_KEYS);
else
setMaxFormKeys(Integer.parseInt(attribute.toString()));
yield oldValue;
}
case FormFields.MAX_LENGTH_ATTRIBUTE ->
{
int oldValue = getMaxFormContentSize();
if (attribute == null)
setMaxFormContentSize(DEFAULT_MAX_FORM_CONTENT_SIZE);
else
setMaxFormContentSize(Integer.parseInt(attribute.toString()));
yield oldValue;
}
default -> super.setAttribute(name, attribute);
};
}
}

private class CoreToNestedHandler extends Abstract
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ else if (getResourceBase() != null)

dumpObjects(out, indent,
Dumpable.named("environment", ContextHandler.ENVIRONMENT.getName()),
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new ClassLoaderDump(getClassLoader()),
new DumpableCollection("Systemclasses " + name, systemClasses),
new DumpableCollection("Serverclasses " + name, serverClasses),
Expand Down
Loading