
Proof-of-concept, демонстрирующий хранимую XSS-уязвимость в Table Widget приложения Appsmith, приводящую к вертикальному повышению привилегий и полному захвату учётной записи администратора через атаку XSS-to-CSRF.
Proof-of-Concept для повышения привилегий в Appsmith через хранимый XSS
Раскрытие: Изначально сообщено мной через GHSA-5hw4-whxv-6794
⚠️ Только для авторизованного пентестинга/исследований.
| Поле | Значение |
|---|---|
| ID CVE | CVE-2026-30862 |
| Серьёзность | 🔴 Критическая |
| Оценка CVSS | 9.1 |
| Вектор CVSS | [CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H] |
| CWE | CWE-79, CWE-269, CWE-352 |
| Затронутый продукт | Appsmith ≤ 1.95 |
| Исправленная версия | 1.96 |
| Консультация | GHSA-5hw4-whxv-6794 |
Критическая уязвимость хранимого XSS существует в виджете таблицы (TableWidgetV2). Основная причина — отсутствие санитизации HTML в конвейере рендеринга компонентов React, что позволяет внедрять вредоносные атрибуты в DOM. Используя функцию «Пригласить пользователей», злоумышленник с обычной учётной записью ([email protected]) может заставить системного администратора выполнить высокопривилегированный вызов API (/api/v1/admin/env), что приведёт к полному захвату административной учётной записи.
1. Основная причина: отсутствие приёмника санитизации вывода Уязвимость находится в движке рендеринга виджета таблицы
Файл: app/client/src/widgets/TableWidgetV2/component/cellComponents/BasicCell.tsx
Компонент BasicCell не выполняет санитизацию данных, когда для columnType установлено значение URL или Plain Text. Он возвращает необработанные значения, предоставленные пользователем, которые напрямую отображаются как дочерние элементы React, и браузер интерпретирует их как исполняемый HTML.
Фрагмент уязвимого кода (строки 132–143 и 172–173):
const contentToRender = useMemo(() => {
switch (columnType) {
case ColumnTypes.URL:
// Прямая интерполяция 'url' в href без санитизации
return <a href={url} target="_blank">{value}</a>;
default:
return value; // Строка 141: возвращается необработанное значение
}
}, [columnType, url, value]);
// Строка 173: конечный приёмник, где несанитизированный контент внедряется в DOM
<Content ref={contentRef}>{contentToRender}</Content>
2. Вектор атаки: XSS-to-CSRF через социальную инженерию (функция приглашения) Хотя файл cookie SESSION защищён с помощью HttpOnly, токен XSRF-TOKEN доступен через document.cookie. Поскольку Appsmith позволяет любому пользователю «приглашать» других в своё приложение, злоумышленник может использовать это как механизм доставки для выполнения подделки межпривилегированных запросов (CPRF) в активной сессии администратора.
Шаг 1: Проверка уязвимости XSS
Войдите с обычной учётной записью: [email protected].
Создайте новое приложение и добавьте виджет таблицы.
В свойстве Table Data внедрите следующее:
[{ "id": 1, "payload": "" }]
-- Шаг 2: Вооружение (полный захват администратора)
[email protected], обновите Table Data следующим payload, предназначенным для изменения административной среды:[
{
"id": 1,
"Status": "System Update Required",
"payload": "alert('Admin Privileges Granted to [email protected]'));\">"
}
]
Используйте функцию «Поделиться», чтобы пригласить системного администратора ([email protected]) в приложение. Это заставит администратора просмотреть вредоносную таблицу при открытии приглашения.
Как только администратор запустит приложение, скрипт выполнится в фоновом режиме. Он считывает XSRF-TOKEN администратора и отправляет запрос PUT для добавления [email protected] в административный белый список.
Результат: снова войдите как [email protected]. Теперь у вас будет полный доступ к настройкам администратора и всем конфигурациям экземпляра.
Тип уязвимости: хранимый XSS / вертикальное повышение привилегий.
Серьёзность: 9.1 (критическая) | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Риск: полная компрометация экземпляра Appsmith. Злоумышленники получают доступ к конфиденциальным переменным окружения, учётным данным базы данных и возможность изменять любое приложение в экземпляре.
Санитизация приёмников: оберните все динамические выходные данные в BasicCell.tsx и связанных компонентах с помощью DOMPurify.sanitize().
Ужесточённая CSP: внедрите строгую политику connect-src, чтобы предотвратить несанкционированные вызовы API к административным конечным точкам из XSS-пейлоадов.
https://github.com/user-attachments/assets/206a10e4-1619-4887-a552-99761baa0a29