Programação Por Equipe DevBras

Capa do artigo: Ataque à GMO no Japão: senha nova não derruba sessão

Ataque à GMO no Japão: senha nova não derruba sessão

Invasão na GMO (Japão): trocar a senha podia não tirar o invasor da conta. Veja a linha do tempo oficial e como revogar sessões e tokens no seu sistema.

A japonesa GMO Internet desligou em 21/10/2026 todos os servidores do Onamae.com Desktop Cloud, um serviço de desktop Windows na nuvem usado para deixar robôs de FX e ferramentas como MT4/MT5 ligados o tempo todo. Alguém instalou um programa malicioso nos servidores dos clientes, levou dados para fora e usou logins de corretoras salvos nessas ferramentas para fazer operações que os donos das contas não fizeram. Depois, pediu dinheiro.

O caso tem um detalhe que interessa a qualquer pessoa que mantém um sistema com login. No 3º aviso, a própria GMO alertou que trocar a senha não bastava: dependendo da corretora, a sessão já aberta pelo invasor continuava valendo por um tempo depois da troca. A seguir: a linha do tempo pelos comunicados oficiais e como fazer o seu sistema derrubar sessões e tokens de verdade, com um exemplo testado.

O que é o Onamae.com Desktop Cloud

É um servidor Windows remoto da marca Onamae.com, da GMO Internet. O cliente instala ali o MT4/MT5 ou um robô de trade, salva o login da corretora e deixa tudo rodando sem depender do próprio computador. Segundo o jornal Nikkei, o serviço soma mais de 200 mil contratos desde o lançamento.

Ou seja: milhares de máquinas, na mesma plataforma, com credenciais de contas que movimentam dinheiro.

Linha do tempo: de 19 a 24 de outubro

As datas abaixo seguem os comunicados da GMO, que usam o horário do Japão (JST, 12 horas à frente de Brasília).

  • 19/10: um cliente entra em contato e a GMO começa a investigar.
  • 20/10: a empresa confirma que um terceiro instalou um programa malicioso no ambiente de servidor de parte dos clientes. Suspende novas contratações e o painel de controle.
  • 21/10, 4h JST (20/10, 16h em Brasília): começa a desligar, em sequência, os servidores de todos os planos. Sai o 1º aviso, que fala em 26.739 servidores com possível impacto e diz que, até ali, não havia vazamento confirmado.
  • A partir de 21/10: clientes relatam operações que não fizeram nas contas de corretoras.
  • 22/10: a GMO procura a polícia e publica o 2º aviso (16h59 JST): troquem as senhas das ferramentas de trade e encerrem as sessões.
  • 23/10, 16h10 JST: o 3º aviso (em japonês) explica que a sessão pode sobreviver à troca de senha e esclarece que 26.739 é o número de servidores que podem ter sido afetados, não o de acessos confirmados.
  • 24/10, 11h50 JST: o 4º aviso confirma falha de segurança no sistema, acesso indevido e saída de dados de clientes, revela o pedido de resgate e anuncia indenização. No mesmo dia sai o comunicado à bolsa de Tóquio, em inglês.
  • 24/10, 15h JST: o 5º aviso repete as orientações e pede antivírus e backup nos computadores dos clientes.

O que está confirmado e o que ainda não se sabe

Pelos comunicados oficiais, estes pontos estão confirmados:

  • Havia um problema de segurança no sistema do serviço, houve acesso indevido ao ambiente e dados de clientes foram levados para fora.
  • A informação em risco é tudo o que estava guardado nos servidores, incluindo os logins de corretoras salvos nas ferramentas de trade. A GMO afirma que não guarda dados de cartão nesses servidores.
  • O atacante pediu dinheiro e ameaçou continuar operando contas em mais de 70 corretoras e empresas de FX, do Japão e de fora, divulgar dados do serviço e dos PCs de clientes conectados a ele, rodar ransomware e expor dados internos da GMO.
  • A GMO não vai pagar e entregou à polícia as mensagens do atacante.
  • Todo cliente atual recebe 5.000 ienes, com ou sem prejuízo. As perdas realizadas em operações que a empresa reconhecer como indevidas serão reembolsadas, descontado o que a corretora devolver. Ganhos que deixaram de acontecer e oscilação de mercado ficam de fora.
  • O sistema antigo não volta. Quem quiser continuar com desktop Windows será levado, só se aceitar, para um serviço alternativo numa infraestrutura separada, com 6 meses grátis. Detalhes por e-mail até 30/10; regras do reembolso até 6/11.

