Um potencial cliente tentou executar código remoto através dos hooks integrados do Git.

Um potencial cliente tentou executar código remoto através dos hooks integrados do Git.

SToFU Systems · Investigação do incidente · 20 de outubro de 2026

Índice

  1. Tudo começou com um pedido de desenvolvimento
  2. Descarga e inspeção dos ficheiros
  3. Como o hook post-checkout do Git podia ser executado
  4. O que faz o descarregador do hook do Git
  5. Havia uma aplicação escondida no arquivo?
  6. O que devolveu o servidor de descarga
  7. Poderia tratar-se de um utilitário legítimo?
  8. Analisar um repositório Git desconhecido
  9. Depois da análise do arquivo
  10. Correspondência e ficheiros de prova

Tudo começou com um pedido de desenvolvimento

A primeira mensagem chegou através do nosso site a 15 de outubro de 2026. O remetente pretendia ajuda para desenvolver uma plataforma de deteção de fraude financeira. O sistema proposto atribuiria pontuações de risco às transações e utilizaria análise comportamental, incluindo ainda, entre outros requisitos, verificação por blockchain e produção de relatórios.

A 19 de outubro, recebemos a ligação para descarregar o arquivo. O e-mail que a acompanhava indicava o ramo conf para a arquitetura e o ramo NDA para o acordo. Repetia o pedido para analisar e assinar o acordo de confidencialidade.

Please review the project materials and review and sign the NDA in the NDA branch.

Seguir essas instruções levaria a pessoa responsável pela análise desde a extração do arquivo até à mudança de ramo no Git. O e-mail apresentava ambas as operações como parte da leitura da documentação. Não mencionava a execução de um programa descarregado.

O e-mail com o arquivo do projeto e as instruções para abrir o ramo NDA. Os dados identificativos estão cobertos com retângulos cinzentos.

O e-mail com o arquivo do projeto e as instruções para abrir o ramo NDA. Os dados identificativos estão cobertos com retângulos cinzentos.

Descarga e inspeção dos ficheiros

A ligação conduzia a uma página normal de partilha de ficheiros do Dropbox. Descarregámos AI-Fraud-Detection_Blockchain.tar.gz para um ambiente de análise isolado e conservámos o arquivo original como referência. O URL de partilha específico não é divulgado aqui.

Listámos o conteúdo do arquivo e lemos diretamente os objetos Git fornecidos. Isto permitiu-nos recuperar os documentos dos três ramos sem extrair um ramo para a árvore de trabalho nem executar o código fornecido. Nas árvores dos ramos, encontrámos 15 ficheiros Markdown e um documento Word.

Ramo Ficheiros O que encontrámos
master 8 ficheiros Markdown Um README, uma visão geral do projeto, requisitos do produto e casos de utilização de negócio. Outros documentos abordavam desempenho, segurança, testes e operações.
conf 7 ficheiros Markdown Orientações para uma proposta de desenvolvimento, arquitetura e integração de blockchain, requisitos de contratos inteligentes, conceção de dados e API, um motor de risco baseado em IA e marcos de entrega.
NDA 1 ficheiro DOCX Um acordo de confidencialidade com um bloco de assinatura e campos de modelo por preencher.

O produto proposto combinava análise de transações, regras de deteção de fraude e pontuações de aprendizagem automática com verificação por blockchain. A combinação de tecnologias sugerida utilizava Node.js e TypeScript com Express, PostgreSQL, bibliotecas Python de aprendizagem automática e Ethereum. O documento de entrega estabelecia seis marcos ao longo de 24 semanas. Encontrámos documentos de planeamento em todas as árvores fornecidas, sem implementação da aplicação, modelo treinado ou código-fonte de contratos inteligentes para analisar.

Alguns detalhes mereciam uma segunda análise. Os exemplos de API continham as cadeias literais <built-in function id> e <built-in function hash> nos caminhos dos endpoints. O acordo de confidencialidade ainda continha campos de modelo por preencher. Estas incoerências levantavam questões sobre o cuidado com que o material tinha sido preparado.

O ficheiro executável .git/hooks/post-checkout foi uma descoberta mais grave. Os seus comentários descreviam um utilitário de atualização de navegador ou extensão, sem ligação aparente à análise deste projeto. A leitura do script revelou instruções para descarregar um programa externo e iniciá-lo em segundo plano. O pedido do e-mail para mudar de ramo podia conduzir a pessoa responsável pela análise a esse percurso de execução enquanto tentava ler o acordo de confidencialidade.

Mantivemos o repositório inativo e examinámos o hook como texto. Os metadados relevantes do arquivo e o comportamento do script são apresentados abaixo.

Como o hook post-checkout do Git podia ser executado

O ficheiro AI-Fraud-Detection_Blockchain.tar.gz tem 779 429 bytes. As suas 100 entradas TAR incluem 60 ficheiros regulares. Um diretório .git completo chegou juntamente com os documentos.

