Limit request body size. (#4866)
Normally we do this with a reverse proxy in front of Boulder, but it's nice to have an additional layer of protection in case someone deploys Boulder without a reverse proxy. Fixes #4730.
This commit is contained in:
parent
3d9c31580a
commit
065cfd502f
|
@ -57,6 +57,8 @@ const (
|
|||
issuerPath = "/acme/issuer-cert"
|
||||
buildIDPath = "/build"
|
||||
rolloverPath = "/acme/key-change"
|
||||
|
||||
maxRequestSize = 50000
|
||||
)
|
||||
|
||||
// WebFrontEndImpl provides all the logic for Boulder's web-facing interface,
|
||||
|
@ -500,8 +502,11 @@ func (wfe *WebFrontEndImpl) verifyPOST(ctx context.Context, logEvent *web.Reques
|
|||
return nil, nil, reg, probs.Malformed("No body on POST")
|
||||
}
|
||||
|
||||
bodyBytes, err := ioutil.ReadAll(request.Body)
|
||||
bodyBytes, err := ioutil.ReadAll(http.MaxBytesReader(nil, request.Body, maxRequestSize))
|
||||
if err != nil {
|
||||
if err.Error() == "http: request body too large" {
|
||||
return nil, nil, reg, probs.Unauthorized("request body too large")
|
||||
}
|
||||
wfe.httpErrorCounter.WithLabelValues("UnableToReadReqBody").Inc()
|
||||
return nil, nil, reg, probs.ServerInternal("unable to read request body")
|
||||
}
|
||||
|
|
|
@ -2191,6 +2191,18 @@ func TestLengthRequired(t *testing.T) {
|
|||
test.AssertEquals(t, http.StatusLengthRequired, prob.HTTPStatus)
|
||||
}
|
||||
|
||||
func TestRequestTooLong(t *testing.T) {
|
||||
wfe, _ := setupWFE(t)
|
||||
payload := fmt.Sprintf(`{"a":"%s"}`, strings.Repeat("a", 50000))
|
||||
|
||||
_, _, _, prob := wfe.verifyPOST(ctx, newRequestEvent(), makePostRequest(signRequest(t,
|
||||
payload, wfe.nonceService)), false, "n/a")
|
||||
test.Assert(t, prob != nil, "No error returned for too-long request body.")
|
||||
test.AssertEquals(t, probs.UnauthorizedProblem, prob.Type)
|
||||
test.AssertEquals(t, "request body too large", prob.Detail)
|
||||
test.AssertEquals(t, http.StatusForbidden, prob.HTTPStatus)
|
||||
}
|
||||
|
||||
type mockSAGetRegByKeyFails struct {
|
||||
core.StorageGetter
|
||||
}
|
||||
|
|
|
@ -23,8 +23,12 @@ import (
|
|||
"github.com/letsencrypt/boulder/web"
|
||||
)
|
||||
|
||||
// POST requests with a JWS body must have the following Content-Type header
|
||||
const expectedJWSContentType = "application/jose+json"
|
||||
const (
|
||||
// POST requests with a JWS body must have the following Content-Type header
|
||||
expectedJWSContentType = "application/jose+json"
|
||||
|
||||
maxRequestSize = 50000
|
||||
)
|
||||
|
||||
func sigAlgorithmForKey(key *jose.JSONWebKey) (jose.SignatureAlgorithm, error) {
|
||||
switch k := key.Key.(type) {
|
||||
|
@ -349,8 +353,11 @@ func (wfe *WebFrontEndImpl) parseJWSRequest(request *http.Request) (*jose.JSONWe
|
|||
|
||||
// Read the POST request body's bytes. validPOSTRequest has already checked
|
||||
// that the body is non-nil
|
||||
bodyBytes, err := ioutil.ReadAll(request.Body)
|
||||
bodyBytes, err := ioutil.ReadAll(http.MaxBytesReader(nil, request.Body, maxRequestSize))
|
||||
if err != nil {
|
||||
if err.Error() == "http: request body too large" {
|
||||
return nil, probs.Unauthorized("request body too large")
|
||||
}
|
||||
wfe.stats.httpErrorCount.With(prometheus.Labels{"type": "UnableToReadReqBody"}).Inc()
|
||||
return nil, probs.ServerInternal("unable to read request body")
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto/rsa"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
@ -881,6 +882,16 @@ func TestParseJWSRequest(t *testing.T) {
|
|||
Request: validJWSRequest,
|
||||
ExpectedProblem: nil,
|
||||
},
|
||||
{
|
||||
Name: "POST body too large",
|
||||
Request: makePostRequestWithPath("test-path",
|
||||
fmt.Sprintf(`{"a":"%s"}`, strings.Repeat("a", 50000))),
|
||||
ExpectedProblem: &probs.ProblemDetails{
|
||||
Type: probs.UnauthorizedProblem,
|
||||
Detail: "request body too large",
|
||||
HTTPStatus: http.StatusForbidden,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
Loading…
Reference in New Issue