Today, we released MS08-065 to fix an issue in MSMQ. You’ll notice that the bulletin was rated “Important” and indicates that remote code execution is possible. However, we would like to show you that in practice the severity of the fixed issue is limited only to information disclosure.
If the MSMQ service were installed by default on any affected Windows configuration, we would have rated this one Critical. The “off-by-default” mitigation drops the rating one notch from Critical to Important. We would like to help you understand the information disclosure threat by revealing some details about the vulnerability. Quick stepping through the pseudo-code representing this issue will give you a sense of whether or not this issue will be exploited in the real-world.
WCHAR *
SomeRpcFunction (int ptr)
{
...
WCHAR *buf = ((blah *) ptr)->SomeString;
DWORD size = sizeof(WCHAR) * (wcslen(buf) + 1)
... do some sanity checking ...
WCHAR *buf2 = allocatememory(size);
wcscpy(buf2, buf);
...
return buf2;
}
The attacker can pass in any address he wants for “ptr” and the function will happily try to dereference it. If the attacker does this correctly, there will be some information leakage through the string returned by the function. For code execution, the attacker has a much tougher job. It will have to be a timing attack. The attacker will need to modify memory (using a separate thread) during the window of time between the string length calculation and the wscpy(). The memory modification would have to make the length of the string bigger than it was when the length of the string was calculated several lines of code earlier. In real world scenarios, we expect that exploiting this race condition in a reliable manner would be very difficult. We can also look at it from an assembly perspective to see the window of attack, measured in assembly instructions:
6b96ac16 8b780c mov edi,dword ptr [eax+0Ch]
6b96ac19 897de4 mov dword ptr [ebp-1Ch],edi
6b96ac1c 57 push edi
“edi” is a pointer to a string
6b96ac1d ff15c0f4996b call dword ptr [mqqm!_impwcslen (6b99f4c0)]
We pass it to wsclen(). The calculated string length will be in “eax”)
6b96ac23 59 pop ecx
6b96ac24 8d440002 lea eax,[eax+eax+2]
Note the compiler optimization on “eax”;this instruction is the same as eax = 2*(eax+1). “eax” now represents how many bytes we need to store the string)
6b96ac28 8945e0 mov dword ptr [ebp-20h],eax
6b96ac2b 3d00000400 cmp eax,40000h
6b96ac30 7615 jbe mqqm!QMGetRemoteQueueName+0x73 (6b96ac47)
do some error checking
6b96ac32 a1dc1b9b6b mov eax,dword ptr [mqqm!s_FN (6b9b1bdc)]
6b96ac37 8945cc mov dword ptr [ebp-34h],eax
6b96ac3a 6899000000 push 99h
6b96ac3f 50 push eax
6b96ac40 be06000ec0 mov esi,0C00E0006h
6b96ac45 eb52 jmp mqqm!QMGetRemoteQueueName+0xc5 (6b96ac99)
6b96ac47 50 push eax
“eax” is how many bytes we needed (see 0x6b96ac24)
6b96ac48 e88879ffff call mqqm!MIDL_user_allocate (6b9625d5)
We allocate a buffer of size “eax”
6b96ac4d 8bf0 mov esi,eax
Save the ptr in “esi”
6b96ac4f 8975dc mov dword ptr [ebp-24h],esi
6b96ac52 57 push edi
“edi” is the pointer to the string we had before. If the attacker managed to change memory content at this pointer, then the length can be greater than what we calculated before…
6b96ac53 56 push esi
“esi” is our newly allocated buffer
6b96ac54 ff15c8f4996b call dword ptr [mqqm!_impwcscpy (6b99f4c8)]
we do wscpy() on it. If the length of string at “edi” changed, then we have a buffer overflow
- SVRD Bloggers
*Postings are provided “AS IS” with no warranties, and confers no rights.*