Skip to main content
MSRC

MS10-048 an explanation of the Defense in Depth fixes

Today we released several fixes on MS10-048 affecting the win32k.sys kernel component. The most severe vulnerability allows a local user to perform an authenticated elevation of privileges, with no possible remote vector.

This update also includes several “Defense in Depth” measures that correct potential integer overflows in unrealistic scenarios. In this blog post we are going to walk you through these vulnerabilities to help explain the technical reasoning behind the DiD rating.

In order to understand these issues we first need to understand the source code involved. The win32k.sys component, among other things, is responsible for handling and forwarding windows messages. Before handling or forwarding them, win32k.sys will validate the messages and their parameters: probing, fetching from user mode, validating sizes, pointers, etc…

While handling a certain type of request, and before forwarding it to the top windows on the desktop, several potential integer overflows can happen that would bypass the before mentioned checks. All these are similar to the one that we will focus on:

case DBT_DEVTYP_PORT:

pPortW = (PDEV_BROADCAST_PORT_W)lParam;

if ((1+wcslen(pPortW->dbcp_name))*sizeof(WCHAR) + FIELD_OFFSET(DEV_BROADCAST_PORT_W, dbcp_name) > cbSize) {

MSGERRORCLEANUP(0);

}

break;

An attacker could control the value of pPortW->dbcp_name, which is already probed and captured locally in kernel space.

On 32 bit systems an integer overflow can happen if wcslen() returns more than 2^311. This would require having a 2^321 byte string captured in kernel mode plus the same one in user mode, 2^33 in total. This is not possible on current 32bit systems since with this 32bit range you can only have 2^32 bytes of virtual memory per process shared by user mode and kernel mode

However, that still leaves 64 bit systems. In order to see if this could be exploitable on 64 bit system we will go to the assembly level.

0:000> u fffff97f`ff07474c

fffff97f`ff07474c 488d7b0c lea rdi,[rbx+0Ch]

fffff97f`ff074750 33c0 xor eax,eax

fffff97f`ff074752 4883c9ff or rcx,0FFFFFFFFFFFFFFFFh

fffff97f`ff074756 66f2af repne scas word ptr [rdi] <- inlined wcslen

fffff97f`ff074759 48f7d1 not rcx <- rcx contains the length

fffff97f`ff07475c 488d4c090c lea rcx,[rcx+rcx+0Ch] <- this does not overflow unless you have a really big (length ~ 2^63 )

fffff97f`ff074761 493bcc cmp rcx,r12 <- compare against cbSize…

fffff97f`ff074764 7609 jbe fffff97f`ff07476f

0:000>

The comparison from the above source code is up-casted on 64 bit systems. Again, the attacker needs a really big string in user space (plus the local copy at kernel space). That’s 2^65 bytes of data and is not possible on current 64bit systems either.

So, why are we fixing it? If there is a future recompilation or source change and the comparison is down-casted to 32 bits this could potentially be exploitable on 64 bit systems. Adding that to the fact that we have fixes in the close area makes this a worthy effort.

-Fermin J. Serna, MSRC Engineering

1 These two values are rounded up. Technically the value that must be bypassed is a few bytes less. However, this does not change the overall argument as the size of the string is too large to be allocated on the system.


Related Posts

How satisfied are you with the MSRC Blog?

Rating

Feedback * (required)

Your detailed feedback helps us improve your experience. Please enter between 10 and 2,000 characters.

Thank you for your feedback!

We'll review your input and work on improving the site.