Ir para o conteúdo principal

Começa com um, acaba com outro

·1204 palavras·6 minutos
Exposição base de dados correio segurança spam
Vitor Pinho
Autor
Vitor Pinho
O informático de casa

Há muito que clamo pela automatização de serviços públicos, porque tratar-se algo neste país envolve muita burocracia, muito papel e muitas… outras coisas. Felizmente, com a entrada dos Serviços Públicos Eletrónicos ou SEPE, algumas operações podem já ser feitas online (como a criação de empresas ou compra de um domínio .ao), mas todas as mensagens de correio enviadas para mim (sejam elas notificações ou alertas) vão diretamente para a pasta de Spam. A resposta típica de que é só marcares como correio fidedigno não funciona para mim, porque se todas as mensagens estão a ir para a pasta de lixo eletrónico, existe um problema obscuro por aí.

Em detalhe analiso o email de recuperação de dados através da informação disponível no seu cabeçalho, em nenhuma ordem particular.

O que faz a mensagem cair na pasta de Lixo Eletrónico?
#

Para melhor proteção de correio não solicitado, a maioria dos gateways de correio anexam uma pontuação de acordo com elementos detetados no email (por exemplo, se o assunto foi escrito todo em maiúsculas, se a mensagem tem apenas imagens ou contem imagens remotas, se o seu domínio consta em alguma blacklist, etc). A mesma é referenciada como X-Spam-score. Para comparação, uma mensagem que chega ao valor agregado de 5 ou acima é considerada spam. Uma mensagem de marketing do Banco Atlântico vai desde 1.6 até 4.5, um comprovativo de transferência do Multicaixa Express regista 0.0, uma mensagem de recuperação de senha do SEPE vai logo para os 8.9. Abaixo os elementos em detalhe que fazem parte da pontuação:

X-Spam-score: 8.9
X-Spam-hits: BAYES_00 -1.9, HTML_IMAGE_ONLY_12 2.059, HTML_MESSAGE 0.001,  ME_NOAUTH 0.01, ME_QUARANTINE 8, ME_ZS_CLEAN -0.001, MPART_ALT_DIFF 0.79,
SPF_HELO_NONE 0.001, T_REMOTE_IMAGE 0.01, T_SPF_PERMERROR 0.01, LANGUAGES pt, BAYES_USED user, SA_VERSION 3.4.2

Na X-Spam-hits, o elemento de maior pontuação é ME_QUARANTINE que com 8 valores, pode ser identificado como a causa das mensagens irem parar a pasta de Spam.

DMARC
#

Procurando pela internet, descubro que o ME_QUARANTINE está ligado ao DMARC, um de três elementos usados na proteção e validação de fidelidade de servidores de correio na internet.

Analisando outros elementos presentes no cabeçalho confirmam a minha teoria:

X-Spam-known-sender: no ("Email failed DMARC policy for domain")
X-Disposition-Quarantine: Quarantined due to DMARC policy

A mensagem foi posta em quarentena porque a política do DMARC para o domínio sepe.gov.ao assim a obriga, conforme o extrato da informação obtida através do MXToolbox, uma ferramenta de visualização de registos DNS:

registo-dmarc-sepe

De acordo com o registo DMARC, todas as mensagens que falharem a verificação do domínio devem ser postas em quarentena, o que lhe valeu a pontuação de 8 valores, mandando-a para a pasta de Spam.

Porque é que a verificação falha?
#

Para descobrirmos a resposta a essa pergunta, analiso a sua origem:

Received: from web2.clusterx.net (web2.clusterx.net [54.36.176.165]) by mx6.messagingengine.com (Postfix) with ESMTP for <xx@vitorpinho.com>; Sat,  6 Jul 2019 18:34:53 -0400 (EDT)

A mensagem é enviada de web2.clusterx.net com o IP 54.36.176.165, alocado em França (isso é outra cena que não entendo, mas não desviemos o assunto). Com essa informação, partimos para os resultados de autenticação do DMARC, também presentes no cabeçalho:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
ARC-Authentication-Results: i=1; mx6.messagingengine.com; arc=none (no signatures found);
dkim=none (no signatures found);
dmarc=fail policy.published-domain-policy=quarantine
policy.published-subdomain-policy=none
policy.applied-disposition=quarantine
policy.evaluated-disposition=quarantine policy.arc-aware-result=fail
(p=quarantine,sp=none,d=quarantine,d.eval=quarantine,arc_aware_result=fail)
policy.policy-from=p header.from=sepe.gov.ao;
iprev=pass smtp.remote-ip=54.36.176.165 (web2.clusterx.net);
spf=permerror smtp.mailfrom=xx@sepe.gov.ao
smtp.helo=web2.clusterx.net;
x-aligned-from=pass (Address match);
x-ptr=pass smtp.helo=web2.clusterx.net policy.ptr=web2.clusterx.net;
x-return-mx=pass header.domain=sepe.gov.ao policy.org_domain=gov.ao
policy.is_org=no (MX Records found: mail3.gov.ao);
x-return-mx=pass smtp.domain=sepe.gov.ao policy.org_domain=gov.ao
policy.is_org=no (MX Records found: mail3.gov.ao);
x-vs=clean score=0 state=0;
x-zs=clean

A linha 9 e 13 confirmam que o servidor que enviou a mensagem tem permissão para tal. As 6-7 e 14-17 mostram a razão da falha: o registo MX mail3.gov.ao que é usado para validar pertence ao domínio gov.ao, enquanto que o domínio que está a enviar a mensagem é sepe.gov.ao. Ou seja, a mensagem vem de um domínio diferente: em vez de gov.ao, vem de sepe.gov.ao e vê como não sendo fidedigna. O endereço MX deveria ser mail3.sepe.gov.ao para assim validar com sucesso.

No meio disso tudo, também está registado um erro no registo SPF. Extraindo o registo do mesmo, noto logo um pequeno erro:

registo-spf-sepe

Oops!

Como resolver?
#

As soluções são simples de se implementar:

  • No caso do DMARC, reduzir o nível da política em questão para none, ou alterar o nome do servidor MX para o correto.
  • No caso do SPF, adicionar os dois pontos que faltam para que o servidor com o IP mencionado consiga validar as mensagens. Como o SoftFail está especificado, as mensagens são entregues, mas marcadas que falharam a verificação e podem ir para a pasta de Spam. Em resumo, se o serviço vai estar disponível para mais de 10 pessoas, testem extensivamente antes de o disponibilizarem e não varram problemas sérios como uma coisa normal. Outro problema? Poderia parar no correio, mas para ensinar futuras gerações sobre boas práticas, tenho de falar sobre o conteúdo da mensagem, que é sobre a recuperação de dados:
Caro(a) Vitor Pinho,

Os seus dados de acesso ao portal Serviços Públicos Electrónicos são os seguintes:

Utilizador: xx@vitorpinho.com
Senha: 3fkM9rNamykJp8seMNAFU

Obrigado,
Serviços Públicos Electrónicos - http://www.sepe.gov.ao

A olho nu, parece estar tudo normal, mas para desenvolvedores e programadores web, a mensagem mostra um conteúdo assustador: a senha em descoberto.

Normalmente, quando se clica em recuperar senha num website, ele envia uma mensagem a pedir que se redefina uma nova, pois a aplicação não tem, não sabe nem deve saber a sua senha.

No caso acima, a senha é enviada para o utilizador, o que quer dizer uma de duas coisas: ou ela é mantida em estado reversível, ou está como texto na base de dados. E isto é uma falha muito grave!

Quem tiver acesso à base de dados (direta ou indiretamente), pode também ter acesso às senhas e posteriormente, a todos os dados guardados no SEPE. Caso a mesma seja vítima de um roubo de informação, todas as contas dos clientes estarão comprometidas.

A maneira correta de se guardar uma senha numa base de dados é com uma função hash criptográfica, que é basicamente uma encriptação de um sentido apenas. Dese modo, quando o utilizador fizer o login, a senha inserida é encriptada e comparada com a que se encontra na base de dados. Se forem iguais, o utilizador entra. Caso contrário, o utilizador recebe um aviso de que a senha é inválida. Se a base de dados for comprometida, as senhas não o serão, impedindo assim o acesso direto pelo website do SEPE, salvo se o conteúdo presente na base de dados não aderir às boas práticas de segurança (da senha já sei que não).

É fácil de resolver?
#

Depende de como a aplicação frontend e a base de dados estão estruturadas. É necessário redesenhar a aplicação para que guarde as senhas inseridas como encriptadas e quando for pedido uma recuperação de senha, enviar um link para a troca da mesma em vez de mostrar a senha antiga. E no final, impedir o utilizador de usar as senhas inseguras, forçando a redefinir uma nova.

No final de tudo, o conselho é o mesmo: Não corta caminho porque vais poupar uns minutos a mais no serviço. Lembra-te: tens mais trabalho hoje para teres menos trabalho amanhã.