
Técnicas de exploração do ChakraCore
CVE-2016-7190 [0] é um estouro de heap na função Array.map() do ChakraCore que permite sobrescrever memória adjacente. A ideia principal para obter acesso arbitrário de leitura/escrita é primeiro alocar uma série de arrays de inteiros JavaScript consecutivos e explorar o estouro para manipular o tamanho de um array. Em seguida, utilizamos esse array para alterar o endereço base de um Uint8Array para qualquer endereço que desejamos ler/escrever. A razão para esta etapa extra é que o estouro é limitado a 2x o tamanho do array de inteiros estourado.
Esta vulnerabilidade é muito adequada para testar diferentes estratégias de exploração porque pode ser facilmente reintroduzida em versões atuais do ChakraCore (veja undo-cve-2016-7190.patch).
Neste exemplo, sequestramos o fluxo de controle sobrescrevendo o ponteiro vtable de um objeto C++ Uint8Array para um endereço de memória controlado e invocando uma função dos objetos Uint8Array que resulta na invocação de uma função virtual.
Integridade do Fluxo de Controle (CFI) é uma técnica de defesa para mitigar ataques de sequestro de fluxo de controle. A ideia geral do CFI é calcular um grafo de fluxo de controle (CFG) de uma aplicação durante o tempo de compilação e, em seguida, instrumentar a aplicação com verificações em tempo de execução para garantir que o fluxo de controle não se desvie do CFG estaticamente calculado durante a execução. No entanto, se uma aplicação, como um navegador web, suporta geração dinâmica de código, o CFG deve ser extensível durante o tempo de execução. Isso impõe uma série de desafios:
Durante o período em que conduzimos nossa pesquisa, focamos no último desafio. A ideia principal é manipular a entrada (dados) do compilador just-in-time (JIT). Como resultado, o compilador JIT geraria código malicioso que seria então integrado ao contexto atual—e até mesmo endurecido com CFI. Concorrentemente à nossa pesquisa, a theori [4] mostrou como contornar o CFI manipulando a saída do compilador JIT. Esse ataque é mitigado verificando a integridade da saída por meio de uma soma de verificação. Isso não pode impedir nosso ataque porque manipulamos a entrada do compilador JIT. NO ENTANTO, ao terceirizar a compilação JIT para outro processo (também conhecido como Arbitrary Code Guard [3]), ambos os ataques são mitigados.
Demonstramos que um atacante pode explorar um ataque somente a dados contra o compilador JIT para gerar código nativo arbitrário. Em particular, modificamos a representação intermediária (IR) do compilador JIT para injetar instruções controladas pelo atacante. Quando o compilador JIT então gera o código nativo com base no IR modificado, ele gerará código nativo controlado pelo atacante.
Entre o momento em que a pesquisa foi originalmente conduzida e agora, o IR do ChakraCore foi alterado. Não fizemos o esforço de portar o ataque, portanto, para brincar com este ataque, use os seguintes binários.
Durante a análise do ACG [3] notamos, entre outros [1,2], que os dados globais somente leitura, armazenados na seção .mrdata, devem ser ajustados para integrar o código gerado dinamicamente. Isso é feito através da função LdrProtectMrdata() que usa um bloqueio para torná-la thread-safe. No entanto, a seção .mrdata é primeiro remapeada como gravável antes que o bloqueio seja adquirido. Curiosamente, a seção .mrdata contém o endereço base e o tamanho da seção .mrdata que é posteriormente usado para remapear esta seção novamente como somente leitura.
Um atacante pode explorar isso para criar uma primitiva de ataque que permite remapear memória somente leitura como gravável. Portanto, o atacante executa os seguintes passos:
A consequência deste ataque é que dados anteriormente confiáveis, ou seja, dados mapeados como somente leitura, tornam-se não confiáveis. Em nossa prova de conceito, exploramos essa primitiva para contornar o Control-flow Guard (CFGuard) alterando o ponteiro para a função de verificação do CFGuard que está salva em _guard_dispatch_icall_fptr. O efeito pode ser observado anexando o depurador e alterando a variável bypass_cfguard.
[0] https://bugs.chromium.org/p/project-zero/issues/detail?id=923
[1] http://alex-ionescu.com/publications/euskalhack/euskalhack2017-cfg.pdf
[2] https://sites.google.com/site/bingsunsec/dataonlyattack
[3] https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/
[4] http://theori.io/research/chakra-jit-cfg-bypass