Перейти к содержимому
← Каталог golang Auth Bypass

JWT Key Confusion (RS256 to HS256)

JWT RS256/HS256 key confusion: the server exposes the public key and doesn't enforce the signing algorithm, allowing token forgery via algorithm switch.

hardgolangPro
Задача
# JWT Key Confusion: подмена асимметричного алгоритма симметричным ## Сценарий Вы — аудитор безопасности **SecureShop**. Приложение использует JWT-токены для аутентификации с асимметричным алгоритмом подписи (RSA): сервер хранит приватный ключ и подписывает им токены, а публичный ключ открыто доступен через стандартные эндпоинты (его, например, потребляют клиенты для верификации on-device или для интеграции с внешними системами). По данным внутреннего аудита, в админ-панели хранится конфиденциальная метка, доступная только пользователям с ролью администратора; её требуется извлечь, имея только обычную учётную запись. ## Цель 1. Изучите, как именно сервер верифицирует JWT-токены: какие алгоритмы он принимает и как именно валидируется заголовок `alg`. 2. Проанализируйте структуру keyfunc-обработчика валидации — какой ключ возвращается для каких алгоритмов. 3. Сформируйте подделанный токен, не зная серверного приватного ключа, и получите доступ к админ-панели; извлеките флаг. ## Теория Key Confusion (или Algorithm Confusion) — атака на JWT-валидацию, основанная на смешении классов криптографических алгоритмов. RSA-подписи (RS256, RS384, RS512) используют **асимметричную** криптографию: приватный ключ для подписания, публичный для верификации. HMAC-подписи (HS256, HS384, HS512) используют **симметричный** ключ: один и тот же секрет для подписания и верификации. Когда серверный keyfunc возвращает один и тот же ключ для разных классов алгоритмов (или возвращает «байты PEM-публичного ключа» как материал для верификации, не различая, на какой алгоритм этот материал реально подаётся), атакующий получает возможность взять открытый публичный ключ и использовать его как «секрет» для подписи токена HMAC. **Уязвимый паттерн:** ```go // Keyfunc не различает классы алгоритмов — байты публичного ключа // при HS256 обрабатываются как HMAC-секрет token, _ := jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) { if _, ok := t.Method.(*jwt.SigningMethodRSA); ok { return &rsaPrivateKey.PublicKey, nil } return []byte(rsaPublicKeyPEM), nil // <- путь HMAC: публичный ключ как секрет }) ``` Атакующий получает публичный ключ через стандартный эндпоинт сервиса, конструирует токен с произвольными claims (включая `role: admin`), указывает в заголовке симметричный алгоритм (HS256), и подписывает токен PEM-байтами публичного ключа как HMAC-секретом. Сервер при верификации видит `alg: HS256` → возвращает PEM-байты публичного ключа как материал → HMAC проверяется на тех же байтах → подпись «совпадает» → токен принимается с подменёнными claims. ## Точка входа атаки | Параметр | Значение | |----------|----------| | Учётные данные обычного пользователя | `demo` / `demo` | | Эндпоинт логина | `POST /login` (выдаёт cookie `token` с RS256-JWT) | | Эндпоинт публичного ключа | `GET /api/public-key` (или `.well-known/jwks.json`) | | Привилегированный эндпоинт | `GET /admin` (требует `role: admin` в claims) |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru