1

A linha de código enfadonha por trás do primeiro desastre da Internet

Uma vez em cada sete

Há uma linha no verme de 1988 de que gosto mais do que de qualquer exploit. Não é a que abusa do sendmail, nem a que rebenta o buffer do fingerd. É uma condicional pequena, quase aborrecida, em que o programa pergunta a uma máquina se já está infetada e, ouvida a resposta, decide ignorá-la numa de cada sete vezes. Copia-se na mesma. É essa linha que transforma uma experiência num desastre, e quase ninguém lhe dá o espaço que merece quando conta a história.

A razão para existir tem uma esperteza desconfortável. Morris percebeu que um administrador atento podia criar um ficheiro ou um processo falso a fingir que a máquina já tinha o verme, e o verme, bem-educado, ia-se embora. Vacina de borla. Para impedir isso deu ao programa uma teimosia estatística, só que sete era pouco para quem tem milhares de ligações a acontecer por hora. Nas máquinas com muitos vizinhos acumulavam-se cópias, dezenas, cada uma a roer CPU, e o load average subia até o sistema deixar de conseguir fazer fosse o que fosse, incluindo deixar-te entrar para matar os processos. Quando li isto pela primeira vez pensei que era um bug. Hoje acho que foi outra coisa, um erro de modelação de ameaça. Desenhou contra um adversário inteligente e esqueceu-se de calcular o custo de ser bem-sucedido.

Fica a ideia. Volto a ela.

A noite foi a de quarta-feira, 2 de novembro de 1988. Robert Tappan Morris tinha vinte e dois anos, era aluno de pós-graduação em Cornell e lançou o programa a partir de uma máquina do MIT, de propósito, para que ninguém olhasse para Ithaca. A rede onde o soltou não era "a Internet" no sentido que hoje damos à palavra. Era um conjunto de redes universitárias, militares e de investigação, com a espinha dorsal da NSFNET acabada de passar para ligações T1, e a estimativa que ficou para o número de máquinas ligadas é de uns sessenta mil. Dessas, calcula-se que umas seis mil foram infetadas. Sempre desconfiei destes números por serem tão limpos, um décimo certinho de um total arredondado. Ninguém contou nada. Houve gente a fazer contas à pressa, a partir de relatos de sítios que responderam ao telefone, e a conta ficou e passou de artigo em artigo até virar facto. Não digo que esteja errada, digo que tem a precisão de uma anedota.

O programa tinha quatro portas de entrada e vale a pena olhar para cada uma, porque nenhuma é uma façanha de génio. A primeira era o sendmail. Nas instalações BSD da época, o daemon de correio vinha com um modo de depuração ativo que deixava quem estava do outro lado da ligação SMTP indicar, em vez de um destinatário, um comando para ser executado. Alguém, algures, tinha deixado isso ligado na configuração distribuída, provavelmente porque dava jeito durante o desenvolvimento e ninguém voltou lá. Uma porta aberta por conveniência. Já a vi demasiadas vezes para me impressionar, mas em 1988 era a única porta com rótulo de "debug" que dava para executar código remoto numa quantidade assustadora de máquinas.

A segunda era o fingerd, e essa é mais bonita. O daemon lia a linha de pedido com gets() para um buffer de 512 bytes, sem olhar ao tamanho do que entrava. O verme mandava mais do que cabia, o excedente sobrescrevia o endereço de retorno na pilha, e a execução saltava para código que vinha no próprio pedido. Isto só funcionava nos VAX. Nas Sun-3 o ataque não pegava, a pilha tinha outra disposição, o programa limitava-se a falhar à porta, e foi a diversidade de hardware, por acaso, que travou parte do estrago. Guardo esse pormenor com um carinho estranho.

Aproveito para um desvio que não leva a lado nenhum. O gets() está condenado desde sempre. Ainda hoje o linker do GCC cospe um aviso a dizer que a função é perigosa e não deve ser usada, e só saiu do padrão da linguagem em 2011, com o C11. Vinte e três anos depois do verme. Quando alguém me diz que a indústria aprende depressa com os incidentes, penso nisto.

As outras duas portas eram menos técnicas e mais sociais. A primeira era a confiança entre máquinas. O rsh e o rexec, com os ficheiros .rhosts e hosts.equiv, deixavam uma máquina aceitar comandos de outra sem pedir palavra-passe, porque eram "da casa". O verme ia ver com que máquinas a hospedeira tinha relações de confiança e usava-as como rampa. A segunda era a pura adivinhação de passwords. Levava um dicionário interno de umas 432 palavras, tentava também o nome de utilizador, o nome invertido, variações óbvias, e depois varria o dicionário do sistema em /usr/dict/words. Para ir depressa trazia a sua própria implementação do crypt, mais rápida do que a da biblioteca. E aqui há uma ironia que me custa a largar, porque o pai de Morris, também Robert, trabalhava nessa altura no centro de segurança informática da NSA e tinha escrito com Ken Thompson, em 1979, o texto clássico sobre segurança de passwords no Unix, onde se mostrava precisamente que as pessoas escolhem passwords previsíveis. O filho foi aplicar o que o pai tinha documentado. Não sei se isto é um comentário sobre hereditariedade ou sobre a facilidade com que a literatura de segurança é lida por quem a quer usar e ignorada por quem a devia aplicar. Provavelmente ambos, e ainda por cima não são ideias que se excluam.