Ainda não foi divulgado como o atacante entrou, quantas contas foram de fato operadas, quanto dinheiro foi perdido nem quem está por trás. O impacto financeiro para a própria GMO também está em aberto: o comunicado à bolsa diz que ele ainda não pode ser calculado. Números de prejuízo ou nomes de grupo que circulam nas redes não têm confirmação oficial.

Por que trocar a senha não tirou o invasor

O 3º aviso diz, em tradução livre: "mesmo depois de trocar a senha, dependendo das especificações do servidor da corretora, a sessão de conexão existente pode continuar ativa por um período, e o terceiro pode continuar negociando". A recomendação é encerrar todas as sessões pelo site da corretora ou pedir isso ao atendimento, e fazer a troca de senha de um aparelho que não seja o usado para operar.

Isso acontece porque, na maioria dos sistemas, a senha só é conferida no login. Depois disso, quem prova a identidade é um cookie de sessão, um token JWT ou uma conexão já autenticada. Se a troca de senha não invalida isso, quem já está dentro continua dentro.

A folha de referência de sessões da OWASP cita a troca de senha entre os eventos que exigem renovar o identificador de sessão e destruir o anterior. Aqui no blog já mostramos como montar um "sair de todos os aparelhos" que revoga a sessão no servidor.

Como derrubar sessões e tokens de verdade

Sessão com versão por usuário

Um jeito simples e barato é guardar no cadastro um número de versão. Toda sessão ou token carrega a versão do momento do login. Trocar a senha (ou clicar em "encerrar todas as sessões") soma 1 nesse número, e qualquer credencial com a versão antiga passa a ser recusada, mesmo com a assinatura válida. O script abaixo, em Python puro, compara isso com a validação que só confere a assinatura:

import hashlib, hmac, secrets

CHAVE = secrets.token_bytes(32)          # chave de assinatura do servidor
# demo: no mundo real a senha fica com hash (bcrypt/argon2), nunca em texto
usuarios = {"ana": {"senha": "senha-antiga", "versao": 1}}

def assinar(dados: str) -> str:
    return hmac.new(CHAVE, dados.encode(), hashlib.sha256).hexdigest()

def login(usuario, senha):
    u = usuarios[usuario]
    if not hmac.compare_digest(u["senha"], senha):
        raise PermissionError("senha errada")
    dados = f"{usuario}:{u['versao']}"
    return f"{dados}:{assinar(dados)}"

def validar_ingenuo(token):
    # confere só a assinatura: o erro comum
    usuario, versao, assinatura = token.split(":")
    return hmac.compare_digest(assinar(f"{usuario}:{versao}"), assinatura)

def validar(token):
    usuario, versao, assinatura = token.split(":")
    if not hmac.compare_digest(assinar(f"{usuario}:{versao}"), assinatura):
        return False
    return int(versao) == usuarios[usuario]["versao"]

def trocar_senha(usuario, nova):
    usuarios[usuario]["senha"] = nova
    usuarios[usuario]["versao"] += 1     # derruba todas as sessões antigas

token_invasor = login("ana", "senha-antiga")
print("antes da troca   | ingenuo:", validar_ingenuo(token_invasor), "| com versao:", validar(token_invasor))
trocar_senha("ana", "senha-nova-longa")
print("depois da troca  | ingenuo:", validar_ingenuo(token_invasor), "| com versao:", validar(token_invasor))
token_dona = login("ana", "senha-nova-longa")
print("login novo da dona | com versao:", validar(token_dona))

Saída real, rodada com Python 3.13:

antes da troca   | ingenuo: True | com versao: True
depois da troca  | ingenuo: True | com versao: False
login novo da dona | com versao: True