O diretório de hooks continha os ficheiros .sample habituais e um executável chamado post-checkout.

AI-Fraud-Detection_Blockchain/.git/hooks/post-checkout

Não tem o sufixo .sample. O seu modo TAR é 0777, que inclui permissões de execução, e o seu tamanho é de 2 774 bytes.

O Git invoca post-checkout depois de atualizar a árvore de trabalho através de operações como checkout ou switch, desde que o ambiente permita a execução do hook. A documentação do Git descreve o acionamento.

Porque importa o diretório .git incluído no arquivo

Um git clone normal não copia os hooks locais do lado do cliente do repositório de origem, como explica o Pro Git. Esta entrega incluía o diretório .git existente dentro de um arquivo, pelo que o hook local veio com ele.

O caminho, o modo e o tamanho do hook lidos diretamente do TAR original. Não utilizámos o diretório recebido como repositório Git.

O caminho, o modo e o tamanho do hook lidos diretamente do TAR original. Não utilizámos o diretório recebido como repositório Git.

Inspecionámos diretamente o contentor e os objetos Git, sem executar checkout ou switch no repositório recebido.

O que faz o descarregador do hook do Git

Os comentários no script de shell descrevem um utilitário de atualização de navegador ou extensão. Não encontrámos nenhum requisito para esse utilitário nos documentos do projeto. O script é texto simples, sem ofuscação.

O limiar de tamanho não utilizado

O script define THRESHOLD como 100 e pede ao Git uma lista dos nomes dos ficheiros alterados. Inicializa TRIGGER a zero.

THRESHOLD=100
FILES=$(git diff --name-only "$OLD_HEAD" "$NEW_HEAD")
TRIGGER=0

Dentro do ciclo, calcula SIZE. Não existe qualquer comparação com THRESHOLD nem atribuição que altere TRIGGER. O bloco de descarga é executado quando TRIGGER é zero.

if [ "$TRIGGER" -eq 0 ]; then

No percurso normal deste script, a condição é verdadeira mesmo quando a lista de ficheiros alterados está vazia. O limiar não restringe a descarga.

Números de linha originais preservados. TRIGGER permanece a zero. THRESHOLD é declarado, mas nunca utilizado numa comparação.

Números de linha originais preservados. TRIGGER permanece a zero. THRESHOLD é declarado, mas nunca utilizado numa comparação.

Descargas separadas para Linux, macOS e Windows

O valor devolvido por uname -s determina o caminho de descarga e o nome do ficheiro local.

Sistema detetado Caminho no servidor Nome do ficheiro local
Linux /api/l run-command.sh
Darwin / macOS /api/m run-command.sh
MINGW, MSYS, CYGWIN, Windows_NT /api/w run-command.cmd
Sistema não reconhecido /api/l run-command.sh

Os URL partilham um único host, aqui substituído por <DOWNLOAD_DOMAIN>. Conservámos o hook sem ocultações em privado. Os ramos condicionais abrangem Linux, macOS e Windows, com uma alternativa Linux para um sistema não reconhecido. Não testámos a execução nesses sistemas.

Descarga do ficheiro e tentativa de execução

O hook guarda o ficheiro em ${TMPDIR:-/tmp} utilizando curl, ou wget se curl não estiver disponível. Não existe qualquer verificação de assinatura ou de hash esperado antes das instruções de execução que se seguem.

chmod +x "$CMD_FILE"
"$CMD_FILE" > /dev/null 2>&1 &

O símbolo & final inicia o comando em segundo plano. Tanto a saída padrão como o erro padrão são redirecionados para /dev/null.

Depois da tentativa de execução, o hook escreve azuku em .git-checker no diretório temporário. Nunca verifica a existência desse marcador antes de voltar a descarregar. Também não espera pelo sucesso do processo em segundo plano antes de escrever o ficheiro. Por isso, o marcador poderia existir após uma tentativa de execução sem sucesso.

As instruções originais de descarga, chmod, execução em segundo plano e escrita do marcador. O programa da segunda fase não está presente neste excerto.

As instruções originais de descarga, chmod, execução em segundo plano e escrita do marcador. O programa da segunda fase não está presente neste excerto.

Um comentário perto do fim indica que se deve remover o diretório temporário de descarga. Não existe nenhum comando de remoção por baixo.

Havia uma aplicação escondida no arquivo?

A descarga pela rede levantou outra questão. Já existiria uma aplicação no arquivo, talvez no histórico do Git ou no acordo de confidencialidade? Examinámos os limites dos contentores e, em seguida, descodificámos todos os objetos Git fornecidos e inspecionámos o conteúdo do DOCX.

Os limites do arquivo

Registámos o SHA-256 do arquivo original antes de inspecionar o seu conteúdo.

6f44ff4e461828dd1fe6ede75ca8d9d4b579c2ac223463629e9a7537b9df5040

A descompressão do gzip como dados produziu um fluxo TAR de 890 880 bytes. O fluxo gzip terminava corretamente, sem bytes não utilizados a seguir. Os últimos 5 120 bytes após a última entrada TAR eram preenchimento com zeros.

Em seguida, examinámos os ficheiros e objetos correspondentes a essas entradas dos contentores.

Verificações guardadas do fim do fluxo gzip e do preenchimento TAR. Não foi executado qualquer código da amostra.

Verificações guardadas do fim do fluxo gzip e do preenchimento TAR. Não foi executado qualquer código da amostra.

Localização do hook no cabeçalho TAR

O cabeçalho da entrada post-checkout começa em 0xCF600, ou 849 408, no TAR descomprimido. Os dados do ficheiro começam em 849 920. Estes deslocamentos referem-se ao fluxo TAR, não ao ficheiro .gz comprimido.

Nesse deslocamento, o cabeçalho começa com o caminho para post-checkout.

TAR / representação hexadecimal

000cf600  41 49 2d 46 72 61 75 64 2d 44 65 74 65 63 74 69  |AI-Fraud-Detecti|
000cf610  6f 6e 5f 42 6c 6f 63 6b 63 68 61 69 6e 2f 2e 67  |on_Blockchain/.g|
000cf620  69 74 2f 68 6f 6f 6b 73 2f 70 6f 73 74 2d 63 68  |it/hooks/post-ch|
000cf630  65 63 6b 6f 75 74 00 00 00 00 00 00 00 00 00 00  |eckout..........|
000cf640  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000cf650  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000cf660  00 00 00 00 30 30 30 30 37 37 37 00 30 30 30 31  |....0000777.0001|
000cf670  37 35 30 00 30 30 30 31 37 35 30 00 30 30 30 30  |750.0001750.0000|
000cf680  30 30 30 35 33 32 36 00 31 35 32 35 32 30 30 34  |0005326.15252004|
000cf690  33 30 37 00 30 32 34 30 37 35 00 20 30 00 00 00  |307.024075. 0...|
000cf6a0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|

Num cabeçalho TAR, mode ocupa os bytes [100:108] e size ocupa [124:136]. Os campos descodificados desta entrada são apresentados depois do dump.

Campo TAR Bytes em bruto / valor
mode b'0000777\x00'
size b'00000005326\x00'
Modo octal 0777
Tamanho decimal 2774 bytes
Soma de verificação armazenada / calculada 10301 / 10301

O tamanho octal corresponde a 2 774 bytes. A soma de verificação armazenada no cabeçalho é 10 301. Recalculá-la com o campo da soma de verificação preenchido com espaços dá o mesmo resultado.

O cabeçalho TAR em bruto do hook e os campos descodificados. O seu nome, permissões e tamanho são visíveis nos bytes do contentor.

O cabeçalho TAR em bruto do hook e os campos descodificados. O seu nome, permissões e tamanho são visíveis nos bytes do contentor.

Também calculámos o hash do hook extraído desta entrada.

854b3b88b06fad9d9ffec36b35be0133b1d502084d4d7cce232eda2b2dd03092

O dump da entrada TAR e o hook anonimizado estão incluídos no artigo. O hash acima identifica o original sem ocultações conservado em privado, não a cópia com ocultações destinada à publicação.

Leitura de objetos Git sem checkout

Existem 24 objetos soltos em .git/objects, cada um armazenado num fluxo zlib. Os dados descomprimidos contêm um cabeçalho Git seguido do corpo do objeto.

<type> <size>\0<body>

Verificámos o comprimento declarado do corpo e calculámos o SHA-1 de toda a sequência descodificada, incluindo o cabeçalho e o byte NUL. O resultado tem de corresponder ao identificador do objeto no nome do ficheiro. Isto verifica a integridade do objeto. Não indica quem o criou.

Para cada objeto, comparámos o comprimento declarado com o comprimento do corpo e verificámos o hash de todos os dados descodificados.

expanded = zlib.decompress(compressed_object)
header, body = expanded.split(b"\0", 1)
kind, declared_size = header.decode("ascii").split()

assert len(body) == int(declared_size)
assert hashlib.sha1(expanded).hexdigest() == object_id

Também verificámos os finais dos fluxos zlib. Os objetos correspondem a 16 blobs, 5 árvores e 3 commits. Percorrer as pontas dos três ramos, os seus commits pais e as suas árvores filhas permite localizar os 24 objetos. Não existem blobs inacessíveis entre os objetos fornecidos.

Git / relações entre commits

master 4bc26f6c18910ca777c8238d2f88f6e725fcdc3f
  tree   feb0feaf7b8e826b085e90dea5399772d7b91f02
  parent (none)

conf   239b9aa2edc8c5e21fddeea5ed0e937496ae013f
  tree   048b51f9673f94354251ce16a78e663c71667a4c
  parent 4bc26f6c18910ca777c8238d2f88f6e725fcdc3f

NDA    a1311875d86bf6f1a6b9f2fee6527abbd1ce647d
  tree   cc020d922090835ea4ac3a3e418d0213d7a2ad94
  parent 239b9aa2edc8c5e21fddeea5ed0e937496ae013f

O inventário completo de objetos inclui os objetos fora da árvore de trabalho atual.

Inventário dos 24 objetos Git

Identificador do objeto Tipo Corpo, em bytes
08e2cda2f440c1792c7c35a3499bfd1ade3e9bad blob 6497
22bb86aacf377c17c7ad0d52c5cefeeb93dfa13e blob 5123
2a7091bdd006a2f98a8c795fd7d2a04c8ee53056 blob 2610
39e13459086f36bc7c933d4e7b5d249a22db24bd blob 3061
3f50e45c67dee5aac77147a5418afe551e8871be blob 2433
476dc872c6def747dcdac549b67a8dc80948b7e1 blob 3191
5a51550933b593eb65da458bbdd579f85c082dab blob 752100
5e53fd0880963e1767ad23fb8612b76e31f04003 blob 2807
60a7cbff83445488fd34b12de1814dc56c956963 blob 2054
74d479352822f5cc1d03552f517cfb5b2d7aa6d3 blob 2281
84e694473554c8a7c01f038a1b6ef8d9355405f7 blob 2033
bb7b5d8bc28c4a6257f7d87a685c61ba16a3789c blob 2425
d83c8e0c416766be34276013944f5b94726e8c8f blob 2776
dfd0f171bca257780eb0d9e22ba2eda1db9d4b68 blob 8402
e3b57e48010fc25fd12e7f5f25e952aca843e537 blob 6316
ed325750862eb6cdc92b216258a00a784312d793 blob 3062
239b9aa2edc8c5e21fddeea5ed0e937496ae013f commit 213
4bc26f6c18910ca777c8238d2f88f6e725fcdc3f commit 165
a1311875d86bf6f1a6b9f2fee6527abbd1ce647d commit 212
048b51f9673f94354251ce16a78e663c71667a4c tree 438
2cb70db8d9317603cb5f0fee0029b66581a7162e tree 104
61874365e5498a30c8b61ef63bbb1d28b4cf4e22 tree 320
cc020d922090835ea4ac3a3e418d0213d7a2ad94 tree 57
feb0feaf7b8e826b085e90dea5399772d7b91f02 tree 104

Comprimento e SHA-1 verificados sobre a codificação Git original de cada objeto. As 24 verificações foram bem-sucedidas.


Seguir o acordo de confidencialidade desde a sua árvore até aos seus bytes

O ramo NDA aponta para uma árvore que contém um ficheiro, Non-Disclosure-Agreement.docx. Uma entrada de árvore Git armazena o modo e o nome do ficheiro como texto, seguidos de um NUL e de 20 bytes em bruto para o identificador do blob. Analisámos a entrada diretamente a partir do corpo da árvore.

Árvore Git / representação hexadecimal

00000000  31 30 30 36 34 34 20 4e 6f 6e 2d 44 69 73 63 6c  |100644 Non-Discl|
00000010  6f 73 75 72 65 2d 41 67 72 65 65 6d 65 6e 74 2e  |osure-Agreement.|
00000020  64 6f 63 78 00 5a 51 55 09 33 b5 93 eb 65 da 45  |docx.ZQU.3...e.E|
00000030  8b bd d5 79 f8 5c 08 2d ab                       |...y.\.-.|

Bytes em bruto da árvore NDA e a referência descodificada ao respetivo blob DOCX.

Bytes em bruto da árvore NDA e a referência descodificada ao respetivo blob DOCX.

Essa entrada faz referência ao seguinte blob.

5a51550933b593eb65da458bbdd579f85c082dab

Após a descompressão zlib, o objeto começa com blob 752100\0. Imediatamente a seguir ao cabeçalho estão os bytes 50 4b 03 04, a assinatura PK de um contentor ZIP.

Blob Git / após a descompressão zlib