O mecanismo de propagação era mais engenhoso do que a história resumida deixa perceber. Em vez de enviar logo o programa completo, o verme mandava um pequeno bootstrap em C, coisa de uma centena de linhas segundo as análises, que a máquina alvo compilava com o seu próprio cc. Depois esse pedaço ligava-se de volta à origem e ia buscar o resto, com objetos para VAX e para Sun, e tentava até algum correr. Isto quer dizer que o verme dependia de haver um compilador de C instalado no alvo, o que em 1988, em máquinas universitárias de Unix, era quase garantido, e hoje seria um bloqueio trivial, porque os servidores de produção bem cuidados nem têm compilador. É dos poucos conselhos de higiene que aprendi cedo e nunca larguei.

Depois escondia-se com um zelo que ainda me parece invulgar. Mudava o nome do processo para sh, apagava do disco os ficheiros que tinha acabado de usar depois de os carregar para memória e, de tempos a tempos, fazia fork e matava o pai para o tempo de CPU acumulado não denunciar o processo. Quem fez ps nessa noite viu dezenas de sh a comer ciclos e a fingir normalidade.

Parêntese rápido sobre a palavra "verme". Vem do romance de John Brunner, The Shockwave Rider, de 1975, e do trabalho de Shoch e Hupp na Xerox PARC, uns anos antes de 1988, onde um programa auto-replicante foi pensado para aproveitar máquinas ociosas à noite. Numa das experiências deixaram-no a correr e na manhã seguinte havia máquinas penduradas pelo laboratório inteiro. Escreveram sobre isso em 1982. Ou seja, o resultado de um programa que se multiplica sem um travão decente já estava documentado seis anos antes, num sítio onde toda a gente ia ler. Pronto. Isto não serve para nada no argumento, só me ficou na cabeça.

O que aconteceu a seguir é, para mim, a parte mais instrutiva e a menos contada. Quem trabalhava na Berkeley, no MIT, em Purdue, percebeu pela carga das máquinas que algo estava errado, e depois pelo comportamento, e passou a noite a desmontar o programa à mão. Havia gente a ler assembly de VAX às três da manhã com café frio. O correio eletrónico, que era o meio normal de coordenação, estava entupido pelo próprio verme, e por isso a coordenação fez-se por telefone. Muitos sítios desligaram-se da rede para se proteger, o que é o reflexo certo. Só que desligar-se também cortou o canal por onde chegavam as correções. As equipas de Berkeley e do MIT tinham a explicação do sendmail e uma correção na madrugada seguinte e na manhã de quinta, mas quem se tinha isolado não as recebia. Um amigo de Morris em Harvard, Andy Sudduth, mandou uma mensagem anónima para a lista TCP-IP com instruções de contenção e um pedido de desculpa em nome do autor, e a mensagem chegou horas depois de devia, presa na mesma rede que estava a ser asfixiada. Não é uma grande lição moral, é só a física do problema. A defesa e o ataque partilhavam o mesmo cabo.

Eu próprio já fiz uma versão minúscula disto, para ser honesto. Deixei um endpoint de debug em produção, um /_dbg que devolvia as variáveis de ambiente do processo, esquecido depois de uma tarde de testes. Esteve lá onze dias. Só dei por ele porque vi um pedido nos logs do nginx vindo de um IP na Letónia que não conhecia. Nada aconteceu, graças à sorte e a um firewall que por acaso estava bem. Rodei tudo o que lá estava, claro, mas fiquei umas semanas com uma sensação particular que não sei descrever bem, parecida com a de ter deixado o fogão ligado, só que retrospetiva.

Agora a narrativa que me irrita. Costuma dizer-se que a cibersegurança nasceu em 1988 com o verme de Morris. Detesto a expressão "fim da inocência", que aparece em todos os textos sobre isto, como se antes disso toda a gente andasse a assobiar. Em 1972, o relatório de James Anderson para a Força Aérea americana já descrevia o problema de fundo, o de sistemas partilhados em que não há maneira de confiar no software que se corre. O relatório Ware é de 1970. Thompson deu em 1984 a sua conferência do Turing Award sobre confiar em confiança, sobre como um compilador alterado pode meter uma porta nas traseiras que nenhuma leitura do código-fonte revela. Havia teoria, havia consciência, havia gente a avisar. O que não havia era um episódio com um nome e um custo, que obrigasse alguém a assinar um cheque.

E no entanto, tenho de me contradizer um pouco, porque o episódio fez mesmo diferença. Poucas semanas depois, a DARPA financiou a criação do CERT na Carnegie Mellon, no Software Engineering Institute, e isso é um marco institucional real, o primeiro ponto de contacto formal para incidentes. O curioso é aquilo que o campo construiu primeiro, que foi um número de telefone. Nem uma ferramenta, nem um padrão, nem uma linguagem mais segura. Uma equipa que atendia o telefone quando algo corria mal. Acho isto revelador e um bocado deprimente, e acho que continua verdadeiro. A maior parte da nossa segurança ainda é, por baixo da maquilhagem, uma pessoa acordada às três da manhã com acesso aos sítios certos.

