Bug de espelhamento de lista de emails com implicações de segurança

Encontrei um bug interessante e obscuro em relação à forma como as respostas a postagens em listas de discussão que são espelhadas no Discourse são arquivadas.

Tenho evidências de que respostas a uma lista de discussão podem ser incorretamente arquivadas em uma segunda lista de discussão (com um público diferente) se o e-mail inicial foi enviado para ambas as listas de discussão ao mesmo tempo.

Imagine que eu participo de duas listas de discussão, A e B, inscrito com meu endereço do Gmail. Elas têm públicos potencialmente diferentes. O servidor da lista envia uma única cópia de uma mensagem para aqueles em ambas as listas de discussão, mas a linha To: indica que a mensagem foi enviada para as listas A e B no mesmo e-mail. Este e-mail chega ao meu endereço do Gmail, que então, através de um filtro, encaminha uma cópia para listA@mydiscourse.org.uk, com o Gmail escolhendo uma das duas listas na linha To:. O Gmail está configurado para encaminhar postagens para A para listA@mydiscourse.org.uk e postagens para B para listB@mydiscourse.org.uk. O Discourse está configurado com duas categorias com esses dois endereços de e-mail de espelhamento de entrada diferentes (listA@mydiscourse.org.uk e listB@mydiscourse.org.uk).

A questão de o servidor de listas e o Gmail enviarem apenas uma cópia é separada e não é o assunto deste bug.

Depois disso, uma cópia do e-mail enviado para mim em minha conta do Gmail acaba sendo exibida na categoria associada ao endereço de entrada listA@mydiscourse.org.uk após o Gmail encaminhá-lo.

Tudo bem até agora (além do fato de que apenas um e-mail chegou do servidor de listas em primeiro lugar).

Agora, um usuário separado, que está apenas na lista de discussão B, responde a esse e-mail para o servidor da lista. O servidor da lista envia essa mensagem para todos na lista de discussão B. Isso chega ao meu endereço do Gmail com uma linha To: indicando que foi enviado para a lista B. O Gmail o encaminha para listB@mydiscourse.org.uk.

Mas então o Discourse o arquiva como se tivesse sido enviado por e-mail para listA@mydiscourse.org.uk!

Isso, portanto, revela àqueles com acesso à lista A o conteúdo de uma postagem de um membro da lista B!

Suspeito que o Discourse ignora a rota pela qual o e-mail entrou no Discourse e o arquivou com base nos sinalizadores do ID da mensagem nos cabeçalhos, contornando assim a rota de entrada.

O e-mail original, enviado para A e B, tem um único ID de mensagem dentro dele e suspeito que o arquivamento baseado apenas nesse ID de mensagem esteja ocorrendo.

Se o remetente original tivesse escrito dois e-mails separados para as listas A e B, esse problema não teria ocorrido, pois as duas mensagens teriam seus próprios IDs de mensagem.

Correção sugerida: Se uma categoria está espelhando uma lista de discussão e uma mensagem chega através do endereço de espelhamento que parece, a partir dos cabeçalhos, ser uma resposta a outra postagem que reside em outro lugar no Discourse, então uma nova postagem precisa ser criada (talvez sem um pai óbvio) na categoria esperada, em vez de a resposta acabar em uma categoria que está associada a uma lista de discussão diferente.

De fato, ou:

Acho que é o assunto deste bug. Isso deve ser corrigido no servidor de listas, não no Discourse.

1 curtida

Não tenho certeza se me expliquei muito bem, pois não consigo entender por que o Discourse colocaria uma postagem na categoria errada. É como se ele não estivesse olhando para a rota em (que deveria ter prioridade), mas apenas para o message-id. Para um único e-mail enviado para duas listas de mala direta ao mesmo tempo, haverá um message-id, mas com duas listas de distribuição (que são independentes), dois endereços ‘To:’ e dois endereços ‘Reply-To:’ (com um diferente exibido em cada uma das mensagens, dependendo para qual lista foi enviado).

Se for isso que está acontecendo, o que aconteceria se alguém movesse um tópico para fora de uma categoria que era um espelho de lista de mala direta e o colocasse em outro lugar no Discourse, mas as respostas (via lista de mala direta) continuassem chegando? O Discourse adicionaria essas respostas à categoria associada à lista de mala direta (mesmo que a postagem original possa ter sido movida para outro lugar) ou todas as respostas acabariam magicamente na categoria para onde o tópico foi movido?

O Discourse consegue lidar com duas mensagens em duas categorias ao mesmo tempo que têm o mesmo message-id (mas com endereços ‘To:’ diferentes)?

