Provavelmente, você está lendo esta postagem do blog usando seu navegador da web. Provavelmente, seu navegador da Web possui várias extensões que fornecem funcionalidade adicional. Normalmente confiamos que as extensões instaladas de lojas de navegadores oficiais são seguras. Mas nem sempre é o caso, como descobrimos recentemente.
Esta postagem do blog traz mais detalhes técnicos sobre CacheFlow: uma ameaça sobre a qual relatamos pela primeira vez em dezembro de 2020. Descrevemos uma enorme campanha composta de dezenas de extensões de navegador Chrome e Edge maliciosas com mais de três milhões de instalações no total. Alertamos o Google e a Microsoft sobre a presença dessas extensões maliciosas em suas respectivas lojas de extensão e temos o prazer de anunciar que, desde então, as duas empresas retiraram todas elas em 18 de dezembro de 2020.
CacheFlow era notável em particular pela maneira como as extensões maliciosas tentavam esconder seu comando e controlar o tráfego em um canal secreto usando o Cache-Control
cabeçalho HTTP de suas solicitações de análise. Acreditamos que esta é uma nova técnica. Além disso, parece-nos que o tráfego ao estilo do Google Analytics foi adicionado não apenas para ocultar os comandos maliciosos, mas que os autores da extensão também estavam interessados nas próprias solicitações de análise. Acreditamos que eles tentaram resolver dois problemas, comando e controle e obtenção de informações analíticas, com uma solução.
Descobrimos que CacheFlow realizaria seu ataque na seguinte sequência:
Com base em nossa telemetria, os três principais países onde os usuários Avast baixaram e instalaram as extensões do CacheFlow foram Brasil, Ucrânia e França.
Inicialmente, ficamos sabendo dessa campanha lendo uma postagem no blog tcheco de Edvard Rejthar de CZ.NIC . Ele descobriu que a extensão do Chrome “Video Downloader for FaceBook ™” (IDpfnmibjifkhhblmdmaocfohebdpfppkf
) estava carregando furtivamente uma parte ofuscada de JavaScript que não tinha nada a ver com a funcionalidade anunciada da extensão. Continuando com suas descobertas, conseguimos encontrar muitas outras extensões que estavam fazendo a mesma coisa. Essas outras extensões ofereciam várias funcionalidades legítimas, muitas delas baixando vídeos para plataformas populares de mídia social. Após a engenharia reversa do JavaScript ofuscado, descobrimos que a principal carga maliciosa entregue por essas extensões era responsável por redirecionamentos maliciosos do navegador. Não só isso, mas os cibercriminosos também estavam coletando muitos dados sobre os usuários de extensões maliciosas, como todas as suas consultas de mecanismo de pesquisa ou informações sobre tudo o que clicaram.
As extensões exibiram um nível bastante alto de furtividade ao empregar muitos truques para diminuir as chances de detecção. Em primeiro lugar, eles evitaram infectar usuários que provavelmente seriam desenvolvedores da web. Eles determinaram isso por meio das extensões que o usuário instalou ou verificando se o usuário acessou sites hospedados localmente. Além disso, as extensões atrasaram sua atividade maliciosa por pelo menos três dias após a instalação, para evitar o alerta precoce. Quando o malware detectava que as ferramentas do desenvolvedor do navegador estavam abertas, ele desativava imediatamente sua funcionalidade maliciosa. O CacheFlow também verificou todas as consultas de pesquisa do Google e se o usuário estava pesquisando por um dos domínios de comando e controle (C&C) do malware, ele relatava isso ao seu servidor C&C e também podia se desativar.
De acordo com análises de usuários na Chrome Web Store, parece que o CacheFlow estava ativo pelo menos desde outubro de 2017. Toda a furtividade descrita acima poderia explicar por que permaneceu sem ser detectado por tanto tempo.
O canal secreto
Primeiro, mostraremos o backdoor oculto que as extensões usaram para baixar e executar JavaScript arbitrário. Especificamente, descreveremos o backdoor da extensão do Chrome “Downloader for Instagram” v5.7.3 (ID olkpikmlhoaojbbmmpejnimiglejmboe
), mas esta análise se aplica a outras extensões também, uma vez que o código malicioso oculto nelas é muito semelhante em funcionalidade.
Geralmente, é uma boa idéia iniciar a análise de extensões desconhecidas do Chrome a partir do manifest.json
arquivo. O manifesto do “Downloader for Instagram” nos dá algumas informações interessantes.
Em primeiro lugar, o content_security_policy
é definido de forma que seja possível usar a função infame eval
para carregar JavaScript adicional. No entanto, procurar a string eval
no código-fonte da extensão não produziu nenhum resultado interessante. Como mostraremos mais tarde, a extensão usa eval
bastante a função, mas oculta seu uso, portanto, não é imediatamente aparente.
Em segundo lugar, a extensão pede muitas permissões e não está imediatamente claro por que essas permissões seriam necessárias para baixar vídeos do Instagram. Especialmente interessante é a management
permissão, que permite que a extensão controle outras extensões. A combinação do webRequest
e as <all_urls>
permissões também é interessante. Juntas, essas duas permissões possibilitam que a extensão intercepte praticamente qualquer solicitação da Web proveniente do navegador.
Finalmente, o manifesto define dois scripts de segundo plano: js/jquery.js
e js/background.js
. Esses scripts são persistentes, o que significa que continuarão em execução, a menos que a extensão seja desabilitada.
Um desses scripts de segundo plano,, background.js
é onde a webRequest
API suspeita é usada. Este script acessa os cabeçalhos de resposta HTTP de todas as solicitações da web interceptadas e armazena seus valores em localStorage.
O conteúdo localStorage é então lido pelo outro script malicioso fundo persistente: jquery.js
. Embora este script pareça à primeira vista ser a biblioteca jQuery legítima , algumas funções adicionais foram inseridas nele. Uma dessas funções adicionais é nomeada erroneamente parseRelative
, enquanto tudo o que faz é retornar o window.localStorage
objeto.
Outra função inserida e nomeada erroneamente é initAjax
.
Esta função está particularmente interessada no conteúdo de localStorage['cache-control']
, que deve, neste ponto, ser definido como o valor do último Cache-Control
cabeçalho de resposta HTTP recebido . A função divide o conteúdo deste cabeçalho com uma vírgula e tenta descriptografar cada parte usando uma função personalizada chamada strrevsstr
, antes de finalmente analisá-la como uma string JSON.
A questão óbvia agora é por que a extensão espera interceptar solicitações que contêm uma string JSON criptografada no Cache-Control
cabeçalho de resposta?
A resposta é que os atores da ameaça estão usando o conteúdo do Cache-Control
cabeçalho como um canal secreto para enviar comandos ocultos à extensão maliciosa.
Como parte da funcionalidade regular da extensão maliciosa, as solicitações analíticas sobre alguns eventos são enviadas para https://stats.script-protection[.]com/__utm.gif
. Essas são solicitações de análise padrão que se parecem com o Google Analytics. O problema é que o servidor usado por esta extensão pode responder às solicitações de análise com um Cache-Control
cabeçalho especialmente formado , que o cliente irá descriptografar, analisar e executar.
Para ver a aparência dos comandos, simulamos a extensão e enviamos uma solicitação HTTP analítica falsa para https://stats.script-protection[.]com/__utm.gif
. Depois de algumas tentativas, recebemos um Cache-Control
cabeçalho especialmente criado .
Observe que a resposta conterá o comando codificado apenas quando algumas condições forem atendidas. Em primeiro lugar, o parâmetro GET it
deve ser definido pelo menos três dias atrás. Como este parâmetro contém a hora em que a extensão foi instalada, isso garante efetivamente que a extensão não exibirá nenhum comportamento malicioso durante os primeiros três dias. Também há uma verificação baseada no endereço IP, uma vez que repetidamente não recebemos nenhum comando de um endereço IP de origem, embora tenhamos recebido um comando para a mesma solicitação GET de outro endereço IP. Como a lógica por trás dessas verificações está escondida com segurança no servidor C&C, pode haver verificações adicionais das quais não temos conhecimento.
Quando o conteúdo do Cache-Control
cabeçalho recebido é decodificado usando a strrevsstr
função personalizada conforme descrito acima, obtemos o comando no seguinte JSON. Como foi visto na initAjax
função, todos os atributos deste JSON são armazenados no window
objeto global .
Ao receber tal comando, a extensão baixa o segundo estágio command['uu']
em uma função chamada siblingAfter
, que também está oculta dentro jquery.js
. O cifrão command['jj']
aqui representa o jQuery
objeto, então a função usa a jQuery.get
função para fazer o download do próximo estágio command['uu']
e armazená-lo nele localStorage.dataDefault
.
Por fim, há ainda outra função oculta em jquery.js
, que executa o JavaScript baixado usando a eval
função de command['ee']
.
O JavaScript baixado é um downloader intermediário ofuscado. Seu objetivo é fazer o download da carga útil do terceiro estágio ulkon.johnoil[.]com
usando uma solicitação XHR. Infelizmente, como o servidor só enviará o próximo estágio sob certas condições, obter uma resposta contendo o terceiro estágio pode ser bastante complicado. Se o download for feito com êxito, ele será criptografado e armazenado persistentemente em localStorage. Em seguida, ele é executado sempre que uma guia é atualizada usando o chrome.tabs.onUpdated
listener.
A carga útil
A carga útil começa testando se pode fazer uso de eval
e localStorage
. Se qualquer um dos dois não estiver funcionando corretamente, o CacheFlow não será capaz de executar a maior parte de sua funcionalidade maliciosa.
Além disso, a carga útil verifica periodicamente se as ferramentas do desenvolvedor estão abertas. Se estiverem, ele se desativa na tentativa de evitar a detecção. A verificação das ferramentas do desenvolvedor também é realizada sempre que a janela atual é redimensionada, o que pode ser porque o usuário acabou de abrir as ferramentas do desenvolvedor.
Como já foi mencionado, os autores do malware fizeram de tudo para garantir que as cargas maliciosas ocultas não fossem descobertas. Acreditamos que eles não ficaram satisfeitos com a verificação anterior e decidiram fazer um novo perfil da vítima para evitar infectar usuários que pareciam mais experientes em tecnologia. Uma das maneiras de fazer isso foi enumerando as outras extensões instaladas pela vítima e comparando-as com uma lista codificada de IDs de extensão . Cada extensão da lista recebia uma pontuação e, se a soma das pontuações das extensões instaladas excedesse um determinado limite, a lista de extensões seria enviada ao servidor C&C, que poderia então comandar a desativação da carga maliciosa. Exemplos de extensões na lista foram “ Chrome extension source viewer ”, “Link Redirect Trace ”ou“ JWT Debugger ”. Acreditamos que esse sistema de “ponderação” ajudou a diferenciar melhor os sistemas de desenvolvedor reais, que teriam várias dessas extensões e uma pontuação mais alta de usuários casuais que teriam menos extensões e, portanto, uma pontuação mais baixa.
Outra forma de traçar o perfil da vítima em potencial era verificar os URLs em que estavam navegando. Sempre que a vítima navegou para uma URL identificado por um endereço IP de um dos intervalos de IPv4 privados ou para uma URL com um TLD .dev
, .local
ou.localhost
, o malware enviaria a URL visitada para seu servidor C&C. O malware também verificou todas as consultas do Google (e apenas o Google) em relação a uma expressão regular que correspondia a seus domínios C&C e identificadores internos. Dessa forma, ele saberia que alguém estava examinando mais profundamente a extensão e poderia tomar medidas para se ocultar. Curiosamente, os domínios não foram totalmente especificados nas expressões regulares, com alguns caracteres sendo representados como o caractere especial de ponto. Supomos que essa foi uma tentativa de dificultar a criação de uma lista de bloqueio de domínio com base na expressão regular.
Nesse ponto, o malware também tentou coletar informações sobre a vítima. Essas informações incluíam datas de nascimento, endereços de e-mail, geolocalização e atividade do dispositivo. Por exemplo, as datas de nascimento foram recuperadas das informações pessoais inseridas na conta do Google da vítima. Mais uma vez, os invasores se concentraram apenas no Google: não vimos nenhuma tentativa semelhante de obter informações de contas da Microsoft. Para recuperar o aniversário, CacheFlow fez uma solicitação XHR para https://myaccount.google.com/birthday e analisou a data de nascimento da resposta.
Observe que, embora possa parecer que fazer essa solicitação de origem cruzada não seria permitido pelo navegador, tudo isso é perfeitamente possível no modelo de segurança de extensão, uma vez que a extensão tem a <all_urls>
permissão. Essa permissão concede à extensão acesso a todos os hosts, para que ela possa fazer solicitações arbitrárias entre sites.
Para tornar mais difícil para o Google perceber que o CacheFlow estava abusando de seus serviços para coletar informações pessoais, ele também registrou um chrome.webRequest.onBeforeSendHeaders
ouvinte especial . Esse ouvinte remove o referer
cabeçalho da solicitação de todas as solicitações XHR relevantes, para que o Google não saiba facilmente quem está realmente fazendo a solicitação.
Por fim, para executar sua principal funcionalidade maliciosa, a carga útil injeta outra parte do JavaScript em cada guia usando a chrome.tabs.executeScript
função.
O script injetado
O script injetado implementa duas peças de funcionalidade. O primeiro é sobre cliques de sequestro. Quando a vítima clica em um link, a extensão envia informações sobre o clique para orgun.johnoil[.]com
e pode receber um comando para redirecionar a vítima para um URL diferente. A segunda funcionalidade diz respeito aos resultados do mecanismo de pesquisa. Quando a vítima está em uma página de mecanismo de pesquisa, a extensão reúne a consulta de pesquisa e os resultados. Essas informações são então enviadas para o servidor C&C, que pode responder com um comando para redirecionar alguns dos resultados da pesquisa.
Roubo de link
O sequestro de link é implementado registrando-se um onclick
ouvinte sobre o todo document
.
O ouvinte está então interessado apenas em pressionar o botão principal (geralmente “cliques com o botão esquerdo”) e clicar em elementos com o nome da tag a
ou area
. Se o clique atender a todos os critérios, uma solicitação XHR para https://orgun.johnoil[.]com/link/
é enviada. Essa solicitação contém um parâmetro GET a
, que contém informações concatenadas sobre o clique e é criptografado usando a strsstr
função personalizada . Essas informações incluem o local atual, o URL de destino, vários identificadores e muito mais.
Simulamos uma solicitação falsa sobre um clique em um link que leva ae https://facebook[.]com
recebemos a seguinte resposta:
ayiudvh3jk6lNjkzMTQ0eAgYGAQRFhNYTVxbE04IBlFDFgEEHBtYQV0HThdXEwJRBANSUVBEDghQCgNOWUMXAhskaiohB3Z4YQlvSU8oaygLZkhBYCJlAW9Rf18Ecyg1TmZdFEQZABACXHxaInY0MklVQlUeTAozcyUSOwABdW9oAXUXGjswNQpgTkkzZSZFMxMJanwqQj1NDixsflIuWAl6kj3hvduiya
Ao receber essa resposta, o malware primeiro se certifica de que começa com uma determinada string gerada aleatoriamente e termina com a mesma string, mas ao contrário. Essa string ( ayiudvh3jk6l
destacada no exemplo acima) foi gerada pela extensão e também foi incluída no a
parâmetro que foi enviado na solicitação XHR. A extensão então pega a porção intermediária da resposta e a descriptografa usando a strrevsstr
função (que é a inversão de strsstr
). Isso produz a seguinte string:
ayiudvh3jk6lhttps://go.lnkam[.]com/link/r?u=https%3A%2F%2Fwww.facebook[.]com%2F&campaign_id=b7YMMAqMdAL7wyzNe5m3wz&source=uvm3rdsqc9zo69l6kj3hvduiya
Mais uma vez, o malware verifica o início e o fim da string descriptografada para a mesma string gerada aleatoriamente como usada antes e extrai a parte do meio dela. Se começar com a substring http
, o malware prossegue com o sequestro do link. Ele faz isso alterando temporariamente o href
atributo do elemento em que o usuário clicou e executando o click
método nele para simular um clique do mouse. Como um mecanismo de fallback, o malware simplesmente configura window.location['href']
o URL de sequestro de link.
Modificação dos resultados da pesquisa
A segunda funcionalidade é executada apenas se a vítima estiver atualmente em uma página de pesquisa do Google, Bing ou Yahoo. Se estiverem, o malware primeiro reúne a string de consulta de pesquisa e os resultados. A forma como isso é feito varia de acordo com o mecanismo de pesquisa. Para o Google, a string de consulta de pesquisa é encontrada como o valor do primeiro elemento nomeado q
. Se isso falhar de alguma forma, o malware tenta alternativamente obter a consulta de pesquisa do q
parâmetro GET.
Os resultados da pesquisa no Google são obtidos procurando por elementos com o nome da classe rc
e, em seguida, iterando sobre seus a
elementos filhos .
Depois de coletados, a consulta de pesquisa e os resultados são enviados em uma solicitação XHR para servscrpt[.]de
. Uma soma de verificação MD5 com sal dos resultados também está incluída na solicitação, acreditamos em uma tentativa de descobrir solicitações falsas (mas essa verificação pode, obviamente, ser ignorada trivialmente recalculando a soma de verificação MD5). A resposta XHR contém uma lista de domínios cujos links o malware deve sequestrar. O próprio hijack é executado registrando um onmousedown
ouvinte no a
elemento. Depois de disparado, o ouvinte chama a preventDefault
função no evento e, em seguida, window.open
redireciona o usuário para o URL malicioso.
Curiosamente, CacheFlow também modifica alguns dos resultados de pesquisa sequestrados, adicionando um logotipo clicável a eles. Acreditamos que isso seja feito com o objetivo de destacar esses resultados e, assim, aumentar as chances de a vítima clicar neles. No entanto, a posição do logotipo não está bem alinhada, o que faz com que o resultado da pesquisa pareça estranho e suspeito, uma vez que Google, Microsoft ou Yahoo provavelmente se esforçariam um pouco mais para formatá-lo.
O logotipo é adicionado criando um novo div
elemento que contém um img
elemento. Depois de criado e formatado, esse elemento é inserido no DOM, de forma que apareça à esquerda do resultado da pesquisa original. O logotipo é obtido do serviceimg[.]de
domínio, que serve um logotipo 90 × 45 exclusivo por domínio.
Conclusão
Nesta postagem do blog, fornecemos detalhes técnicos sobre CacheFlow: uma enorme rede de extensões de navegador mal-intencionadas que infectou milhões de usuários em todo o mundo. Descrevemos como as extensões maliciosas estavam sequestrando os cliques de suas vítimas e modificando os resultados de seus mecanismos de pesquisa. Como o CacheFlow era bem capaz de se ocultar, cobrimos em detalhes as técnicas que ele estava usando para ocultar o fato de que estava executando um código malicioso em segundo plano. Acreditamos que entender como essas técnicas funcionam ajudará outros pesquisadores de malware a descobrir e analisar ameaças semelhantes no futuro.
Indicadores de compromisso
A lista completa de IoCs está disponível em https://github.com/avast/ioc/tree/master/CacheFlow .
Nome | Cerquilha |
manifest.json | 2bc86c14609928183bf3d94e1b6f082a07e6ce0e80b1dffc48d3356b6942c051 |
background.js | bdd2ec1f2e5cc0ba3980f7f96cba5bf795a6e012120db9cab0d8981af3fa7f20 |
jquery.js | 3dad00763b7f97c27d481242bafa510a89fed19ba60c9487a65fa4e86dcf970d |
Intermediary downloader | 4e236104f6e155cfe65179e7646bdb825078a9fea39463498c5b8cd99d409e7a |
Payload | ebf6ca39894fc7d0e634bd6747131efbbd0d736e65e68dcc940e3294d3c93df4 |
Injected script | 0f99ec8031d482d3cefa979fbd61416558e03a5079f43c2d31aaf4ea20ce28a0 |
Nome da extensão do Chrome | ID de extensão |
Direct Message for Instagram | mdpgppkombninhkfhaggckdmencplhmg |
DM for Instagram | fgaapohcdolaiaijobecfleiohcfhdfb |
Invisible mode for Instagram Direct Message | iibnodnghffmdcebaglfgnfkgemcbchf |
Downloader for Instagram | olkpikmlhoaojbbmmpejnimiglejmboe |
App Phone for Instagram | bhfoemlllidnfefgkeaeocnageepbael |
Stories for Instagram | nilbfjdbacfdodpbdondbbkmoigehodg |
Universal Video Downloader | eikbfklcjampfnmclhjeifbmfkpkfpbn |
Video Downloader for FaceBook™ | pfnmibjifkhhblmdmaocfohebdpfppkf |
Vimeo™ Video Downloader | cgpbghdbejagejmciefmekcklikpoeel |
Zoomer for Instagram and FaceBook | klejifgmmnkgejbhgmpgajemhlnijlib |
VK UnBlock. Works fast. | ceoldlgkhdbnnmojajjgfapagjccblib |
Odnoklassniki UnBlock. Works quickly. | mnafnfdagggclnaggnjajohakfbppaih |
Upload photo to Instagram™ | oknpgmaeedlbdichgaghebhiknmghffa |
Spotify Music Downloader | pcaaejaejpolbbchlmbdjfiggojefllp |
The New York Times News | lmcajpniijhhhpcnhleibgiehhicjlnk |
FORBES | lgjogljbnbfjcaigalbhiagkboajmkkj |
Скачать фото и видео из Instagram | akdbogfpgohikflhccclloneidjkogog |
Nome da extensão de borda | ID de extensão |
Direct Message for Instagram™ | lnocaphbapmclliacmbbggnfnjojbjgf |
Instagram Download Video & Image | bhcpgfhiobcpokfpdahijhnipenkplji |
App Phone for Instagram | dambkkeeabmnhelekdekfmabnckghdih |
Universal Video Downloader | dgjmdlifhbljhmgkjbojeejmeeplapej |
Video Downloader for FaceBook™ | emechknidkghbpiodihlodkhnljplpjm |
Vimeo™ Video Downloader | hajlccgbgjdcjaommiffaphjdndpjcio |
Volume Controller | dljdbmkffjijepjnkonndbdiakjfdcic |
Stories for Instagram | cjmpdadldchjmljhkigoeejegmghaabp |
Upload photo to Instagram™ | jlkfgpiicpnlbmmmpkpdjkkdolgomhmb |
Pretty Kitty, The Cat Pet | njdkgjbjmdceaibhngelkkloceihelle |
Video Downloader for YouTube | phoehhafolaebdpimmbmlofmeibdkckp |
SoundCloud Music Downloader | pccfaccnfkjmdlkollpiaialndbieibj |
Instagram App with Direct Message DM | fbhbpnjkpcdmcgcpfilooccjgemlkinn |
Downloader for Instagram | aemaecahdckfllfldhgimjhdgiaahean |
URL |
abuse-extensions[.]com |
ampliacion[.]xyz |
a.xfreeservice[.]com |
b.xfreeservice[.]com |
c.xfreeservice[.]com |
browser-stat[.]com |
check-stat[.]com |
check4.scamprotection[.]net |
connecting-to-the[.]net |
cornewus[.]com |
downloader-ig[.]com |
exstats[.]com |
ext-feedback[.]com |
extstatistics[.]com |
figures-analysis[.]com |
huffily.mydiaconal[.]com |
jastats[.]com |
jokopinter[.]com |
limbo-urg[.]com |
mydiaconal[.]com |
notification-stat[.]com |
orgun.johnoil[.]com |
outstole.my-sins[.]com |
peta-line[.]com |
root.s-i-z[.]com |
s3.amazonaws[.]com/directcdn/j6dle93f17c30.js |
s3.amazonaws[.]com/wwwjs/ga9anf7c53390.js |
s3.amazonaws[.]com/wwwjs/hc8e0ccd7266c.js |
s3.amazonaws[.]com/protectscript/instagram-downloader.js |
safenewtab[.]com |
script-protection[.]com |
server-status[.]xyz |
serviceimg[.]de |
servscrpt[.]de |
stats.script-protection[.]com |
statslight[.]com |
ulkon.johnoil[.]com |
user-experience[.]space |
user-feedbacks[.]com |
user.ampliacion[.]xyz |
xf.gdprvalidate[.]de/partner/8otb939m/index.php |
FONTE: AVAST