Um use-after-free no librsvg, com RCE confirmada em diversas aplicações.
01 / the bug
O mesmo nome, outra entidade.
O librsvg usa o libxml2 para ler o XML de uma imagem SVG. Durante a expansão de uma entidade, um XInclude pode iniciar a leitura de outro documento. Os dois parses compartilham o mapa de entidades do librsvg.
Se o documento incluído declara uma entidade com o mesmo nome, o librsvg substitui a entrada e libera a anterior. O parse externo ainda guarda um ponteiro para ela. Quando ele continua, usa memória já liberada, que pode ter sido ocupada por outro objeto.
01 / retainouter parse↓xmlEntity Apointer still held
02 / replacenested XInclude↓free(A)same entity name
Confirmei RCE em diversas aplicações que usavam librsvg. Next.js e Ghost são os casos que reportei e que geraram advisories públicos, detalhados abaixo.
Cada produto levava o input até o parser de um jeito. Ter librsvg entre as dependências, por si só, não basta para que a aplicação seja explorável.
01
Next.js / ImageResponse
text → Satori → SVG → Sharp / libvips → librsvg
Uma falha separada de escaping no Satori permitia que o texto controlado pelo atacante alterasse o SVG gerado. No runtime Node.js, ImageResponse enviava esse SVG para o pipeline nativo de imagens. O caminho não se aplica ao runtime Edge.
Quando a API aceitava uma fonte de imagem controlada pelo atacante, uma imagem preparada podia passar pela rejeição de SVG e depois ser interpretada como SVG pelo Sharp/libvips. Isso expunha o UAF a requisições sem autenticação em Linux com glibc, sem envolver Satori.
Um usuário da equipe, incluindo Contributor, podia criar um bookmark card para um site sob seu controle. Ao processar a imagem do card, o Ghost alcançava a biblioteca vulnerável. Esse caminho também permitia executar comandos no servidor.