PostgreSQL 18.6 - Alta - Remoto - Escrita de arquivo - pg_basebackup segue symlink tar absoluto remanescente do CVE-2026-6475
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · postgres-basebackup-symlink
Classe: Escrita de arquivo Alcance: Remoto
PostgreSQL 18.6 (724edf9) - PostgreSQL Global Development Group
CVE-2026-6475 adicionou path_is_safe_for_extraction para nomes de membros tar. Alvos de symlink absolutos ainda ignoram essa verificação para que tablespaces funcionem. astreamer_file.c então faz symlink() do alvo e depois fopen(..., "wb") o segue. O formato padrão do pg_basebackup é plain (-F p). O create_target_symlink do pg_rewind verifica o caminho e nunca cria o link.
Uma origem hostil que fala BASE_BACKUP pode plantar um symlink absoluto e sobrescrever qualquer arquivo que o UID do backup possa escrever. Mesmo modelo de vítima do 6475. Isto não é um re-file das verificações de nome de membro.
| ID | ainda sem CVE |
| Classe | Escrita de arquivo (resíduo de symlink tar absoluto do CVE-2026-6475) |
| Alcance | Remoto (UI:R cliente vs PostgreSQL hostil) |
| CWE | CWE-59, CWE-22 |
| CVSS | Alto: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Produto | PostgreSQL |
| Afetado | tag 18.6 REL_18_6 (724edf9bde9d356724ad384a2e196edc3c9f80f7), pg_basebackup / pg_rewind in-tree |
| Autenticação | vítima executa pg_basebackup -D <dir> padrão contra uma origem atacante |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Alguém que consiga fazer um operador executar pg_basebackup -D contra o seu PostgreSQL (o mesmo modelo UI:R do CVE-2026-6475) pode escrever fora de -D.
| Privilégio | Método / sink | Comprovado em lab ou inferido |
|---|---|---|
Integridade: escrever um arquivo fora de -D | Tar BASE_BACKUP hostil: membro com typeflag '2' com um nome relativo seguro (pg_tblspc/16384) e um alvo de link absoluto, depois um membro regular sob esse nome. extract_link então create_file_for_extract fopen(..., "wb") sem O_NOFOLLOW | Comprovado em lab. Escreveu POSTGRES-BASEBACKUP-SYMLINK-WITNESS em /work/oracle/. O destino contém o symlink. O tar de controle (sem symlink) deixou o oracle vazio e escreveu apenas PG_VERSION dentro de -D |
Integridade: sobrescrever shell rc, authorized_keys, uma unit systemd de usuário ou crontab | Mesmo sink, qualquer caminho que o UID do cliente possa escrever | Inferido. Este lab não toca nesses arquivos |
| Disponibilidade: destruir configuração ou chaves do cliente | Mesma escrita | Inferido. Não demonstrado |
| Reconhecimento do disco do cliente | extract é escrita, não leitura | Fechado |
Percorrer .. ou nomes de membros absolutos | path_is_safe_for_extraction | Fechado. Isso é o CVE-2026-6475 |
| SQL sem privilégios no lado do servidor / protocolo sem autenticação | servidor padrão 18.6 | Fechado. Este resíduo é o cliente |
| Backup apenas tar | pg_basebackup -F t armazena o tar sem extrair | Fechado |
RCE dentro do postgres | não é este sink | Fechado |
pg_rewind tem o mesmo resíduo de create_target_symlink / open(). Este lab aciona apenas o pg_basebackup.
Fixe em postgres/postgres REL_18_6 após a onda 18.6 (28 CVEs, mais o conjunto 18.4/18.2 já nesta árvore). Vinte e duas caçadas. Servidor padrão, SQL sem privilégios, protocolo sem autenticação: nenhum neste nível. O CVE-2026-6475 era o irmão a reler.
Nomes de membros são verificados. Alvos de symlink absolutos não são:
if (!is_absolute_path(linktarget) &&
!path_is_safe_for_extraction(member->linktarget))
{
pg_fatal("link target has unsafe path name: \"%s\"",
member->linktarget);
}
extract_link(mystreamer->filename, linktarget);
create_file_for_extract ainda é fopen(filename, "wb"). O comentário em astreamer_file.c:351-356 diz que o mapeamento é aplicado sem verificar se o link está dentro de pg_tblspc.
Caminhos errados já registrados: tratar o 6475 como fechado e ir embora; apontar -D para um diretório de dados ativo; sobrescrever shell rc por teatro. Um servidor 18.6 honesto só emite symlinks pg_tblspc/<oid> e coloca o conteúdo do tablespace em um arquivo separado. Uma origem maliciosa que fala BASE_BACKUP pode colocar o membro regular de acompanhamento no mesmo tar. Esse é o resíduo.
python3 postgres-basebackup-symlink-Abraxas-Labs.py
ou
cd lab
./run.sh
postgres:18.6 como imagem de origem, executando um falante BASE_BACKUP. O cliente é o pg_basebackup in-tree da mesma tag (pg_basebackup (PostgreSQL) 18.6). Loopback 127.0.0.1:19370. Projeto compose postgres-basebackup-symlink. Não aponte -D para um diretório de dados ativo.
SUCCESS postgres-basebackup-symlink control-inside=yes oracle-outside=yes dest-is-symlink=yes image=postgres:18.6 how=pg_basebackup POSTGRES-BASEBACKUP-SYMLINK-WITNESS
Trate alvos de symlink absolutos como inseguros, a menos que sejam reescritos por --tablespace-mapping. Abra arquivos extraídos com O_NOFOLLOW / lstat para que um link plantado não possa ser seguido. Aplique path_is_safe_for_extraction ao link do rewind, bem como ao path. Rejeite um membro regular cujo caminho passe por um symlink que saiu de -D.
724edf9bde9d356724ad384a2e196edc3c9f80f7)src/fe_utils/astreamer_file.c · src/fe_utils/astreamer_tar.csrc/bin/pg_rewind/file_ops.cGNU Affero GPL v3.0. Veja LICENSE. Apenas lab em loopback. Sem garantia.