
Prova de Conceito para CVE-2023-21716 Corrupção de Heap no Microsoft Word
Em fevereiro de 2023, a Microsoft corrigiu uma vulnerabilidade crítica no Microsoft Word, identificada como CVE-2023-21716 com pontuação CVSS de 9,8, que poderia permitir que invasores executassem código remoto sem autenticação. Esta vulnerabilidade também afetou o Outlook Preview Pane, o que significa que pode ser acionada apenas visualizando o arquivo. Embora a Microsoft tenha lançado um patch e uma solução alternativa, eles não divulgaram detalhes sobre o problema. Em 6 de março, o pesquisador que descobriu o bug (Joshua J.Drake - @jduck) compartilhou uma prova de conceito (PoC) no Twitter.
CVE-2023-21716 decorre de como o Microsoft Word lida com arquivos Rich Text Format (RTF), particularmente a palavra de controle \fonttbl, que define fontes no documento usando o formato \f. O \fonttbl dentro da wwlib.dll recebe uma certa quantidade de espaço alocado dentro do Heap (Isso porque as alocações de heap são tipicamente usadas para dados dinâmicos, como a análise de estruturas grandes como uma tabela de fontes, onde o tamanho pode variar dependendo da entrada). A falha ocorre devido a um estouro de buffer quando o número de fontes excede o limite (comprovado pelo PoC como sendo 32760). Exceder o espaço alocado no heap leva à sobrescrita do Ponteiro de Retorno de Instrução (RIP), o que causa a falha do aplicativo.
Os usuários são fortemente encorajados a instalar as atualizações de segurança mais recentes da Microsoft, pois elas resolveram este problema. Para aqueles que não podem atualizar, a Microsoft também forneceu várias soluções alternativas, que podem ser encontradas aqui: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-21716.
Usando o WinDbg, podemos analisar mais de perto para entender a causa da falha. Aqui está o processo:
O WinDbg será interrompido automaticamente quando a falha ocorrer, permitindo-nos analisá-la mais a fundo. Para começar, podemos digitar 'k' para visualizar a pilha de chamadas:
0:000> k
# ChildEBP RetAddr
00 012f5134 77a5feb5 ntdll!RtlReportCriticalFailure+0x4b
01 012f5170 77a5dda9 ntdll!RtlpReportHeapFailure+0x2f
02 012f5170 77a66220 ntdll!RtlpHpHeapHandleError+0x89
03 012f5188 77a5dab7 ntdll!RtlpLogHeapFailure+0x43
04 012f51ec 779b400d ntdll!RtlpAnalyzeHeapFailure+0x281
05 012f5348 779f806d ntdll!RtlpFreeHeap+0x24d
06 012f53a4 779b3d66 ntdll!RtlpFreeHeapInternal+0x783
07 012f53c4 6ea4aa24 ntdll!RtlFreeHeap+0x46 //As funções mostradas em ntdll estão relacionadas ao tratamento de erros da corrupção do heap
08 012f53d8 6ea4a9cb mso20win32client!Ordinal1068+0xab
09 012f53e8 6ea4a995 mso20win32client!Ordinal1068+0x52
0a 012f53f4 6cccda52 mso20win32client!Ordinal1068+0x1c
0b 012f5410 03657fea mso!Ordinal1387+0x24
0c 012f5424 03990115 wwlib!PTLS7::FsUpdateFinitePage+0x7e26f //wwlib é responsável pelo tratamento da tabela de fontes
0d 012f5670 034ea593 wwlib!PTLS7::LsDestroyContext+0x245f90
0e 012f6f5c 033a68ef wwlib!PTLS7::FsUpdateBottomlessPage+0x17494
0f 012f7484 035054ed wwlib!PTLS7::LsAssert+0x2bd1c
10 012f888c 03503d3b wwlib!PTLS7::FsUpdateBottomlessPage+0x323ee
11 012f8910 0400be52 wwlib!PTLS7::FsUpdateBottomlessPage+0x30c3c
12 012f9e9c 0390013a wwlib!wdGetApplicationObject+0xdf8a0
13 012faf48 03ebf20e wwlib!PTLS7::LsDestroyContext+0x1b5fb5
14 012faf90 0410ab2a wwlib!DllCanUnloadNow+0xcc314
15 012fcfe0 03752fb4 wwlib!wdGetApplicationObject+0x1de578
16 012ff538 03385b93 wwlib!PTLS7::LsDestroyContext+0x8e2f
17 012ff578 75e6173b wwlib!PTLS7::LsAssert+0xafc0
18 012ff5a4 75e57eaa USER32!_InternalCallWinProc+0x2b
19 012ff68c 75e57666 USER32!UserCallWinProcCheckWow+0x33a
1a 012ff6c4 75e55e8b USER32!CallWindowProcAorW+0x7f
1b 012ff6dc 7500ae9d USER32!CallWindowProcW+0x1b
.....
.....
Nossas duas principais bibliotecas são wwlib.dll, uma biblioteca principal do Word que gerencia o conteúdo do documento, como fontes, texto e layout, e ntdll.dll, que lida com tarefas de baixo nível do sistema, como gerenciamento de memória e tratamento de erros. A falha ocorre quando o Word processa um grande número de fontes do arquivo RTF. À medida que ntdll.dll detecta que o Word está tentando acessar ou liberar memória inválida (provavelmente corrompida devido ao excesso de fontes), gera um erro de corrupção de heap, levando à falha.
Para aprofundar, podemos definir um breakpoint na última parte da biblioteca wwlib para ver como nossas fontes estão sendo carregadas na memória e entender o que desencadeou o problema:
bc * //excluir todos os outros breakpoints
bp wwlib!PTLS7::FsUpdateFinitePage+0x7e26f //criar o breakpoint
Agora obtemos uma violação de acesso:
(ba4.1a14): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=004f1ce4 ebx=00000001 ecx=000004e4 edx=ffff7ffc esi=13474fe8 edi=00008002
eip=02b300d5 esp=004f1c3c ebp=004f1c48 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210206
wwlib!PTLS7::FsUpdateFinitePage+0x7635a:
02b300d5 66894c5604 mov word ptr [esi+edx*2+4],cx ds:002b:13464fe4=???? //A quebra está acontecendo aqui
Como paramos o programa antes, no ponto em que wwlib.dll está tentando acessar ou modificar memória inválida (em FsUpdateFinitePage), isso nos permite ver a violação de acesso inicial (que causa a corrupção de memória), dando a chance de inspecionar o que deu errado antes que o erro de corrupção de heap seja detectado por ntdll.dll.
Para ser mais preciso, o programa parou devido a uma violação de acesso (código c0000005) na instrução mov word ptr [esi+edx2+4],cx dentro da função wwlib!PTLS7::FsUpdateFinitePage+0x7635a. Este erro indica que o Word tentou acessar um local de memória inválido, especificamente ao tentar armazenar um valor (cx) na memória no local esi+edx2+4.
Se olharmos mais para o registrador ESI, podemos ver que ele contém os dados da fonte:
Cada valor de 16 bits (dois bytes) no formato little-endian representa uma entrada de fonte no formato \fA;
O último valor representado dentro de ESI é f8 7f, que corresponde a {\f32760A;} antes de chegarmos ao final (simbolizado por 29-00)

Agora que a tabela de fontes está carregada no local de memória apontado pelo registrador ESI, com um número tão grande de fontes sendo processado, o local de memória calculado (esi + edx*2 + 4) provavelmente excede a memória alocada para a tabela de fontes. Isso resulta em uma escrita fora dos limites, causando um erro de violação de acesso. A violação de acesso é detectada por ntdll.dll, que lida com o gerenciamento de memória e relatórios de erro. Como resultado, ntdll.dll invoca funções que detectam corrupção de heap, causando, em última instância, a falha do aplicativo.