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.
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.