Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/ivanesk315/cve-2026-28496
Vulnerability ScannersVulnerability AnalysisExploitationServerless SecurityWeb Application ExploitationWeb SecurityPenetration TestingLearning & EducationLabs & Practice
GitHubivanesk315/cve-2026-28496

CVE-2026-28496

Docker lab reproducing the FOSSBilling pre-auth RCE chain (CVE-2026-27604 auth bypass + CVE-2026-28496 Twig SSTI) with a Python PoC and patched comparison target.

1821 days agoNot yet reviewed
View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-27604 + CVE-2026-28496 — FOSSBilling Pre-Auth RCE Chain

Executive Summary

This repository contains a local Docker lab for reproducing and validating the FOSSBilling Pre-Auth RCE chain, composed of two chained vulnerabilities:

CVETypeCVSS v4GHSADescription
CVE-2026-27604Auth Bypass10.0GHSA-78x5-c8gw-8279Missing throw in API role checker exposes admin endpoints to unauthenticated callers
CVE-2026-28496SSTI9.4GHSA-57mv-jm88-66jcUnsandboxed Twig template rendering via string_render API

FOSSBilling is a free and open-source billing and client management platform. Versions 0.5.4 through 0.7.2 are affected. FOSSBilling 0.8.0 patches both vulnerabilities.

This lab compares two FOSSBilling versions:

ServiceFOSSBilling versionPurposeURL
vuln0.7.2Vulnerable targethttp://localhost:8081
patched0.8.0Patched targethttp://localhost:8082

The validated chain in this local lab is:

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}

The patched target (0.8.0) returns:

{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}

The lab is intentionally scoped to local Docker services. It does not target external systems and does not include web shells, malware, persistence, external callbacks, database dumping, or destructive payloads.

The Chain

The Pre-Auth RCE requires both vulnerabilities working together:

┌──────────────────────────────────────────────────────────────┐
│  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                                     │
└──────────────────────────────────────────────────────────────┘

This lab demonstrates the chain using the safe arithmetic proof {{ 7*7 }}. The full RCE path via getDi() is not demonstrated.

Verified Facts

ClaimEvidenceHow to verify
CVE-2026-27604 is an auth bypass in FOSSBilling API role handling.GHSA-78x5-c8gw-8279: missing throw in role checker allows /api/system/ to resolve as admin.Run the PoC: guest path is denied, system path returns admin result.
CVE-2026-28496 is an SSTI in FOSSBilling Twig rendering.GHSA-57mv-jm88-66jc: string_render passes _tpl into Twig createTemplate() without sandbox.Run the PoC: server evaluates {{ 7*7 }} and returns 49.
Both vulnerabilities affect FOSSBilling 0.5.4 through 0.7.2.Public advisories identify the affected version range.Compare vuln (0.7.2) and patched (0.8.0) targets.
FOSSBilling 0.8.0 patches both vulnerabilities.Patched target returns "Unknown API call" for the tested endpoint.Run the PoC against port 8082.
The auth bypass gives unauthenticated admin access./api/guest/ denies string_render; /api/system/ returns the result without auth.Run Stage 1 of the PoC.
The SSTI evaluates attacker-controlled templates.{{ 7*7 }} returns 49 through the vulnerable path.Run Stage 2 of the PoC.
The chain enables Pre-Auth RCE.Auth bypass + SSTI = unauthenticated template injection with admin context.Run the full chain PoC.
The PoC is HTTP-only.poc.py sends HTTP POST requests only.Inspect poc/poc.py.

Root Cause Analysis

CVE-2026-27604: Auth Bypass

The FOSSBilling API resolves roles from the URL path:

/api/:role/:module/:method

The role checker validates whether the requested role is allowed. However, in vulnerable versions, the exception for disallowed roles is instantiated but never thrown:

// Simplified vulnerable pattern
if (!in_array($role, $allowed_roles)) {
    new \Exception("Role not allowed");  // BUG: missing "throw"
}

Because the exception is never thrown, the validation silently passes. The role system resolves to the cron admin identity, granting full admin API access to any unauthenticated caller.

The security impact:

/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)

The system role maps to the internal cron admin identity, which has full administrative privileges.

CVE-2026-28496: SSTI

The string_render admin API method receives _tpl from request data and passes it into the Twig template rendering pipeline without sandbox enforcement:

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);
}

The renderString() method falls through to createTemplateFromString():

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;
}

The critical issue: createTemplate($tpl) creates a Twig template from the attacker-controlled string and renders it without sandbox restrictions. The template has access to objects in the template context, including the guest API handler which exposes getDi().

Combined Chain

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

Source Patch Summary

FOSSBilling 0.8.0 addresses both vulnerabilities:

Download Tool