Vale a pena olhar também para a monocultura. O verme só funcionava em BSD, em duas arquiteturas, e atingiu uma fração da rede por isso mesmo, porque outras máquinas corriam outros sistemas e saíram ilesas. É um argumento antigo e desconfortável, o de que a diversidade protege e a uniformidade facilita a vida a quem ataca. Os sistemas de hoje são, por razões económicas muito razoáveis, uma monocultura de contentores, de imagens base, de três ou quatro fornecedores de cloud. Não digo que seja errado. Digo que quando se descobre uma falha numa biblioteca de logging de Java, como em dezembro de 2021, a distância entre a descoberta e o pânico é de horas, e se isso não te lembra 1988 não estás a prestar atenção.

A relação de confiança do rsh, essa também nunca morreu. Mudou de nome. Hoje é a chave da AWS esquecida num .env que foi parar ao repositório, o token de longa duração partilhado entre serviços, a conta de serviço com permissões a mais porque ajustar permissões dava trabalho. O verme usava as relações de confiança de uma máquina para saltar para a seguinte. Os atacantes de hoje usam o mesmo princípio, e sempre que vejo um .env com credenciais num commit antigo penso que, se Morris tivesse um dicionário de 432 palavras e uma tarde livre, nós seríamos o dicionário.

Sobre a intenção. Morris disse sempre que não queria causar dano, que queria saber quão grande era a rede, e que o erro foi o fator de replicação. Pode ser verdade. Não sou juiz e não consigo olhar para dentro da cabeça de um rapaz de vinte e dois anos de há trinta e oito anos. O que sei é que a defesa de "não queria estragar nada" é uma defesa que ouço, com variações, de quem faz scraping agressivo e de quem corre scanners contra servidores que não são seus, e a resposta honesta é que a intenção interessa menos do que a conduta. O tribunal federal de Syracuse, em janeiro de 1990, entendeu qualquer coisa parecida. O júri condenou-o ao abrigo da Computer Fraud and Abuse Act, de 1986, e a discussão jurídica girou à volta de saber se a intenção exigida pela lei se aplicava ao dano ou apenas ao acesso não autorizado. O tribunal de recurso decidiu que bastava a intenção de aceder. A pena foi de três anos de liberdade condicional, quatrocentas horas de serviço comunitário e uma multa de dez mil e cinquenta dólares. Pouco, para quem deixou milhares de máquinas inúteis durante dias, e acho que isso diz mais sobre a época do que sobre o juiz.

Os números do prejuízo, já agora, são um capítulo à parte. O GAO apontou um intervalo de cem mil a dez milhões de dólares. Isso não é uma estimativa, é um encolher de ombros com carimbo oficial. No julgamento falou-se de custos por local entre duzentos e cinquenta e três mil dólares, e é aí que se percebe que ninguém sabia contar. O custo de um incidente de segurança continua a ser, trinta e tal anos depois, uma ficção contabilística que cada parte ajusta ao que lhe convém.

O que Morris fez a seguir é a parte que costuma arrancar um sorriso amargo. Co-fundou a Viaweb com Paul Graham, que foi vendida à Yahoo em 1998 por qualquer coisa como quarenta e nove milhões de dólares em ações, foi mais tarde co-fundador do Y Combinator e acabou professor catedrático no MIT, a mesma casa de onde lançou o verme. Não tenho nada de pessoal contra ele e sei que a história das segundas oportunidades é bonita. Mas o mundo não dá segundas oportunidades com esta generosidade a toda a gente que escreve código que corre fora de controlo, e quem o diz está a falar de classe, de rede de contactos, de cor de pele, sei lá, de coisas que não cabem num artigo sobre um verme.

Dei-me ao trabalho, há uns anos, de ler a análise de Spafford, do relatório técnico de Purdue de dezembro de 1988, e a de Eichin e Rochlis do MIT, "With Microscope and Tweezers". Recomendo as duas, mais a segunda. O tom é de quem passou a noite acordado e tem pressa de contar. Há uma humildade técnica ali que raramente vejo hoje em análises de incidentes, cheias de diagramas e de siglas de frameworks, mas pobres em "isto foi o que vimos e isto foi o que não percebemos".

Volto, então, ao sete. Nunca percebi porque é que ele escolheu sete. Um em dez, um em vinte, qualquer outro valor evitava o desastre, e a explicação mais honesta, e a menos satisfatória, é que não pensou muito nisso. Foi um número que lhe pareceu razoável numa terça à noite. A história da segurança está cheia disto, de decisões pequenas, arbitrárias, tomadas sem testes, que por acaso se ligam a uma rede de sessenta mil máquinas. Se há uma coisa que o verme me ensinou, e não sei se é uma lição ou apenas um tique de quem já foi apanhado, é a desconfiar dos números que não consigo justificar. Os meus também.

Carregando publicação patrocinada...