httpd: validate reference also for CSRF token in headers

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2024-09-14 21:45:25 +02:00
parent 14cabda5c2
commit 6896d2bfb1
No known key found for this signature in database
GPG key ID: 935D2952DEC4EECF
4 changed files with 23 additions and 2 deletions

View file

@ -468,6 +468,10 @@ func verifyCSRFToken(r *http.Request, csrfTokenAuth *jwtauth.JWTAuth) error {
logger.Debug(logSender, "", "error validating CSRF token IP audience")
return errors.New("the form token is not valid")
}
return checkCSRFTokenRef(r, token)
}
func checkCSRFTokenRef(r *http.Request, token jwt.Token) error {
claims, err := getTokenClaims(r)
if err != nil {
logger.Debug(logSender, "", "error getting token claims for CSRF validation: %v", err)

View file

@ -20705,6 +20705,17 @@ func TestWebAdminBasicMock(t *testing.T) {
checkResponseCode(t, http.StatusForbidden, rr)
assert.Contains(t, rr.Body.String(), "Invalid token")
req, err = http.NewRequest(http.MethodPost, webAdminTOTPSavePath, bytes.NewBuffer(asJSON))
assert.NoError(t, err)
setJWTCookieForReq(req, altToken)
setCSRFHeaderForReq(req, csrfToken) // invalid CSRF token
req.RemoteAddr = defaultRemoteAddr
rr = executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
assert.Contains(t, rr.Body.String(), "the token is not valid")
csrfToken, err = getCSRFTokenFromInternalPageMock(webAdminPath, altToken)
assert.NoError(t, err)
req, err = http.NewRequest(http.MethodPost, webAdminTOTPSavePath, bytes.NewBuffer(asJSON))
assert.NoError(t, err)
setJWTCookieForReq(req, altToken)
@ -20781,7 +20792,7 @@ func TestWebAdminBasicMock(t *testing.T) {
rr = executeRequest(req)
checkResponseCode(t, http.StatusSeeOther, rr)
form.Set(csrfFormToken, "invalid csrf")
form.Set(csrfFormToken, csrfToken) // associated to altToken
req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode())))
req.RemoteAddr = defaultRemoteAddr
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
@ -20790,6 +20801,8 @@ func TestWebAdminBasicMock(t *testing.T) {
checkResponseCode(t, http.StatusForbidden, rr)
assert.Contains(t, rr.Body.String(), util.I18nErrorInvalidCSRF)
csrfToken, err = getCSRFTokenFromInternalPageMock(webAdminPath, token)
assert.NoError(t, err)
form.Set(csrfFormToken, csrfToken)
form.Set("email", "not-an-email")
req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode())))

View file

@ -343,6 +343,10 @@ func (s *httpdServer) verifyCSRFHeader(next http.Handler) http.Handler {
sendAPIResponse(w, r, errors.New("the token is not valid"), "", http.StatusForbidden)
return
}
if err := checkCSRFTokenRef(r, token); err != nil {
sendAPIResponse(w, r, errors.New("the token is not valid"), "", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})

View file

@ -1,6 +1,6 @@
#!/bin/bash
NFPM_VERSION=2.39.0
NFPM_VERSION=2.40.0
NFPM_ARCH=${NFPM_ARCH:-amd64}
if [ -z ${SFTPGO_VERSION} ]
then