Saltar para o conteúdo
Voltar ao trabalho

Trabalho · Exposição de base de dados · 2026

Quatro tabelas abertas durante oito semanas

Num Postgres alojado, quatro tabelas criadas fora dos ficheiros de migração herdaram permissões públicas e nenhuma segurança por linha. Qualquer pessoa com a chave pública podia ler, inserir, alterar e apagar. Foi assim que se encontrou, fechou e verificou a partir de fora.

1. Como o buraco abriu

Um produto de diretório com cerca de nove mil páginas corre num Postgres alojado onde cada tabela é criada por um ficheiro de migração que também ativa a segurança por linha e escreve as políticas. Em junho, uma desduplicação da tabela principal foi feita à mão e deixou para trás quatro tabelas de trabalho, duas cópias e dois mapeamentos, criadas com create table as select a partir do painel.

Uma tabela criada assim recebe os defaults do esquema: sem segurança por linha, e com as permissões públicas que a plataforma dá ao papel anónimo. A partir desse dia, as quatro tabelas podiam ser lidas e escritas por quem tivesse a chave pública que vem dentro da aplicação web.

2. Como se encontrou, e o que o alerta acertou mal

O advisor da plataforma enviou um email em agosto a nomear uma tabela, detetada no dia nove. A análise estava certa sobre o que viu e errada sobre a forma do incidente: eram quatro tabelas, e a exposição começou a catorze de junho, oito semanas antes. Um advisor reporta a sua própria análise, e a data da análise nunca é a data do incidente.

As tabelas guardavam dados de trabalho da desduplicação, por isso a exposição era de dados de listagens já públicos no site. O acesso de escrita era o problema real: qualquer visitante podia ter alterado o mapeamento que o produto usava.

3. Fechar, e provar que fechou

A correção foi uma migração que ativa a segurança por linha nas quatro tabelas sem adicionar políticas, o que nega tudo ao papel anónimo. A prova veio de fora: um pedido a cada tabela com a chave pública devolvia 206 antes da migração e 401 depois. Uma correção confirmada só no painel é uma correção em que se acredita; um 401 vindo da internet pública é uma que se sabe.

A consulta de auditoria abaixo corre agora depois de qualquer alteração próxima de uma migração. Só a tabela de referência do PostGIS deve aparecer sem segurança por linha, porque pertence à extensão.

A auditoria, corrida quando entra uma migração
select c.relname,
       c.relrowsecurity as rls_enabled,
       (select count(*) from pg_policies p
         where p.tablename = c.relname) as policies,
       has_table_privilege('anon', c.oid, 'SELECT') as anon_select
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relkind = 'r'
order by c.relrowsecurity, c.relname;

4. O que levar daqui

  • 1

    A disciplina de migrações é a única coisa que impõe a segurança por linha. Uma tabela criada de outra forma está aberta por defeito.

  • 2

    Verifique a partir de fora com a chave pública. O painel mostra a intenção; o 401 mostra o estado.

  • 3

    Trate um alerta do advisor como o resultado de uma análise. Estabeleça a contagem e a data de início antes de escrever o incidente.