Amazon AppSec CTF: HalCrypto

Executive Summary

  • Challenge: HalCrypto
  • Category: Web Security
  • Vulnerability: JWT validation bypass via URL confusion with @ symbol
  • Impact: Authentication bypass leading to admin access
  • Flag: HTB{r3d1r3c73d_70_my_s3cr37s}

Vulnerability Overview

Attack Flow Diagram

Attack Flow Diagram

Source-to-Sink Analysis

1. Entry Point - JWT Authentication (Source)

The vulnerability starts when the AuthMiddleware processes JWT tokens:

// middleware/AuthMiddleware.js:5-34
module.exports = async (req, res, next) => {
    try {
        if (req.cookies.session === undefined) {
            if (!req.is('application/json')) return res.redirect('/');
            return res.status(401).send(response('Authentication required!'));
        }
        return JWTHelper.getHeader(req.cookies.session)
            .then(header => {
                if (header.jku && header.kid) {
                    // VULNERABILITY: Weak URL validation using lastIndexOf
                    if (header.jku.lastIndexOf(config.AUTH_PROVIDER, 0) !== 0) {
                        return res.status(500).send(response('The JWKS endpoint is not from localhost!'));
                    }
                    return JWTHelper.getPublicKey(header.jku, header.kid)
                        .then(pubkey => {
                            return JWTHelper.verify(req.cookies.session, pubkey)
                                .then(data => {
                                    req.user = data.user;
                                    return next();
                                })
                                .catch(() => res.status(403).send(response('Authentication token could not be verified!')));
                        })
                        .catch(() => res.redirect('/logout'));
                }
                return res.status(500).send(response('Missing required claims in JWT!'));
            })
            .catch(err => res.status(500).send(response("Invalid session token supplied!")));
    } catch (e) {
        return res.status(500).send(response(e.toString()));
    }
}

2. The Vulnerable Validation - String-based URL Check

The critical vulnerability lies in line 14 of AuthMiddleware.js:

[Read More]