CVE-2018-3975
An exploitable uninitialized variable vulnerability exists in the RTF-parsing functionality of Atlantis Word Processor. A specially crafted RTF file can leverage an uninitialized stack address, resulting in an out-of-bounds write, which in turn could lead to code execution.
Atlantis Word Processor 3.2.6
https://www.atlantiswordprocessor.com/
7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-457: Use of Uninitialized Variable
Atlantis is a traditional word processor containing quite a few features. Atlantis supports a large variety of document formats, as well as quite a few different graphics formats to complement the text in a document. Many of the capabilities of Atlantis are designed to be more efficient for the user.
One file format that is parsed by Atlantis is rich text format (RTF). RTF has a series of tokens that are parsed via a large switch statement as the parser comes across them. For example, the beginning of this parsing function looks like:
sub_54b4e0+0x12:
token_index = (unsigned __int16)token_index;
switch ( (unsigned __int16)token_index )
{
case 0u:
*(_DWORD *)(*(_DWORD *)(document_obj - 264) + 1464) = 3;
goto continue_parsing;
case 1u:
*(_DWORD *)(*(_DWORD *)(document_obj - 264) + 1464) = 0;
goto continue_parsing;
case 3u:
*(_DWORD *)(*(_DWORD *)(document_obj - 264) + 1468) = 4;
goto continue_parsing
...
Some switch cases are simply setting flags in the overarching document object, while others took parameters and call further functions for parsing. Each index in this switch statement is referenced to a global list of tokens available in Atlantis.
...
CODE:00430918 aCell db 'cell',0
CODE:00430920 aCellx db 'cellx',0
CODE:00430928 aCf db 'cf',0
CODE:0043092C aCharscalex db 'charscalex',0
CODE:00430938 aChcbpat db 'chcbpat',0
CODE:00430940 aChcfpat db 'chcfpat',0
CODE:00430948 aChftn db 'chftn',0
CODE:00430950 aChftnsep db 'chftnsep',0
CODE:0043095C aChftnsepc db 'chftnsepc',0
CODE:00430968 aChshdng db 'chshdng',0
CODE:00430970 aClbrdrb db 'clbrdrb',0
CODE:00430978 aClbrdrl db 'clbrdrl',0
CODE:00430980 aClbrdrr db 'clbrdrr',0
CODE:00430988 aClbrdrt db 'clbrdrt',0
...
RTF format allows for embedded OLE objects. These objects rely on a few tokens specific for OLE and are used to set a variety of options in the OLE.
CODE:00431014 aObjautlink db 'objautlink',0 ; DATA XREF: DATA:00664F9C↓o
CODE:0043103C aObjemb db 'objemb',0 ; DATA XREF: DATA:00664FAC↓o
CODE:00431044 aObjh db 'objh',0 ; DATA XREF: DATA:00664FB0↓o
CODE:0043104C aObjhtml db 'objhtml',0 ; DATA XREF: DATA:00664FB4↓o
CODE:00431054 aObjlink db 'objlink',0 ; DATA XREF: DATA:00664FB8↓o
CODE:00431064 aObjocx db 'objocx',0 ; DATA XREF: DATA:00664FC0↓o
CODE:0043107C aObjw db 'objw',0 ; DATA XREF: DATA:00664FCC↓o
In particular, these tokens have the following switch cases:
sub_53b4e0:
case 0x0ffu:
*(_BYTE *)(*(_DWORD *)(document_obj - 0x8E0) + 44) = 3;
goto continue_parsing;
case 0x104u:
*(_BYTE *)(*(_DWORD *)(document_obj - 0x8E0) + 44) = 1;
goto continue_parsing;
case 0x105u:
*(_DWORD *)(*(_DWORD *)(document_obj - 0x8E0) + 12) = sub_43192C();
goto continue_parsing;
case 0x106u:
*(_BYTE *)(*(_DWORD *)(document_obj - 0x8E0) + 44) = 4;
goto continue_parsing;
case 0x107u:
*(_BYTE *)(*(_DWORD *)(document_obj - 0x8E0) + 44) = 2;
goto continue_parsing;
case 0x109u:
*(_BYTE *)(*(_DWORD *)(document_obj - 0x8E0) + 44) = 5;
goto continue_parsing;
case 0x10Cu:
*(_DWORD *)(*(_DWORD *)(document_obj - 0x8E0) + 8) = sub_43192C();
goto continue_parsing;
These cases rely on the document_obj
having a valid OLE pointer at offset - 0x8e0
in order to set the correct value. This document_obj
passed to the RTF-parsing function comes from a stack variable:
CODE:0058EA29 push ebp
CODE:0058EA2A push offset loc_58EA59
CODE:0058EA2F push dword ptr fs:[eax]
CODE:0058EA32 mov fs:[eax], esp
CODE:0058EA35 push ebp
CODE:0058EA36 xor eax, eax
CODE:0058EA38 call sub_588f94 ; stack variable passed to the
This stack variable is directly passed forward to the RTF-parsing function:
CODE:005894BE mov edx, eax
CODE:005894C0 mov eax, [ebp+document_obj]
CODE:005894C3 lea ecx, [eax-5Ch]
CODE:005894C6 mov eax, [ebp+document_obj]
CODE:005894C9 add eax, 0FFFFF708h
CODE:005894CE call rtf_parser_54B4E0
The assumption at this point is, if any of the Ole token are parsed, a valid OLE document object pointer exists at offset -0x8e0
. The initialization function for the OLE document object is not necessarily called before parsing the OLE tokens. Because of this, the OLE document object pointer (offset -0x8e0
) can be uninitialized. If this stack offset can be controlled by an attacker, then an attacker can write to an arbitrary address, causing an out-of-bounds write condition.
eax=01000000 ebx=00000104 ecx=0019f5fc edx=00000104 esi=0019ed60 edi=0019fdcc
eip=00587151 esp=0019ead8 ebp=0019eb10 iopl=0 nv up ei ng nz ac po cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210293
image00400000+0x187151:
00587151 c6402c01 mov byte ptr [eax+2Ch],1 ds:002b:0100002c=??
2018-09-10 - Vendor Disclosure
2018-09-11 - Vendor patched via beta version
2018-09-26 - Vendor released
2018-10-01 - Public Disclosure
Discovered by Cory Duplantis and another member of Cisco Talos.