Yandex Pay payment-manager.js — postMessage без проверки event.origin

PoC-демо. Страница грузит настоящий SDK Яндекса и показывает, что входящее message-событие принимается по строке source в payload'е, а не по origin отправителя.

Шаг 0 — что загружено

загрузка SDK…

Шаг 1 — исходник уязвимого листенера (из живого бандла)

выкачиваю payment-manager.js и ищу проверки origin…

Шаг 2 — форж-сообщение принимается (self-postMessage)

Наш листенер повторяет ровно логику SDK: доверять, если data.source === "YandexMBPaymentWidget". Жмём — шлём себе поддельное «успешная оплата».

Шаг 3 — E2E против реального Яндекса нужен твой залогин на plus.yandex.ru

Открывает plus.yandex.ru/gift в новой вкладке и «спреит» туда поддельные события виджета. Если ты залогинен — увидишь, как чужой payload прилетает на доверенный Яндекс-origin. Это твой тест на твоём же аккаунте, ничего не покупается (бэкенд подписку не выдаёт).

Механика: у мерчант-страницы (plus.yandex.ru, ott.kinopoisk.ru, bookmate.ru …) SDK ставит window.addEventListener("message", cb) и дёргает колбэки мерчанта (onSuccess/onError/NEED_AUTH/open-uri-tech) без сравнения e.origin. Любое окно, сделавшее postMessage в окно мерчанта, форжит любое событие виджета под доверенным Яндекс-origin. Потолок: integrity-forge клиентских колбэков + self-редирект вкладки (токен не утекает — исходящие пиннят targetOrigin; подписку выдаёт бэкенд). CVSS 6.5 Medium.