
Implementação do exploit CVE-2018-16858
Nesta entrada veremos como utilizar uma falha simples de um programa para conseguir abrir uma porta dos fundos no sistema que utilize esse programa.
A falha em questão é definida no CVE-2018-16858 pertencente à suíte de escritório LibreOffice. Essa falha consegue, em um arquivo especialmente formatado, realizar um escalonamento de diretórios, permitindo a execução de código Python. Essa execução é vinculada ou acionada pela ação do usuário sobre o documento, e é realizada sem que nenhum tipo de aviso seja dado ao usuário pela execução de macros.
O presente documento se divide em cinco partes. Na primeira parte será explicada a falha em si, como desempacotar um OpenDocument, como alterar sua estrutura para que execute o script local desejado, e como recompor o documento novamente para sua execução e teste.
Na segunda parte veremos como utilizar a execução local para lançar qualquer comando no sistema em que o documento for aberto, e geraremos uma porta dos fundos que permita a execução de comandos remotos.
Na terceira parte automatizaremos o processo para gerar documentos que criem portas dos fundos com comunicação direta ou reversa, determinando endereço IP e porta aos quais se deverá conectar.
A quarta parte tratará sobre a integração da falha no sistema metasploit para que, através do msfconsole, seja possível gerar documentos compatíveis com a forma de exploração do metasploit. Com isso, poderão ser escolhidos como código a executar qualquer payload definido na suíte do metasploit.
A quinta e última parte mostrará como integrar em um sistema de antivírus o processo de detecção que permita identificar os arquivos do tipo LibreOffice infectados pelo procedimento anterior. Será utilizado o formato de detecção do antivírus ClamAV, permitindo compreender melhor o processo de detecção que os antivírus possuem e assim facilitar nossa proteção contra ameaças desse tipo.
Todo o processo será realizado para sistemas Linux baseados em Debian, mas o que aqui é explicado pode ser extrapolado para outros sistemas, já que é descrito detalhadamente. Tanto a falha quanto as provas de conceito do CVE original foram realizadas para a versão do LibreOffice para Windows, portanto sempre se pode recorrer a essa fonte para utilizar o descrito neste documento de forma análoga para as versões do Windows.
O LibreOffice (e, por questões genéticas, o Apache OpenOffice) tem uma falha em versões anteriores à sua última versão (6.1.5) que permite a execução de código Python localizado em qualquer lugar do computador sem que o usuário seja avisado pela execução de uma macro.
Para poder ver a falha em questão, podemos gerar um documento novo no editor de textos no qual escreveremos algo, selecionaremos e geraremos um hiperlink. Para criar um hiperlink no texto, é necessário selecionar o menu Insert e dentro dele a opção Hyperlink (também é possível selecionando o texto e depois usando a combinação de teclas Ctrl+K).
Aparecerá o seguinte diálogo:

Para definir um hiperlink, devemos inserir uma URL e clicar em Apply. Além da opção de URL na parte inferior da caixa de diálogo, onde se pode ler Further Settings, disporemos de um botão com o ícone de Play que nos permitirá também vincular eventos a determinadas ações. É aí que definiremos que desejamos executar um código Python como ação.
Ao pressionar esse botão, abrirá um novo diálogo:

Nele poderemos selecionar entre três eventos básicos e o script que se deseja utilizar. Como evento selecionaremos Mouse Over Object e como script, dentro dos scripts da família LibreOffice Macros, selecionaremos Python Samples. Dentro dessa opção existe apenas um script predefinido chamado TableSample, que é o que selecionaremos.
Feito isso, se passarmos o mouse sobre o texto que convertemos em hiperlink, veremos que se abre uma janela com um documento no qual há uma tabela. Isso significa que associamos o evento de passar o mouse sobre o hiperlink ao script em Python. O que pretendemos é substituir essa ação por outra que quisermos.
Para isso, salvaremos o documento que criamos e sairemos do LibreOffice para executar no console uma série de comandos.
O formato de documento ODT nada mais é do que um zip com uma série de arquivos dentro dele (o formato DOCX do Microsoft Office é muito parecido). Por isso, a primeira coisa que faremos é descomprimir o arquivo com um descompactador de arquivos zip.
No nosso caso, utilizaremos a ferramenta de linha de comando chamada unzip. Então, simplesmente executaremos a seguinte instrução:
user@host:~/Documents/prueba$ unzip ~/Documents/blog/exploitlibreoffice/doc/CV.odt
Com isso veremos os arquivos que realmente existem dentro de um arquivo do tipo OpenDocument. Os mais relevantes para nós serão o arquivo mimetypes, o arquivo content.xml e o arquivo styles.xml.
O arquivo mimetype é o primeiro que deve aparecer na lista de arquivos do zip, portanto quando voltarmos a empacotar os arquivos, deveremos forçar com nosso empacotador de arquivos que assim seja, ou o arquivo não será interpretado como um OpenDocument.
O arquivo content.xml contém o texto do documento que escrevemos, no qual temos texto misturado com determinadas tags que indicam em que formato o texto deve ser exibido.
Por exemplo, na seguinte linha:
<text:p text:style-name="_5f_ECV_5f_SectionDetails">Indicar lista de documentos adjuntos a seu CV. Exemplos:</text:p>
Pode-se observar um exemplo de um parágrafo de texto escrito com um estilo concreto definido pelo atributo text:style-name. O parágrafo de texto está entre a tag de abertura text:p e a tag de fechamento </text:p>.
O script associado ao hiperlink que fizemos também pode ser visto de forma bastante simples. Se buscarmos entre o texto de content.xml pela palavra python ou pelo nome do script python que carregamos, no nosso caso TableSample.py, é fácil detectar a linha onde devemos variar o conteúdo:
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|TableSample.py$createTable?language=Python&location=share" xlink:type="simple"/>
Nessa linha se encontra o caminho do script em python que será carregado quando colocarmos o mouse sobre o hiperlink chamado TableSample.py e a função que será executada do código python, neste caso createTable.
O problema inerente ao LibreOffice é que, ao ler os documentos, o valor do código python a ser carregado não é limpo corretamente. O programa não limpa os caracteres ../ do caminho do arquivo, portanto é possível acessar qualquer arquivo do sistema em que o documento de texto for aberto. Além disso, se esse arquivo acessado for um arquivo com código python, poderemos executar qualquer função que esteja definida nesse arquivo.
Como primeiro teste de conceito, faremos com que ao passar o mouse sobre o hiperlink seja executada a calculadora, no nosso caso o programa galculator abre a calculadora. Devemos gerar um programa em python que permita executar um comando dentro de uma função, ao estilo de como o LibreOffice espera a execução. Para isso, geraremos o seguinte código no caminho /tmp/prueba.py:
import os;
def ejecuta():
os.system("galculator");
Com esse pequeno código conseguiremos nosso propósito. Agora só precisamos adicionar tanto o arquivo python /tmp/prueba.py quanto o nome da função ejecuta dentro da chamada que é feita no arquivo odt. Portanto, a linha que fazia a chamada ao python ficaria da seguinte forma: