PNG, não TXT: Identificando um Arquivo pelos Bytes de Assinatura
O desafio
Um arquivo chamado notes.txt apareceu numa pasta de downloads, mas um editor de texto mostra só lixo. Abra-o no visualizador hexadecimal, compare os primeiros bytes com as assinaturas de referência e digite o tipo real do arquivo.
O que você vai aprender
- Reconhecer a assinatura PNG de 8 bytes 89 50 4E 47 0D 0A 1A 0A
- Ler os bytes 50 4E 47 como as letras ASCII PNG
- Explicar que um arquivo de texto não tem magic number fixo e por isso não pode corresponder a esse cabeçalho
- Identificar o bloco IHDR que segue todo cabeçalho PNG
- Diferenciar PNG de GIF, PDF e ZIP pelos bytes iniciais
Habilidades testadas
Pré-requisitos
- Familiaridade com leitura de valores de bytes em hexadecimal
- Consciência de que renomear um arquivo não muda seu conteúdo
Como funciona
A extensão de um arquivo é apenas parte do nome e pode ser trocada em um segundo, mas os bytes internos seguem um formato. A maioria dos formatos binários começa com uma assinatura (magic number) fixa que os identifica independente do nome. Um arquivo de texto simples é a exceção: não tem cabeçalho obrigatório, apenas caracteres. Então, se um arquivo .txt começa com uma assinatura binária conhecida, a extensão está errada.
A assinatura PNG tem oito bytes: 89 50 4E 47 0D 0A 1A 0A. Os três bytes do meio, 50 4E 47, são as letras ASCII PNG. Os bytes ao redor formam uma verificação de integridade inteligente: o 89 inicial é um byte não ASCII que quebra se o arquivo for tratado incorretamente como texto, e o final 0D 0A 1A 0A detecta corrupção de fim de linha causada por transferências que bagunçam quebras de linha. Logo após a assinatura vem o bloco IHDR (você pode ver 49 48 44 52 = 'IHDR' nos bytes), que carrega as dimensões da imagem.
A lista de referência compara PNG com outras imagens e documentos. GIF começa com 47 49 46 38 ('GIF8'), PDF começa com 25 50 44 46 ('%PDF'), e ZIP começa com 50 4B 03 04 ('PK'). Nenhum deles corresponde, então a única resposta consistente é PNG.
Erros comuns
- Confiar na extensão .txt. O nome diz que é texto, mas arquivos de texto não têm cabeçalho mágico e este claramente tem.
- Interpretar mal o byte inicial 89. É um byte não imprimível proposital; não deixe que ele esconda o
PNGlegível que vem em seguida. - Confundir PNG com GIF. Ambos são imagens, mas GIF começa com
47 49 46 38, não89 50 4E 47. - Responder 'imagem' de forma genérica. O enunciado pede o tipo específico e a assinatura aponta exatamente para um: PNG.
Como se proteger
Sistemas que aceitam ou armazenam arquivos devem identificá-los pelo conteúdo, nunca pelo nome ou extensão informados.
- Use uma verificação de tipo baseada em conteúdo (libmagic ou equivalente) nos uploads, em vez de confiar na extensão.
- Se você só permite texto, rejeite arquivos cujos primeiros bytes correspondam a qualquer assinatura binária conhecida.
- Ao renderizar conteúdo de usuário, defina o tipo de resposta a partir do tipo real validado, não do informado, para evitar confusão de content-type.
- Coloque em quarentena e revise arquivos cuja extensão e tipo detectado divirjam, já que essa incompatibilidade costuma ser proposital.