]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: jwt: fix base64 decoding error detection
authorWilly Tarreau <w@1wt.eu>
Fri, 15 Oct 2021 09:41:16 +0000 (11:41 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 15 Oct 2021 09:41:16 +0000 (11:41 +0200)
Tim reported that a decoding error from the base64 function wouldn't
be matched in case of bad input, and could possibly cause trouble
with -1 being passed in decoded_sig->data. In the case of HMAC+SHA
it is harmless as the comparison is made using memcmp() after checking
for length equality, but in the case of RSA/ECDSA this result is passed
as a size_t to EVP_DigetVerifyFinal() and may depend on the lib's mood.

The fix simply consists in checking the intermediary result before
storing it.

That's precisely what happens with one of the regtests which returned
0 instead of 4 on the intentionally defective token, so the regtest
was fixed as well.

No backport is needed as this is new in this release.

reg-tests/jwt/jws_verify.vtc
src/jwt.c

index 27a187ff7ec98ed8423766f84fab4242ede034f6..47d5303a4c2674a8ea8e2f6724b94ca942ec3abb 100644 (file)
@@ -152,7 +152,7 @@ client c4 -connect ${h1_mainfe_sock} {
     rxresp
     expect resp.status == 200
     expect resp.http.x-jwt-alg == "HS512"
-    expect resp.http.x-jwt-verify-HS512 == "0"
+    expect resp.http.x-jwt-verify-HS512 == "4"
 } -run
 
 
index fd4626215d39e495b59cb5aee81cd31df906cbd8..0e233059f616631c7dba1533eeaa7217f691101d 100644 (file)
--- a/src/jwt.c
+++ b/src/jwt.c
@@ -292,10 +292,10 @@ enum jwt_vrfy_status jwt_verify(const struct buffer *token, const struct buffer
 {
        struct jwt_item items[JWT_ELT_MAX] = { { 0 } };
        unsigned int item_num = JWT_ELT_MAX;
-
        struct buffer *decoded_sig = NULL;
        struct jwt_ctx ctx = {};
        enum jwt_vrfy_status retval = JWT_VRFY_KO;
+       int ret;
 
        ctx.alg = jwt_parse_alg(alg->area, alg->data);
 
@@ -325,13 +325,14 @@ enum jwt_vrfy_status jwt_verify(const struct buffer *token, const struct buffer
        if (!decoded_sig)
                return JWT_VRFY_OUT_OF_MEMORY;
 
-       decoded_sig->data = base64urldec(ctx.signature.start, ctx.signature.length,
-                                        decoded_sig->area, decoded_sig->size);
-       if (decoded_sig->data == (unsigned int)-1) {
+       ret = base64urldec(ctx.signature.start, ctx.signature.length,
+                          decoded_sig->area, decoded_sig->size);
+       if (ret == -1) {
                retval = JWT_VRFY_INVALID_TOKEN;
                goto end;
        }
 
+       decoded_sig->data = ret;
        ctx.key = key->area;
        ctx.key_length = key->data;