Independentemente de como o Discourse lida com isso, um Message-ID deve ser único. Na minha opinião, quando um servidor de lista envia uma mensagem para uma lista de e-mail, ele cria uma nova instanciação dessa mensagem e, portanto, deve reescrever o message ID.

Além disso, não consigo entender como a mensagem original poderia ser adequada tanto para membros da lista A quanto da B, mas a resposta do membro da lista B não poderia ser revelada aos membros da lista A. Se esses públicos são tão diferentes, por que o usuário envia as mesmas mensagens para ambas as listas ao mesmo tempo?

Talvez exista uma boa solução técnica para isso e talvez o Discourse possa ser alterado para lidar com isso corretamente, mas acho que este é um caso extremo realmente estranho em uma tecnologia de 36 anos.

Poderia argumentar que, como a mensagem é a mesma, ela tem um único ID de mensagem. De fato, para o exemplo em questão, o autor original compôs a mensagem no Gmail (que atribuiu o ID da mensagem) e ela foi enviada para dois endereços de listas de discussão no mesmo servidor. Isso não é incomum, por exemplo, pode ser um comunicado de imprensa comum para gerentes e clínicos, cada um dos quais está em suas próprias listas de e-mail. Pode haver uma questão médica dentro do comunicado de imprensa que precise de discussão, então um clínico pode responder (e o endereço Reply-to: teria sido definido para a lista de clínicos, mesmo que o cabeçalho To: ainda tivesse ambas as listas de discussão mencionadas). Da mesma forma, os gerentes podem querer discutir sua própria visão das notícias. Eles responderiam e o cabeçalho Reply-to: relevante seria usado para refletir a lista de gerentes. Se um remetente tivesse feito uso dos endereços To: fazendo um “responder a todos”, uma mensagem de rejeição teria sido gerada da lista da qual eles não eram membros.

O comportamento acima não é tão incomum, mas parece que o Discourse não consegue lidar com isso corretamente se for usado como um espelho de lista de discussão e mantiver as respostas ramificadas separadas, pois todas serão vinculadas ao ID da mensagem original e à categoria em que essa postagem apareceu pela primeira vez.

Isso pode significar que os gerentes poderiam ver as postagens dos clínicos, por exemplo, se o clínico, respondendo à lista de clínicos, tivesse essa postagem aparecendo no espelho da lista de gerentes devido à forma como o Discourse arquiva as mensagens.

Uma solução poderia ser verificar cada endereço no cabeçalho To: das mensagens recebidas para ver se ele correspondia a um endereço de espelho de lista de discussão em cada uma das configurações de Categoria. Se correspondesse, uma cópia da mensagem poderia ser postada em cada categoria correspondente, e poderiam haver várias cópias potencialmente da postagem em diferentes categorias. Então, se alguma resposta chegasse, o ID da mensagem poderia ser usado, como é o caso atualmente, mas apenas se a linha To: também correspondesse à categoria.

Uma solução poderia ser uma opção para reescrever o message-id para refletir o id original criado pelo cliente de e-mail do remetente, mais um identificador adicional, por exemplo, o endereço To: da lista de e-mails que o Discourse já procura? Isso significaria que, se uma postagem viesse da lista de e-mails B, mas referenciou um cabeçalho message-id que também estava em uma postagem da lista de e-mails A, ela seria arquivada corretamente pelo Discourse?

Por exemplo. E-mail original enviado simultaneamente para duas listas de e-mails A e B tem message-id único ‘1234567890gmail’.

O Discourse recebe duas cópias encaminhadas para o endereço genérico de entrada do Discourse. A primeira mensagem é arquivada com base no endereço To: ser para a Lista A e o message-id recebe caracteres adicionais anexados pelo Discourse para se tornar ‘1234567890gmailListA’. A segunda mensagem não é arquivada, pois parece um duplicado. (Acho que este é o comportamento atual).

Alguém na Lista B responde usando o endereço To: para a Lista B. O Discourse recebe uma cópia e percebe que há um cabeçalho in reply to que contém ‘1234567890gmail’. O Discourse, vendo que o e-mail entrou com uma linha To: refletindo a Lista B, anexa caracteres ao final para fazer o cabeçalho in reply to parecer ‘1234567890gmailListB’. Em seguida, ele arquiva isso como uma nova mensagem na categoria correta, pois não está mais vinculado à mensagem que foi arquivada contra a Lista A.

Essa abordagem poderia funcionar para transferir arquivos também, onde o mesmo message-id pode ser encontrado em várias listas de e-mails se um usuário enviou a mensagem para várias listas ao mesmo tempo. No ponto de importação, todos os campos message-id (e in reply to) podem ter texto exclusivo anexado vinculado à lista de e-mails nomeada para interromper uma espécie de “conversa cruzada” entre arquivos quando as mensagens são indexadas.