Skip to content

Commit

Permalink
[SECURITY-3030]
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-beck authored and jenkinsci-cert-ci committed Feb 23, 2023
1 parent f39c11f commit b70f4cb
Show file tree
Hide file tree
Showing 4 changed files with 382 additions and 3 deletions.
2 changes: 1 addition & 1 deletion bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ THE SOFTWARE.
<properties>
<asm.version>9.4</asm.version>
<slf4jVersion>2.0.6</slf4jVersion>
<stapler.version>1770.v0c3dc82ee103</stapler.version>
<stapler.version>1775.v3181508ea_21e</stapler.version>
<groovy.version>2.4.21</groovy.version>
</properties>

Expand Down
51 changes: 50 additions & 1 deletion core/src/main/java/hudson/util/MultipartFormDataParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileCountLimitExceededException;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.ArrayUtils;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

/**
* Wraps commons file-upload and handles a "multipart/form-data" form submission
Expand All @@ -45,15 +49,60 @@ public class MultipartFormDataParser implements AutoCloseable {
private final ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
private final Map<String, FileItem> byName = new HashMap<>();

public MultipartFormDataParser(HttpServletRequest request) throws ServletException {
/**
* Limits the number of form fields that can be processed in one multipart/form-data request.
* Used to set {@link org.apache.commons.fileupload.servlet.ServletFileUpload#setFileCountMax(long)}.
* Despite the name, this applies to all form fields, not just actual file attachments.
* Set to {@code -1} to disable limits.
*/
private static /* nonfinal for Jenkins script console */ int FILEUPLOAD_MAX_FILES = Integer.getInteger(MultipartFormDataParser.class.getName() + ".FILEUPLOAD_MAX_FILES", 1000);

/**
* Limits the size (in bytes) of individual fields that can be processed in one multipart/form-data request.
* Used to set {@link org.apache.commons.fileupload.servlet.ServletFileUpload#setFileSizeMax(long)}.
* Despite the name, this applies to all form fields, not just actual file attachments.
* Set to {@code -1} to disable limits.
*/
private static /* nonfinal for Jenkins script console */ long FILEUPLOAD_MAX_FILE_SIZE = Long.getLong(MultipartFormDataParser.class.getName() + ".FILEUPLOAD_MAX_FILE_SIZE", -1);

/**
* Limits the total request size (in bytes) that can be processed in one multipart/form-data request.
* Used to set {@link org.apache.commons.fileupload.servlet.ServletFileUpload#setSizeMax(long)}.
* Set to {@code -1} to disable limits.
*/
private static /* nonfinal for Jenkins script console */ long FILEUPLOAD_MAX_SIZE = Long.getLong(MultipartFormDataParser.class.getName() + ".FILEUPLOAD_MAX_SIZE", -1);

@Restricted(NoExternalUse.class)
public MultipartFormDataParser(HttpServletRequest request, int maxParts, long maxPartSize, long maxSize) throws ServletException {
upload.setFileCountMax(maxParts);
upload.setFileSizeMax(maxPartSize);
upload.setSizeMax(maxSize);
try {
for (FileItem fi : upload.parseRequest(request))
byName.put(fi.getFieldName(), fi);
} catch (FileCountLimitExceededException e) {
throw new ServletException("File upload field count limit exceeded. Consider setting the Java system property "
+ MultipartFormDataParser.class.getName() + ".FILEUPLOAD_MAX_FILES to a value greater than " + FILEUPLOAD_MAX_FILES + ", or to -1 to disable this limit.", e);
} catch (FileUploadBase.FileSizeLimitExceededException e) {
throw new ServletException("File upload field size limit exceeded. Consider setting the Java system property "
+ MultipartFormDataParser.class.getName() + ".FILEUPLOAD_MAX_FILE_SIZE to a value greater than " + FILEUPLOAD_MAX_FILE_SIZE + ", or to -1 to disable this limit.", e);
} catch (FileUploadBase.SizeLimitExceededException e) {
throw new ServletException("File upload total size limit exceeded. Consider setting the Java system property "
+ MultipartFormDataParser.class.getName() + ".FILEUPLOAD_MAX_SIZE to a value greater than " + FILEUPLOAD_MAX_SIZE + ", or to -1 to disable this limit.", e);
} catch (FileUploadException e) {
throw new ServletException(e);
}
}

@Restricted(NoExternalUse.class)
public MultipartFormDataParser(HttpServletRequest request, int maxParts) throws ServletException {
this(request, maxParts, FILEUPLOAD_MAX_FILE_SIZE, FILEUPLOAD_MAX_SIZE);
}

public MultipartFormDataParser(HttpServletRequest request) throws ServletException {
this(request, FILEUPLOAD_MAX_FILES, FILEUPLOAD_MAX_FILE_SIZE, FILEUPLOAD_MAX_SIZE);
}

public String get(String key) {
FileItem fi = byName.get(key);
if (fi == null) return null;
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/jenkins/model/Jenkins.java
Original file line number Diff line number Diff line change
Expand Up @@ -4398,7 +4398,7 @@ public void reload() throws IOException, InterruptedException, ReactorException
@RequirePOST
public void doDoFingerprintCheck(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
// Parse the request
try (MultipartFormDataParser p = new MultipartFormDataParser(req)) {
try (MultipartFormDataParser p = new MultipartFormDataParser(req, 10)) {
if (isUseCrumbs() && !getCrumbIssuer().validateCrumb(req, p)) {
// TODO investigate whether this check can be removed
rsp.sendError(HttpServletResponse.SC_FORBIDDEN, "No crumb found");
Expand Down
Loading

0 comments on commit b70f4cb

Please sign in to comment.