A segunda linha resume o incidente. Na validação ingênua, o token roubado continua aceito depois da troca de senha. Com a versão, ele cai na hora, e a dona da conta entra normalmente com a senha nova.

Sessões no Redis: um índice por usuário

Se as sessões ficam no Redis com chaves aleatórias, não dá para achar "todas as sessões da Ana" sem varrer o banco. A saída é manter, junto com cada sessão, um conjunto com os IDs daquela pessoa e apagar tudo de uma vez quando precisar:

SADD sessoes_do_usuario:ana <id-da-sessao>     # no login
SMEMBERS sessoes_do_usuario:ana                  # no incidente: lista os IDs
DEL sess:<id1> sess:<id2> sessoes_do_usuario:ana # e apaga todos

Testamos essa lógica em Python com fakeredis: duas sessões criadas, duas encerradas, e a do "invasor" sumiu. Evite FLUSHDB no meio de um incidente: ele derruba todo mundo e apaga também as provas de quem estava conectado.

JWT: prazo curto, refresh revogável e troca da chave

Um JWT assinado vale até expirar, porque o servidor não consulta nada para aceitá-lo. Por isso o token de acesso deve durar minutos, e o refresh token, guardado no servidor, é o que se revoga. Detalhamos isso em JWT que expira: prazo curto, assinatura conferida e um jeito de revogar. A versão por usuário do exemplo acima também funciona como uma claim dentro do JWT.

Se a suspeita é de vazamento da chave de assinatura, e não da senha de uma pessoa, a resposta é trocar a chave: todos os tokens emitidos com a antiga deixam de valer. Para não derrubar o sistema inteiro, dá para aceitar as duas chaves por um período curto, como mostramos em trocar segredo sem derrubar o sistema. Num incidente confirmado, porém, a chave antiga sai na hora.

OAuth: o endpoint de revogação

Quem emite tokens OAuth deve oferecer o endpoint de revogação da RFC 7009: o cliente envia o token (com token_type_hint opcional) e o servidor o invalida. A RFC diz que, ao revogar um refresh token, o servidor que suporta revogação de tokens de acesso deve invalidar também os tokens de acesso da mesma autorização. A RFC 9700 pede ainda rotação de refresh tokens em clientes públicos (ou vínculo ao remetente).

Credencial em servidor compartilhado é credencial exposta

O atacante não precisou invadir nenhuma corretora: os logins estavam salvos nas ferramentas de trade, nos servidores invadidos. A GMO pediu também a troca das senhas salvas no navegador do servidor e das reaproveitadas em outros serviços.

A lição vale para qualquer VPS, runner de CI ou máquina de equipe. Senha em arquivo de texto, token exportado no .bashrc e login salvo no navegador do servidor vão junto com quem invadir a máquina. Prefira permissão mínima (senha só de leitura quando o robô não precisa operar), cofre de segredos e chaves revogáveis. E quando um segredo vazar, a ordem é sempre a mesma: troque a chave antes de limpar o rastro.

O 2FA, que a GMO também pediu, não derruba uma sessão já roubada, mas impede que a senha vazada abra sessões novas. Entra junto com a revogação, não no lugar dela.

Por que a GMO se recusou a pagar

A justificativa do 4º aviso é direta: pagar não garante que os dados serão apagados nem que deixarão de ser usados. A empresa avisou que o atacante pode divulgar material com informações falsas misturadas e alertou para golpes com cara de "reembolso". No processo de indenização, a GMO diz que só vai pedir a senha somente leitura do MT4/MT5, para conferir o histórico.

A ordem de ação quando o login de alguém vaza

  1. Troque a senha de um aparelho limpo, fora da máquina comprometida.
  2. Encerre todas as sessões e tokens no servidor (versão, índice no Redis, revogação OAuth), e não só no navegador.
  3. Se a chave de assinatura pode ter vazado, troque a chave.
  4. Ative o 2FA e troque toda senha reaproveitada.
  5. Confira histórico e logs de acesso, guardando as provas.
  6. Comunique pelos canais oficiais e avise sobre golpes.
Siga a DevBras no Instagram e no YouTube (@devbrasoficial).

Avalie este artigo