00000000  62 6c 6f 62 20 37 35 32 31 30 30 00 50 4b 03 04  |blob 752100.PK..|
00000010  0a 00 00 00 00 00 87 4e e2 40 00 00 00 00 00 00  |.......N.@......|
00000020  00 00 00 00 00 00 09 00 00 00 64 6f 63 50 72 6f  |..........docPro|
00000030  70 73 2f 50 4b 03 04 14 00 00 00 08 00 87 4e e2  |ps/PK.........N.|
00000040  40 a5 76 12 16 69 01 00 00 7b 02 00 00 10 00 00  |@.v..i...{......|
00000050  00 64 6f 63 50 72 6f 70 73 2f 61 70 70 2e 78 6d  |.docProps/app.xm|
00000060  6c 9d 92 c1 4e c3 30 10 44 ef 48 fc 43 94 7b 62  |l...N.0.D.H.C.{b|

Bytes do objeto comprimido, cabeçalho Git descodificado e início do DOCX. O comprimento e o identificador do objeto foram verificados sobre o objeto completo.

Bytes do objeto comprimido, cabeçalho Git descodificado e início do DOCX. O comprimento e o identificador do objeto foram verificados sobre o objeto completo.

O corpo tem 752 100 bytes. O seu SHA-256 corresponde ao DOCX que guardámos separadamente para análise.

9d85170d2c0aa7a9b90dfc3855715a31d971bba7abb563e9efa1153fdc15634f

Estes objetos permitem seguir o caminho do ramo NDA até aos bytes do documento.

Identificação dos 16 blobs

Quinze blobs são descodificados como documentos de projeto Markdown em UTF-8. O blob restante é o DOCX acima. Nenhum começa com um cabeçalho PE, ELF ou Mach-O.

Caminho nas árvores Tamanho, em bytes Tipo / primeiros bytes
04-solution-proposal-guidance.md 2054 Texto UTF-8 · 23 20 44 65 76 65 6c 6f 70 6d 65 6e 74 20 43 6f
06-blockchain-architecture.md 6497 Texto UTF-8 · 23 20 42 6c 6f 63 6b 63 68 61 69 6e 20 41 72 63
07-blockchain-integration-specification.md 2807 Texto UTF-8 · 23 20 42 6c 6f 63 6b 63 68 61 69 6e 20 49 6e 74
08-smart-contract-specification.md 2610 Texto UTF-8 · 23 20 53 6d 61 72 74 20 43 6f 6e 74 72 61 63 74
09-data-and-api-architecture.md 2776 Texto UTF-8 · 23 20 44 61 74 61 20 26 20 41 50 49 20 41 72 63
11-ai-fraud-and-risk-engine.md 3062 Texto UTF-8 · 23 20 41 49 20 46 72 61 75 64 20 44 65 74 65 63
14-deliverables-acceptance-and-milestones.md 6316 Texto UTF-8 · 23 20 44 65 6c 69 76 65 72 61 62 6c 65 73 2c 20
Detailed/03-business-and-use-cases.md 3061 Texto UTF-8 · 23 20 42 75 73 69 6e 65 73 73 20 52 65 71 75 69
Detailed/05-non-functional-requirements.md 2033 Texto UTF-8 · 23 20 4e 6f 6e 2d 46 75 6e 63 74 69 6f 6e 61 6c
Detailed/10-security-and-privacy-requirements.md 2433 Texto UTF-8 · 23 20 53 65 63 75 72 69 74 79 20 26 20 50 72 69
Detailed/12-testing-and-quality-requirements.md 2425 Texto UTF-8 · 23 20 54 65 73 74 69 6e 67 20 26 20 51 75 61 6c
Detailed/13-deployment-monitoring-and-operations.md 2281 Texto UTF-8 · 23 20 44 65 70 6c 6f 79 6d 65 6e 74 2c 20 4d 6f
Intro/01-project-overview.md 8402 Texto UTF-8 · 23 20 50 72 6f 6a 65 63 74 20 4f 76 65 72 76 69
Intro/02-product-requirements.md 3191 Texto UTF-8 · 23 20 50 72 6f 64 75 63 74 20 52 65 71 75 69 72
Non-Disclosure-Agreement.docx 752100 DOCX/ZIP · 50 4b 03 04 0a 00 00 00 00 00 87 4e e2 40 00 00
README.md 5123 Texto UTF-8 · 23 20 41 49 20 46 72 61 75 64 20 44 65 74 65 63

Os 16 blobs fornecidos foram classificados. As árvores contêm documentos do projeto, sem que tenha sido encontrada uma implementação do produto.

Os 16 blobs fornecidos foram classificados. As árvores contêm documentos do projeto, sem que tenha sido encontrada uma implementação do produto.

Lemos os corpos de texto, além de verificar as suas assinaturas. O DOCX era o único blob não textual e precisava de uma inspeção separada do contentor.

Abertura do DOCX como ZIP

O documento contém 25 entradas ZIP, constituídas por 17 partes de ficheiro e 8 diretórios. Lemos cada parte de ficheiro e verificámos o seu CRC.

Parte do DOCX Tamanho, em bytes CRC32
[Content_Types].xml 1482 ec936159
_rels/.rels 737 1f222201
customXml/_rels/item1.xml.rels 296 7a393f74
customXml/item1.xml 400 4ed0e3fe
customXml/itemProps1.xml 327 457b4363
docProps/app.xml 635 161276a5
docProps/core.xml 595 d5626da7
docProps/custom.xml 722 8d44908d
word/_rels/document.xml.rels 1086 22475620
word/_rels/settings.xml.rels 398 e5802c0c
word/document.xml 91835 4df71596
word/fontTable.xml 4234 2796cccd
word/media/image1.png 712863 09063019
word/media/image2.png 10193 3aea21cf
word/settings.xml 4116 34faa9ef
word/styles.xml 30020 b4e9edbd
word/theme/theme1.xml 6329 ed5975e1

Nomes, comprimentos e valores CRC32 das partes do DOCX. Inspecionámos os dados ZIP e XML sem abrir o documento no Office.

Nomes, comprimentos e valores CRC32 das partes do DOCX. Inspecionámos os dados ZIP e XML sem abrir o documento no Office.

Não existe vbaProject.bin nem anexo OLE na lista de partes. Dois ficheiros PNG contêm um logótipo e uma imagem de assinatura. Também inspecionámos as relações XML e encontrámos uma referência a um caminho de modelo de documento de escritório local na máquina do autor do documento. Não resolvemos a referência nem carregámos o modelo.

A imagem da assinatura e os campos de autor do Git não nos dão uma forma fiável de identificar o remetente. Ambos podem ser copiados ou substituídos.

Não encontrámos nenhuma aplicação separada nem implementação do produto no conteúdo fornecido. O hook obtém o programa seguinte através da rede. A nossa inspeção dos contentores não exclui todas as técnicas possíveis de exploração ou esteganografia.

O que devolveu o servidor de descarga

Obtivemos os três URL exatos como dados, sem executar as respostas nem seguir redirecionamentos. A 19 de outubro, entre as 17:29:27 e as 17:29:28 UTC, cada um devolveu HTTP 200. Os três corpos continham a mesma mensagem de 21 bytes.

Permanently suspended

As três observações guardadas dos endpoints. Não fizemos mais pedidos aos URL do descarregador durante a preparação deste artigo.

As três observações guardadas dos endpoints. Não fizemos mais pedidos aos URL do descarregador durante a preparação deste artigo.

Não temos bytes da segunda fase para analisar por engenharia inversa. Também não sabemos o que esses endpoints devolviam anteriormente, a outro visitante ou sob condições de pedido diferentes. A mensagem de suspensão não nos dá uma explicação verificada para o motivo da suspensão do serviço.

O hook tenta descarregar e executar um ficheiro externo. Alegações sobre roubo de palavras-passe, tokens, código-fonte ou carteiras exigiriam provas que não temos.

Poderia tratar-se de um utilitário legítimo?

Um atualizador interno poderia acabar num arquivo por engano. Os hooks do Git, os processos em segundo plano e curl têm utilizações legítimas.

Neste envio, o e-mail pedia-nos explicitamente que visitássemos outro ramo. Fazê-lo podia invocar o descarregador fornecido, embora o motivo indicado para a mudança de ramo fosse ler um acordo. O e-mail não mencionava a execução. Também não encontrámos qualquer ligação entre um atualizador de navegador e o sistema proposto, e a verificação de tamanho do script estava incompleta.

Tratámos o envio como uma tentativa de ataque através da entrega de código e impedimos a execução do hook. Reconsiderar essa avaliação exigiria o código-fonte dos ficheiros descarregados e uma explicação verificável de por que motivo um prestador de serviços precisava de os executar para analisar o acordo de confidencialidade.

Não estabelecemos a identidade do operador. O endereço do remetente, os metadados dos commits e os nomes no documento são insuficientes para atribuir a operação.

Diagrama de análise das etapas de execução descritas pelo hook fornecido.

Diagrama de análise das etapas de execução descritas pelo hook fornecido.

Analisar um repositório Git desconhecido

Um programador que seguisse o e-mail podia chegar ao acionamento da execução enquanto ainda lia informações sobre o projeto. Não era necessário compilar nem iniciar a aplicação proposta.

Se analisar envios de clientes numa máquina com chaves SSH de produção ou tokens da cloud, um script inesperado pode ter acesso a esses recursos. Um ambiente descartável precisa de manter essas credenciais fora do alcance. As sessões do navegador na máquina de análise merecem a mesma consideração.

A análise deve incluir o diretório .git fornecido e qualquer automatização do IDE antes de um engenheiro começar a utilizar os seus comandos habituais. Os scripts de instalação também precisam de escrutínio. Nos registos do host, procuraríamos o Git ou uma shell a descarregar um ficheiro para um diretório temporário e a executá-lo em seguida. Um processo curl, por si só, diz-nos muito menos.

Preservar o e-mail e o arquivo originais permite a uma pessoa que os analise mais tarde verificar o que foi entregue. Os hashes e os eventos do host ajudam a estabelecer o que aconteceu na máquina. A ausência de um marcador não permite estabelecer que um programa nunca foi executado.

Descarregar ou extrair o arquivo pode executar este hook?

A descarga e a extração normais não invocam, por si só, o hook post-checkout do Git. Nesta amostra, o acionamento documentado é a atualização da árvore de trabalho pelo Git através de checkout ou switch, quando a execução de hooks é permitida. Inspecionámos diretamente os objetos fornecidos sem invocar essas operações.

Depois da análise do arquivo

Esperávamos que a troca de mensagens seguinte fosse sobre arquitetura e datas de entrega. Em vez disso, enviámos uma resposta sobre o hook e preservámos o material para análise posterior. Continuamos sem poder dizer o que o programa remoto fazia ou quem o operava. O hook deu-nos razões suficientes para interromper o fluxo de trabalho do Git solicitado.

Há mais de cinco anos que a SToFU Systems e as nossas soluções ajudam empresas a proteger os seus sistemas, incluindo contra ataques distribuídos através de correspondência comercial e materiais de desenvolvimento. As nossas auditorias de segurança examinam de que forma o código e os acessos podem ser utilizados indevidamente. Também disponibilizamos engenharia inversa quando uma equipa precisa de compreender software desconhecido.

Se um repositório ou binário suscitar dúvidas, fale com a nossa equipa sobre uma análise técnica antes de o colocar no seu ambiente de desenvolvimento habitual.

Correspondência e ficheiros de prova

As quatro mensagens abaixo utilizam marcadores de substituição para nomes de pessoas, endereços, identidades de terceiros e ligações identificativas. A restante redação de cada nova mensagem é preservada. As citações repetidas são omitidas porque cada e-mail aparece separadamente. O IP do serviço do formulário web e os endereços de destinatários alheios ao caso também são ocultados.

1. O primeiro pedido através do nosso site

Email / dados identificativos substituídos

Date: Thu, 15 Oct 2026 12:55:21 +0000
From: SToFU Site Form <TEAM_EMAIL>
To: <TEAM_EMAIL>
Subject: SToFU Systems - Contact by <SENDER_NAME> <SENDER_EMAIL>
Reply-To: <SENDER_NAME> <SENDER_EMAIL>

Time: 2026-10-15T12:55:21+00:00
IP: [redacted]
Page: /contact
Name: <SENDER_NAME>
Email: <SENDER_EMAIL>
Attachments: none
Message:
We are currently developing an AI-powered FinTech fraud detection platform designed to help financial organizations identify suspicious transactions, assess potential risks in real time, and strengthen their fraud prevention and investigation processes.
The planned platform will incorporate AI/ML-based fraud detection, transaction risk scoring, behavioral analysis, configurable fraud-detection rules, blockchain-based verification, automated alerts, investigation support, and reporting and analytics.
We are looking to connect with an experienced technology partner with expertise in blockchain, financial technology, AI/ML, and scalable web platform development to help us bring this product to life.
We would welcome the opportunity to discuss your team’s capabilities, experience, and potential role in the project. The specific scope of your team’s involvement, technical responsibilities, and collaboration model can be determined through our discussion, based on your expertise and recommendations.
If this opportunity aligns with your team’s capabilities and interests, I’d be happy to share the project overview and technical roadmap for an initial review.
---

O primeiro pedido através do nosso site. Vista anonimizada para publicação do e-mail preservado.

O primeiro pedido através do nosso site. Vista anonimizada para publicação do e-mail preservado.

SHA-256 do EML privado sem ocultações: bf7d0f3a59b84f509ca436e0750640e844e9731ce363a42a99d5be60cdf8597e


2. A nossa resposta a solicitar os materiais

Email / dados identificativos substituídos

Date: Sat, 17 Oct 2026 19:46:28 -0000
From: <TEAM_MEMBER_NAME> <TEAM_EMAIL>
To: <SENDER_NAME> <SENDER_EMAIL>
Subject: Re: Your AI fraud detection platform
Cc: [redacted: third-party addresses]

Hi <SENDER_NAME>,

Thank you for getting in touch through our website. I'm <TEAM_MEMBER_NAME>, <TEAM_MEMBER_ROLE> of SToFU Systems (<COMPANY_WEBSITE>). You can find me on <PROFESSIONAL_NETWORK> here:
<PROFILE_URL>

Your fraud detection platform sounds like a great project. Helping financial teams spot suspicious transactions and investigate them more effectively is a worthwhile problem to solve, and we'd be very happy to help you bring it to life.

We'd be glad to help with the architecture, development, security, and ongoing maintenance. We'll do everything we can to get the platform launched and keep it running reliably as it grows.

If you plan to seek investment, we can also help prepare the technical side for those conversations, including a working product or demo, clear architecture and documentation, and a practical development roadmap.

Please send over the project overview and technical roadmap you mentioned. It would be helpful to understand what you've already built and what you'd like to tackle first.

I'd be happy to arrange a call to discuss the project and how we could work together. What day and time would suit you? Please include your time zone so we can find a slot that works for both teams.

Thank you again for reaching out, and have a great day!

Best regards,
<TEAM_MEMBER_NAME>
<TEAM_MEMBER_ROLE>
SToFU Systems
<COMPANY_WEBSITE>

A nossa resposta a solicitar os materiais. Vista anonimizada para publicação do e-mail preservado.

A nossa resposta a solicitar os materiais. Vista anonimizada para publicação do e-mail preservado.

SHA-256 do EML privado sem ocultações: 1e5330dd82e02911254722744a3202e9b761c8c1d2950be937cd5d539c1bcad9


3. O e-mail do arquivo que indicava os ramos NDA / conf

Email / dados identificativos substituídos

Date: Mon, 19 Oct 2026 09:03:41 +0000
From: <SENDER_EMAIL>
To: <TEAM_EMAIL>
Subject: Re: Your AI fraud detection platform

Hi <TEAM_MEMBER_NAME>,
Thank you for your interest in our AI-powered FinTech fraud detection platform.
I’ve also reviewed your <PROFESSIONAL_NETWORK> profile, and I’m confident that you and your team can make a valuable contribution to our project.
I’m happy to share the project materials for your review.
We’ve prepared the project overview, technical roadmap, and NDA, which provide the key information needed to understand the project, its objectives, and the proposed technical direction.
The platform focuses on AI-driven fraud detection, transaction risk assessment, behavioral analysis, fraud prevention, blockchain-based verification, automated alerts, investigation support, and financial risk analytics.
This is the Link:
<FILE_SHARE_URL>
Please review the project materials and review and sign the NDA in the NDA branch.
The NDA is required because the project materials contain confidential business, technical, architectural, and product information.
So, please send me the signed NDA as soon as possible.
In particular, we would appreciate your initial technical assessment of the proposed system architecture and timeline. The detailed documentation and specifications related to these areas are available in the conf branch.
After your review, we would like to arrange a meeting to discuss your technical observations, recommendations, questions, development approach, and potential partnership opportunities in more detail.
Once you have completed your review, please let me know your preferred meeting date and time and provide the signed NDA.
Please feel free to take the time you need to review the materials thoroughly. I look forward to receiving your feedback and speaking with you about the project.
Kind regards,
<SENDER_NAME>

O e-mail do arquivo que indicava os ramos NDA / conf. Vista anonimizada para publicação do e-mail preservado.

O e-mail do arquivo que indicava os ramos NDA / conf. Vista anonimizada para publicação do e-mail preservado.

SHA-256 do EML privado sem ocultações: f7007ed3053d3ba2ef71ea01c74ec0c4aebfd48417f757ecec8d9d7d5884bf33


4. A nossa resposta após descobrir o hook

Email / dados identificativos substituídos

Date: Mon, 19 Oct 2026 19:37:58 +0200
From: SToFU Systems <TEAM_EMAIL>
To: <SENDER_NAME> <SENDER_EMAIL>
Subject: Re: Your AI fraud detection platform

Hi <SENDER_NAME>,

We reviewed the materials you sent. Unfortunately, we found no application source code or working implementation, only planning documents and an NDA.

Execution of the supplied Git post-checkout hook was disabled during our review. The hook downloads and runs platform-specific files from <DOWNLOAD_DOMAIN>, hides their output, and writes a local marker. Our security policies do not allow the execution of untrusted third-party hooks.

Thank you for your time and for the elaborate attempt to deliver malicious code.

We have traced the technical delivery chain and preserved the archive, hook, download responses, correspondence, and author names and email addresses recorded in the repository. The relevant evidence will be passed to the competent law enforcement authorities in the applicable jurisdictions.

SToFU Systems

A nossa resposta após descobrir o hook. Vista anonimizada para publicação do e-mail preservado.

A nossa resposta após descobrir o hook. Vista anonimizada para publicação do e-mail preservado.

SHA-256 do EML privado sem ocultações: 31df91adb2eb52be2171836d3e26610328a0a1a1273dbf7d56efe4354bb62e19


Vista anonimizada do hook completo

Os 101 números de linha do código-fonte foram preservados. Os dados identificativos estão cobertos com retângulos cinzentos.

Os 101 números de linha do código-fonte foram preservados. Os dados identificativos estão cobertos com retângulos cinzentos.


Os originais sem ocultações são conservados em privado. Os ficheiros de prova públicos utilizam marcadores de substituição e as capturas de ecrã utilizam retângulos cinzentos opacos. Os hashes identificados como originais correspondem à fonte privada, não a uma cópia editada para publicação. As figuras são capturas de ecrã de vistas locais das provas, com o texto identificativo removido antes da renderização. Não foi executado qualquer código recebido.

SToFU Systems

SToFU Systems

Voltar aos blogs

Contato

Comece a conversa

Algumas linhas claras bastam. Descreva o sistema, a pressão e a decisão que está bloqueada. Ou escreva diretamente para midgard@stofu.io.

0 / 10000
Nenhum arquivo escolhido