MS13-105 : Oracle Outside In MDB Parsing Vulnerability – CVE-2013-5791

People sometimes ask how to know what exact vulnerability was patched in particular piece of closed source software. In this blog, we would like to describe one such example from the Microsoft security bulletin. In December 2013, Microsoft released MS13-105 [1] to fix vulnerabilities in Microsoft Exchange Server, which uses Oracle Outside In libraries for the WebReady and Data Loss Prevention features. Oracle released patch for this vulnerability in October 2013. [2]

The vulnerability exists within the vsacs.dll library which is used by multiple vendors (Microsoft Exchange, Novell Groupwise, Oracle Fusion Middleware, IBM WebSphere Portal, etc..) and occurs when reading a field (column) name from the Microsoft Access 1.x file. A string from the heap is copied into a fixed size stack buffer without verifying that the destination buffer is large enough to hold the string. This results in a stack-based buffer overflow.

Patch Analysis

CVE: CVE-2013-5791 [3]

Before Patch : vsacs.dll 8.3.7.0.1106281647
After Patch   : vsacs.dll 8.4.1.52.1309170927

One of the interesting(vulnerable) part of the code (Imagebase: 10000000):

10002A4B                 movzx   cx, byte ptr [eax+3875h]
10002A53                 movzx   dx, byte ptr [eax+3874h]
10002A5B                 shl     cx, 8
10002A5F                 add     cx, dx          ; size (user-controlled)
10002A62                 sub     cx, 1Ah         ; size = size - 0x1A (26)
10002A66                 movzx   edx, cx
10002A69                 xor     ebx, ebx
10002A6B                 cmp     dx, bp          ; size must be greater than 0
10002A6E                 jle     short loc_10002A94
10002A70                 movzx   ebp, dx
10002A73                 lea     edi, [esp+78h+var_40] ; destination (stack)
10002A77                 lea     ecx, [eax+3889h] ; source (field name)
10002A7D                 movzx   ebx, bp
10002A80
10002A80 loc_10002A80:                           ; CODE XREF: sub_100028C0+1D2
10002A80                 mov     dl, [ecx]
10002A82                 add     word ptr [esi+24h], 1
10002A87                 mov     [edi], dl       ; <-- Exception, stack-based buffer overflow
10002A89                 add     ecx, 1
10002A8C                 add     edi, 1
10002A8F                 sub     ebp, 1
10002A92                 jnz     short loc_10002A80

After patch (Imagebase: 10000000):

10002E82                 movzx   ax, byte ptr [edx+esi+3875h]
10002E8B                 movzx   cx, byte ptr [edx+esi+3874h]
10002E94                 lea     edi, [edx+esi]
10002E97                 shl     ax, 8
10002E9B                 add     ax, cx          ; size (user-controlled)
10002E9E                 sub     ax, 1Ah         ; size = size - 0x1A (26)
10002EA2                 movzx   ebp, ax
10002EA5                 cmp     bp, 28h         ; <-- added check (maximum size is 0x28 (40))
10002EA9                 jle     short loc_10002EC6
10002EAB                 mov     edx, [esi+4450h]
10002EB1                 mov     eax, [esi+444Ch]
10002EB7                 mov     ecx, [esi+4278h]
10002EBD                 push    edx
10002EBE                 push    eax
10002EBF                 push    9
10002EC1                 call    ecx             ; sccut.UTBailOutEx
10002EC3                 add     esp, 0Ch
10002EC6
10002EC6 loc_10002EC6:                           ; CODE XREF: sub_10002C90+219
10002EC6                 xor     edx, edx
10002EC8                 test    bp, bp          ; size must be greater than 0
10002ECB                 jle     short loc_10002EF4
10002ECD                 movzx   ebp, bp
10002ED0                 lea     ecx, [esp+80h+var_40] ; destination (stack)
10002ED4                 lea     eax, [edi+3889h] ; source (field name)
10002EDA                 movzx   edx, bp
10002EDD                 lea     ecx, [ecx+0]
10002EE0
10002EE0 loc_10002EE0:                           ; CODE XREF: sub_10002C90+262
10002EE0                 mov     bl, [eax]
10002EE2                 add     word ptr [esi+24h], 1
10002EE7                 mov     [ecx], bl
10002EE9                 add     eax, 1
10002EEC                 add     ecx, 1
10002EEF                 sub     ebp, 1
10002EF2                 jnz     short loc_10002EE0

As you can see there was added size check to prevent stack-based buffer overflow.

Windbg Crash Log

(9d8.f58): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0408b8ce ebx=00004127 ecx=040901f3 edx=00004104 esi=0408b580 edi=00290000
eip=62502a87 esp=0028ef2c ebp=0000308b iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00210202
vsacs!VwStreamTell+0xd57:
62502a87 8817            mov     byte ptr [edi],dl          ds:002b:00290000=41

First chance exception was triggered during parsing a PoC file [4] within Oracle Outside In library.

Happy exploiting in 2014!
Alino, alino@citadelo.com

References:
1. https://technet.microsoft.com/en-us/security/bulletin/ms13-105
2. http://www.oracle.com/technetwork/topics/security/cpuoct2013-1899837.html
3. http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-5791
4. http://www.citadelo.com/download/CVE-2013-5791.MDB