Só uma raposa Postado Janeiro 20, 2019 Denunciar Compartilhar Postado Janeiro 20, 2019 (editado) A história (se quiser, pule) Por volta de 2014 e 2015, uma única pessoa havia descoberto por conta própria um dos exploits mais poderosos que já haviam encontrado. O poder dessa brecha era tão imenso que, com um único packet mandado pela rede, era possível preencher toda a memória do servidor até ele gerar um OutOfMemoryError (além de DEVORAR a CPU). Essa mesma pessoa tentou contatar a Mojang diversas vezes, mas o suporte dela não foi o suficiente. A Mojang não deu tanta importância ao caso, como diz ele em seu site: "...A cada 1 mês durante 3 meses, eu pedia updates que corrigissem isso, e fui ignorado ou respondido de forma insatisfatória." Este defeito havia sido primeiramente reportado na 1.6.2 (e funciona em todas as versões anteriores também), mas já havia chegado na 1.8.3, e não havia nenhuma correção satisfatória. A Mojang até tentou fazer uma correção, mas ficou meio bosta e ainda dava pra crashar. Cansado disso, a pessoa que encontrou decidiu expor o problema ao público. Com a informação de como funciona este crasher chegando ao público, a Mojang desenvolveu na 1.8.4 a correção final para isso. Toda a história se encontra neste post dessa mesma pessoa: http://blog.ammaraskar.com/minecraft-vulnerability-advisory/ Como funcionava? O Minecraft se comunica com qualquer servidor por meio da internet, certo? Certo. E para o servidor saber por exemplo em qual bloco você clicou, onde você colocou um bloco, ou quem você atacou, ou que você está tentando conectar (e tudo mais), isso tudo tem que ser passado pela rede da sua casa até chegar ao servidor. E, do servidor até a sua casa, é a mesma coisa. Esses dados passados pela rede são chamados de packets, e é assim que iremos chamar daqui em diante. Packets são identificados por números. Por exemplo, o packet de clicar no chão tem um ID X, e o packet de atacar uma entidade tem o ID Y. Isso serve para o servidor saber qual tipo de dado você está enviando a ele: se é um hit, se é um movimento do seu personagem, se é um clique, e etc. Cada packet envia um ou mais dados que poderá ser lido. Estes dados são, por exemplo, 3 números seguidos que significam coordenada X Y Z de algo, ou um Item que o servidor envia ao seu jogo, ou literalmente qualquer coisa (pois afinal, dá pra enviar qualquer coisa pela rede, se souber como interpretar lá do outro lado). Acontece que, em alguns packets do Minecraft (como os packets de ID 17 e 08 [na 1.7.10]), essa pessoa havia descoberto uma coisa. Para essa explicação, eu vou falar do packet de ID 08, que se refere ao packet "PlayerColocaBloco". Esse packet é mandado do seu jogo pro servidor toda vez que você clica no chão. Mas afinal, qual o problema dele? Na verdade, não é "problema dele". O packet é perfeito. Porém, este packet (e muitos outros como o ID 17) enviam ao servidor toda a informação do item que você está segurando, mesmo não importando pro servidor (sério, ele nem usa as informações do item que você DISSE ter na mão). O defeito todo está na definição de COMO o servidor LÊ ESTE ITEM que o jogador mandou. Um item no inventário, no chão, num baú, na sua mão, onde quer que esteja, é chamado de ItemStack. Vocês sabem: ItemStacks contém um númerozinho que diz a quantidade que tem no stack, o ID do item, e também carregam informações extras sobre eles, como a Lore (que é uma lista de strings), o displayName (que é apenas uma String), e QUALQUER outra informação. Estas informações extras se chamam dados NBT. Dados NBT são nada mais que estruturas de dados (exemplo: listas, conjuntos de números, números em si, etc, coisinha simples), cujo podem ser comprimidos, mandados e lidos pela rede ou pelo disco. Todo tipo de dado do mapa e entidades é salvo em formato NBT, inclusive conteúdo de baús, vida do seu personagem, seu inventário, e tuuuudo mais. Citar Curiosidade: Itens e blocos de mods salvam todos seus dados no composto NBT do bloco/item. No caso de um mod de mochila, todos os itens da mochila são serializados em formato NBT e salvos dentro do ItemStack da mochila. Você, pelo Bukkit/Spigot, consegue por meio de plugin, ler e alterar todos esses dados manualmente, por meio de interação com NMS. Alguns desenvolvedores dizem que é impossível mexer com algumas coisas complexas de mods, mas não é verdade. É possível alterar quase tudo em itens e blocos de mods por meio de plugins. Na hora que seu jogo irá enviar o item que você está segurando, ele envia TUDO do item, inclusive os dados NBT dele. Seu jogo pode enviar tranquilamente estes dados, e o servidor pode ler tranquilamente (se seu jogo não estiver mal-intencionado). Acontece que foi descoberto que o servidor tenta fazer a leitura NBT de forma que permita qualquer pessoa enviar alguma coisa que é complexa demais para o servidor, fazendo crashar de uma só vez. Agora que você sabe o conceito-base do defeito, explicarei um pouquinho sobre os tipos NBT. Existem 11+ tipos de estrutura NBT (dependendo da versão), cujo cada tipo tem seu ID. Abaixo, tem um print do método NBTBase.createTag(). A utilidade deste método pouco importa, mas entenda que existam vários tipos, e que o servidor irá lê-los, não importando qual você envie. Para que você possa entender ainda melhor, eu fiz uma simplificação abaixo só do conceito da NBTTagList, que é nosso alvo de crash mais fácil. A NBTTagList não passa de uma lista que contém uma quantia X de qualquer outro tipo NBT dentro dela. Antes de olhar, entenda o seguinte: Esse código é usado na hora que o servidor irá ler essa NBTTagList. Isso existe dentro do jogo (source: 1.5.2). Perceba que ele lê um int (se você não sabe o que é, entenda que é um número) que meu jogo enviou a ele. Depois, ele usa esse mesmo número para fazer um laço de repetição que repete o número de vezes que foi mandado. Para cada vez que repete, ele cria um novo objeto NBT, e coloca na lista. Agora, imagine a maldade: e se eu mentir dizendo que estou enviando um bilhão de coisas? Ou senão, e se eu enviar milhões de listas dentro de listas, criando uma recursão hiper demorada? O Java além de demorar para processar esse um bilhão de repetições, ele ainda estourará a memória! A ideia-base do exploit é essa. Viu como é simples? E na verdade, não é só o tipo NBTTagList que havia brechas como essa. Haviam brechas no NBTTagCompound, nos NBT Arrays (int/string), e em outros. Então a questão era só explorar a brecha. E posso ser sincero? Defeitos de vulnerabilidade como esses aparecem não só no Minecraft em si, mas também em mods (inclusive já encontrei defeitos de crash em Dragon Block C e Pixelmon, em packets que nem trafegam NBT). Você pode encontrar um exemplo real e menos didático no site da pessoa (http://blog.ammaraskar.com/minecraft-vulnerability-advisory/) De forma resumida (já que está em inglês), vou traduzir o que o autor diz: Citar A vulnerabilidade decorre do fato de que o cliente pode enviar as informações do servidor sobre determinados itens. Isso, juntamente com o agrupamento do formato NBT, permite a gente criar um pacote que é incrivelmente complexo para o servidor desserializar, mas MUITO fácil para nós gerarmos. No meu caso, optei por criar listas dentro de listas, até cinco níveis de profundidade. Esta é uma representação json do que parece. A raiz do objeto, rekt, contém 300 listas. Cada lista tem uma lista com 10 sub-listas, e cada uma dessas sub-listas tem 10 sub-listas, até 5 níveis de recursão. Isso é um total de 10 ^ 5 * 300 = 30.000.000 de listas. Apenas os dados do NBT deste dado são no total 26,6 MB. Mas felizmente o Minecraft implementa uma maneira de comprimir packets grandes, cujo é sorte nossa! Uma compressão zlib reduz os nossos "dados do mal" para apenas 39 KB. Um garoto por aí da internet implementou exatamente da mesma forma e postou um vídeo (em russo) com esse crasher, mas só pra 1.5.2 e 1.6.4: Como esses defeitos podem ser descobertos? Vocês sabem que a Mojang não disponibiliza o código do Minecraft. MAS... A galera do Forge e do MCP traduz todo o código ofuscado do jogo, que permite você ver o código de forma que dê pra entender a source do jogo, mesmo com alguns nomes doidos, como "func_18751_a()". Basicamente é só baixar o Forge da versão mais atual do jogo e ir em busca de ler e entender os packets do Minecraft. Procure entender o Minecraft, ou um tal mod, entender os packets deles (pois mods tem packets próprios, o que é ainda mais legal de procurar defeitos). Procure ser curioso no que faz. De vez em quando você tropeça em um bug aqui ou ali. Na minha opinião, a equipe da Mojang agora está super grande e eu acredito que exploits desse nível não aparecerá denovo no Vanilla. Ainda funciona? Em resumo, nas versões 1.8.4 e acima disso, não. Em servidores Forge 1.7.10 isso já está corrigido (esses caras do Forge são f#da), mas no Vanilla 1.7.10 não. MAS... Vocês que são mais velhos neste fórum provavelmente devem se lembrar deste tópico: https://gamersboard.com.br/topic/14595-fix-spigot-nbt-exploit-152-e-17/ Eu observei atentamente essa correção e eu descobri uma coisa: ela corrige o problema de listas dentro de listas, mas ainda havia outro defeito na correção: era possível fazer o servidor instanciar bilhões de NBTTagEnd (veja lá em cima o ID 0) ao mentir pro servidor dizendo que você estaria enviando uma lista contendo bilhões de NBTTagEnd, enviando aproximadamente somente alguns míseros 0.1 KB de rede. Não é necessário fazer a recursão, e sim enviar uma lista "supostamente" contendo bilhões de NBTTagEnd, MAS SEM ENVIAR QUALQUER NBTTagEnd. É estranho de entender, eu sei. Mas funciona. Isso significa que (infelizmente) todos os servidores (vanilla: 1.5.2 até 1.8.3 & forge: 1.5.2 até 1.6.4) que usam essas correções estão todos vulneráveis ainda, mas não usando a forma explicada pelo autor, e sim a forma explicada no parágrafo acima. Enfim, o intuito deste post é didático. Editado Janeiro 20, 2019 por Só uma raposa 4 Link para o comentário Compartilhar em outros sites More sharing options...
FerreiraCosta Postado Janeiro 20, 2019 Denunciar Compartilhar Postado Janeiro 20, 2019 Ótimo post 1 Link para o comentário Compartilhar em outros sites More sharing options...
Levy26 Postado Janeiro 20, 2019 Denunciar Compartilhar Postado Janeiro 20, 2019 Ótimo tópico. Manja muito haha 1 Link para o comentário Compartilhar em outros sites More sharing options...
gaalaxY Postado Abril 22, 2020 Denunciar Compartilhar Postado Abril 22, 2020 Seu tópico foi marcado como Inativo. Para reverter esta ação, entre em contato com a equipe de Moderação. OBS: Essa mensagem é automática. Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados