
CVE-2026-77818 - Sistema de Automação de Biblioteca Yordam - Injeção de HTML refletida em três pontos distintos, sequestro de ação de formulário e roubo de credenciais (CWE-79)
CVE-2026-77818 · CVSS 3.1 6.1 (Médio) · Presidência de Cibersegurança · Publicado em 2026-09-04 · TR-26-1011
Status: As vulnerabilidades foram corrigidas na versão v22.2. As instalações afetadas devem ser atualizadas para v22.2 ou superior.
O Sistema de Automação de Biblioteca Yordam é um software comercial de automação de bibliotecas e catálogo online (OPAC) amplamente utilizado em bibliotecas universitárias, públicas e institucionais na Turquia. A instalação é on-premise; cada cliente executa uma cópia separada em sua instituição.
Na versão v22.1 do produto, existem injeções de HTML refletidas em três pontos distintos e independentes. Nenhum deles exige autenticação, e todos são acionados por um único link.
| # | Ponto | Causa raiz |
|---|---|---|
| 1 | Página de login, parâmetro devam | Nenhum escape aplicado |
| 2 | Atributo value de campo de formulário oculto | Dupla decodificação de URL após o escape |
| 3 | Atributo name de campo de formulário oculto | Escape aplicado apenas ao valor, não ao nome |
Como os três ocorrem na mesma versão do mesmo produto e na mesma classe de vulnerabilidade, foram agrupados em um único aviso e publicados sob um único ID de CVE. Em termos de impacto, o ponto nº 1 é o mais grave.
devamEste é o mais crítico. O ponto de injeção está diretamente na própria tag HTML do formulário de autenticação.
O parâmetro devam carrega o endereço para o qual o usuário retornará após o login e chega codificado em hex — o valor 2f796f7264616d2f significa /yordam/. A aplicação decodifica esse valor de hex e o escreve na tag de abertura do formulário de login. Não há nenhuma operação de escape no meio:
<form class='girisForm collapse show ikiAdimliGiris' method='post'
action='inc/islem.fm.inc.php'
data-url='<ENTRADA DO USUÁRIO DECODIFICADA EM HEX>'
autocomplete="off">
Na saída, os caracteres <, > e aspas aparecem brutos. A única coisa que contém o payload é o fato de o atributo data-url estar entre aspas simples. Quando uma aspa simples é inserida na entrada, isso também termina: o atributo é fechado, a tag <form> é fechada e o HTML escrito pelo atacante substitui o formulário de autenticação da página.
O action do formulário é sequestrado. Aqui não é desenhado um formulário falso — o formulário da própria aplicação é deixado vazio e fechado, e imediatamente em seguida uma nova <form> com as mesmas classes CSS é aberta. Como os campos de nome de usuário, senha e código de verificação na página são todos do HTML original da aplicação, eles permanecem dentro desse novo formulário. O usuário vê o formulário real, preenche o formulário real; as informações inseridas vão para o servidor do atacante. Não há nenhuma diferença visualmente distinguível.
O ponto crítico: a injeção não ocorre em uma página aleatória, mas na página onde já se espera que o usuário digite sua senha. Em uma injeção refletida comum, o atacante precisa convencer a vítima; aqui, a própria interface da aplicação faz o trabalho de convencimento.
value de Campo de Formulário Oculto — Dupla Decodificação de URLNa página de busca, os valores dos parâmetros GET são escritos em campos de formulário ocultos. Neste ponto, o escape é aplicado — mas na ordem errada.
O mesmo valor q é usado em três contextos diferentes dentro de uma única resposta, e cada um tem uma profundidade de decodificação diferente:
| Contexto | Decodificação | Status |
|---|---|---|
String JS em bloco <script> | 1 vez | Seguro |
Caixa de busca principal <input value="…"> | 1 vez | Seguro |
Campos de formulário ocultos <input type='hidden' value="…"> | 2 vezes | Vulnerável |
A sequência de operações é a seguinte:
Entrada do cliente : %2522
↓ análise de $_GET
Variável PHP : %22
↓ filtro de entrada → não vê conteúdo malicioso, não há aspas
↓ htmlspecialchars → nenhum caractere para escapar, sem alteração
↓ urldecode → %22 é decodificado
Escrito na página : " ← aspa bruta, saída do atributo
Enquanto o filtro de entrada e o escape operam na primeira camada de decodificação, a saída é alimentada pela segunda camada. A diferença fica clara ao comparar as versões codificadas uma e duas vezes do mesmo payload:
| Enviado | Resposta | Saída do campo oculto |
|---|---|---|
q=foo%22… (codificação única) | 302 Found | value="foo"…" — o filtro captura |
q=foo%2522… (codificação dupla) | 200 OK | value="foo"><…>" — HTML bruto |
A vulnerabilidade não é específica do parâmetro q. O bloco que gera campos ocultos itera sobre todos os parâmetros GET da requisição; também foi validado em tip e alan.
name de Campo de Formulário Oculto — Injeção no Nome do ParâmetroO mesmo bloco gera a seguinte estrutura para cada parâmetro GET:
<input type='hidden' name="<NOME DO PARÂMETRO>" value="<VALOR DO PARÂMETRO>"/>
O escape é aplicado apenas ao lado do value. Não é aplicado ao lado do name. Neste ponto, também não há necessidade de codificação dupla — uma única codificação é suficiente, pois não há escape a ser contornado.
Um nome de parâmetro inventado é escrito diretamente e bruto no atributo name, e é possível sair do atributo. Como o nome do parâmetro está sob controle do atacante, não precisa ser um parâmetro reconhecido pela aplicação.
Os pontos nº 2 e nº 3 destes três pontos originam-se do mesmo bloco de código, e esse bloco se repete em seis formulários diferentes: dilForm, adetForm, siralaForm, tkForm, ekForm, tmForm. Ou seja, em uma única requisição, a injeção ocorre seis vezes.
A natureza dinâmica do bloco foi confirmada comparando a saída de duas requisições:
Requisição A: ?p=1&dil=0&alan=&tip=basit&gorunum=liste&q=…
Saída A: name="p" · name="alan" · name="tip" · name="gorunum" · name="q"
Requisição B: ?p=2&dil=0&devam=…
Saída B: name="p" · name="devam"
Os campos gerados não vêm de uma lista fixa, mas são derivados diretamente dos parâmetros da requisição. Portanto, tanto o conteúdo escrito no atributo name quanto no value está sob controle do atacante.
A única coisa que o atacante precisa é de um link que a vítima abra. Não precisa estar autenticado nem ter uma conta.
action do formulário de login é redirecionado para o atacante. Confirmado.Como a plataforma afetada armazena credenciais e dados pessoais de usuários da biblioteca, é possível acessar os registros de membros por meio de contas comprometidas.
A aplicação usa CSP, e script-src e object-src são baseados em nonce; ou seja, o XSS clássico baseado em script não funciona nessas páginas. À primeira vista, isso parece reduzir o achado ao nível de "apenas adulteração de conteúdo".
A política completa é a seguinte:
Content-Security-Policy: script-src 'nonce-...'; object-src 'nonce-...'; frame-ancestors 'self'
Não há form-action. Também não há default-src — portanto, não há um padrão para o qual recorrer para diretivas não definidas. Resultado: o navegador não bloqueia de forma alguma o formulário de fazer POST para o servidor do atacante.