
CVE-2026-77818 - Yordam Kütüphane Otomasyon Sistemi - Injection HTML réfléchie à trois points distincts, détournement d'action de formulaire et vol d'identifiants (CWE-79)
CVE-2026-77818 · CVSS 3.1 6.1 (Moyen) · Présidence de la Cybersécurité · Publication 2026-09-04 · TR-26-1011
Statut : Les vulnérabilités ont été corrigées dans la version v22.2. Les installations concernées doivent être mises à niveau vers v22.2 ou une version ultérieure.
Le système d'automatisation de bibliothèque Yordam est un logiciel commercial d'automatisation de bibliothèque et de catalogue en ligne (OPAC) largement utilisé dans les bibliothèques universitaires, publiques et institutionnelles en Turquie. L'installation est sur site ; chaque client exécute une copie distincte au sein de son institution.
Dans la version v22.1 du produit, on trouve des injections HTML réfléchies à trois points distincts et indépendants. Aucune des trois ne nécessite d'authentification, et chacune est déclenchée par un simple lien.
| # | Point | Cause racine |
|---|
| 1 | Page de connexion, paramètre devam | Aucun échappement appliqué |
| 2 | Attribut value d'un champ de formulaire masqué | Double décodage URL après échappement |
| 3 | Attribut name d'un champ de formulaire masqué | Échappement appliqué uniquement à la valeur, pas au nom |
Comme les trois se trouvent dans la même version du même produit et relèvent de la même classe de vulnérabilité, elles ont été regroupées sous un seul avis et publiées sous un seul identifiant CVE. En termes d'impact, le point n° 1 est le plus grave.
devamC'est le plus critique. Le point d'injection se trouve directement dans la balise HTML du formulaire d'authentification lui-même.
Le paramètre devam transporte l'adresse vers laquelle l'utilisateur reviendra après la connexion et arrive encodé en hexadécimal — la valeur 2f796f7264616d2f signifie /yordam/. L'application décode cette valeur depuis l'hexadécimal et l'écrit dans la balise d'ouverture du formulaire de connexion. Aucun échappement n'est appliqué entre les deux :
<form class='girisForm collapse show ikiAdimliGiris' method='post'
action='inc/islem.fm.inc.php'
data-url='<ENTRÉE UTILISATEUR DÉCODÉE EN HEXADÉCIMAL>'
autocomplete="off">
Dans la sortie, les caractères <, > et les guillemets apparaissent bruts. La seule chose qui retient le payload est que l'attribut data-url est entouré de guillemets simples. Lorsqu'un guillemet simple est inséré dans l'entrée, cela suffit : l'attribut se ferme, la balise <form> se ferme, et le HTML écrit par l'attaquant remplace le formulaire d'authentification de la page.
L'action du formulaire est détournée. Aucun faux formulaire n'est dessiné ici — le formulaire propre de l'application est laissé vide et fermé, puis un nouveau <form> portant les mêmes classes CSS est ouvert immédiatement après. Comme les champs de nom d'utilisateur, de mot de passe et de code de vérification de la page proviennent tous du HTML d'origine de l'application, ils restent à l'intérieur de ce nouveau formulaire. L'utilisateur voit le vrai formulaire, remplit le vrai formulaire ; les informations saisies partent vers le serveur de l'attaquant. Il n'y a aucune différence visuellement perceptible.
Le point crucial : l'injection ne se produit pas sur une page quelconque, mais sur la page où l'utilisateur est déjà censé saisir son mot de passe. Dans une injection réfléchie ordinaire, l'attaquant doit convaincre la victime ; ici, c'est l'interface de l'application elle-même qui fait le travail de persuasion.
value d'un champ de formulaire masqué — Double décodage URLSur la page de recherche, les valeurs des paramètres GET sont écrites dans des champs de formulaire masqués. Un échappement est appliqué à ce stade — mais dans le mauvais ordre.
La même valeur q est utilisée dans trois contextes distincts au sein d'une même réponse, chacun ayant une profondeur de décodage différente :
| Contexte | Décodage | Statut |
|---|---|---|
Chaîne JS dans un bloc <script> | 1 fois | Sûr |
Champ de recherche principal <input value="…"> | 1 fois | Sûr |
Champs de formulaire masqués <input type='hidden' value="…"> | 2 fois | Vulnérable |
La séquence d'opérations est la suivante :
Entrée client : %2522
↓ analyse $_GET
Variable PHP : %22
↓ filtre d'entrée → ne voit aucun contenu malveillant, pas de guillemet présent
↓ htmlspecialchars → aucun caractère à échapper, aucune modification
↓ urldecode → %22 est décodé
Écrit sur la page : " ← guillemet brut, sortie de l'attribut
Alors que le filtre d'entrée et l'échappement opèrent sur la première couche de décodage, la sortie est alimentée par la seconde couche. La différence est clairement visible en comparant les versions à encodage simple et double du même payload :
| Envoyé | Réponse | Sortie du champ masqué |
|---|---|---|
q=foo%22… (encodage simple) | 302 Found | value="foo"…" — le filtre l'attrape |
q=foo%2522… (double encodage) | 200 OK | value="foo"><…>" — HTML brut |
La vulnérabilité n'est pas spécifique au paramètre q. Le bloc qui génère les champs masqués parcourt tous les paramètres GET de la requête ; elle a également été vérifiée sur tip et alan.
name d'un champ de formulaire masqué — Injection dans le nom du paramètreLe même bloc génère la structure suivante pour chaque paramètre GET :
<input type='hidden' name="<NOM DU PARAMÈTRE>" value="<VALEUR DU PARAMÈTRE>"/>
L'échappement n'est appliqué que du côté value. Il n'est jamais appliqué du côté name. À ce stade, le double encodage n'est même pas nécessaire — un simple encodage suffit, car il n'y a aucun échappement à contourner.
Un nom de paramètre inventé est écrit directement et brut dans l'attribut name, permettant de sortir de l'attribut. Comme le nom du paramètre est sous le contrôle de l'attaquant, il n'a pas besoin d'être un paramètre reconnu par l'application.
Les points n° 2 et n° 3 de ces trois points proviennent du même bloc de code, et ce bloc se répète dans six formulaires distincts : dilForm, adetForm, siralaForm, tkForm, ekForm, tmForm. Autrement dit, en une seule requête, l'injection se produit six fois.
Le caractère dynamique du bloc a été vérifié en comparant la sortie de deux requêtes :
Requête A : ?p=1&dil=0&alan=&tip=basit&gorunum=liste&q=…
Sortie A : name="p" · name="alan" · name="tip" · name="gorunum" · name="q"
Requête B : ?p=2&dil=0&devam=…
Sortie B : name="p" · name="devam"
Les champs générés ne proviennent pas d'une liste fixe, mais sont dérivés directement des paramètres de la requête. Par conséquent, le contenu écrit à la fois dans les attributs name et value est sous le contrôle de l'attaquant.
La seule chose dont l'attaquant a besoin est un lien que la victime ouvrira. Il n'a pas besoin de se connecter ni d'avoir un compte.
action du formulaire de connexion est redirigée vers l'attaquant. Vérifié.Comme la plateforme concernée héberge les identifiants et les données personnelles des membres de la bibliothèque, l'accès aux dossiers des membres est possible via les comptes compromis.
L'application utilise une CSP, avec script-src et object-src basés sur des nonces ; autrement dit, les XSS classiques basés sur des scripts ne fonctionnent pas sur ces pages. À première vue, cela semble réduire la découverte au niveau d'une « simple altération de contenu ».
La politique complète est la suivante :
Content-Security-Policy: script-src 'nonce-...'; object-src 'nonce-...'; frame-ancestors 'self'
Il n'y a pas de form-action. Il n'y a pas non plus de default-src — donc aucune valeur par défaut vers laquelle retomber pour les directives non définies. Résultat : rien dans le navigateur n'empêche le formulaire d'envoyer un POST vers le serveur de l'attaquant.
Pour voler des identifiants, il n'est pas nécessaire d'exécuter du JavaScript. Du HTML simple suffit, et la CSP n'arrête pas le HTML simple.
Principale
Connexes
Dans l'enregistrement CVE, la faiblesse principale est classée comme CWE-79. Au niveau de la cause racine, CWE-116 est plus explicite : la cause des trois points est que l'échappement de sortie n'est soit jamais appliqué, soit appliqué dans le mauvais ordre.
Il convient de noter qu'aucun script n'est exécuté dans ce produit — la politique script-src basée sur des nonces envoyée par le produit lui-même ne le permet pas, et la valeur du nonce ne peut pas être lue en cross-origin. L'impact réel n'est pas l'exécution de scripts, mais l'injection HTML et le détournement du formulaire de connexion. C'est également pour cette raison que la correspondance CAPEC-148 (Content Spoofing) a été établie.
CWE-174 s'applique particulièrement au point n° 2 — le décodage d'une même donnée une seconde fois après l'échappement.
Moyen — Score de base CVSS 3.1 6.1 (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)
L'attaquant n'a besoin d'aucun privilège ; comme la victime doit ouvrir le lien préparé, l'interaction utilisateur est Requise. Le Scope est défini sur Changed, car le contenu injecté est traité dans le contexte de sécurité du navigateur.
Les trois points correspondent tous au même score. En termes d'impact, le point n° 1 est le plus grave : comme l'injection se produit directement dans la balise du formulaire d'authentification lui-même, le détournement de la cible action du formulaire et le vol d'identifiants sont possibles.
Système d'automatisation de bibliothèque Yordam
Concernées : v22.1 et antérieures
Corrigées : v22.2
La vérification a été effectuée sur v22.1. Les vulnérabilités ne proviennent pas d'une erreur de configuration spécifique à une institution, mais de composants d'interface communs du produit ; elles affectent toutes les installations de la même famille de versions. L'état des versions plus anciennes doit être évalué par le fabricant.
Comme les installations sont sur site, même si le fabricant a publié le correctif, les installations qui n'ont pas appliqué la mise à jour restent vulnérables.
| # | Point de terminaison | Point de sortie |
|---|---|---|
| 1 | GET /yordam/?p=2&dil=<n>&devam=<hex> | Attribut data-url du formulaire de connexion |
| 2 | GET /yordam/?p=1&…&<paramètre>=<payload> | Attribut value du champ de formulaire masqué |
| 3 | GET /yordam/?p=1&…&<payload>=1 | Attribut name du champ de formulaire masqué |
Les points n° 2 et n° 3 proviennent du même bloc générateur de champs masqués ; le bloc se répète dans les formulaires dilForm, adetForm, siralaForm, tkForm, ekForm et tmForm.
Les vulnérabilités ont été corrigées par le fabricant. L'application doit être mise à niveau vers v22.2 ou une version ultérieure.
| Identifiant CVE | CVE-2026-77818 |
| Assignateur (CNA) | TR-CERT (USOM) — Présidence de la Cybersécurité de la République de Turquie |
| Statut | PUBLISHED |
| Réservé | 2026-08-21 |
| Publication | 2026-09-04 |
| Avis de sécurité | TR-26-1011 |
| Titre de l'enregistrement CVE | Reflected HTML Injection via Form Hijacking in Yordam Informatics's Library Automation System |
| CAPEC | CAPEC-148 — Content Spoofing |
Fabricant : Yordam Bilgi Teknolojileri Danışmanlık Eğitim ve Elektronik Sistemler Sanayi ve Ticaret A.Ş.
Alkım Coşkun – Netlore Security
| Date | Événement |
|---|---|
| 2026-08-20 | Vulnérabilités découvertes et vérifiées |
| 2026-08-21 | Signalées à la Présidence de la Cybersécurité ; identifiant CVE réservé |
| 2026-09-04 | CVE-2026-77818 publié, avis de sécurité TR-26-1011 annoncé |