Microsoft Responds to WMF Vulnerability
beuges writes "In an entry on the Microsoft Security Response Center Blog, Stephen Toulouse explains exactly how the WMF flaw could be triggered. BetaNews has an overview of the company's response." From the BetaNews article: "This code exists on every version of Windows since version 3.0, security firms have said. When this functionality was introduced, Toulouse said the security landscape differed from what it is now and metafile records were completely trusted by the operating system. Gibson claimed that the flaw could be exploited only by using a byte size of 1 in the metafile record, which Toulouse says is incorrect. He surmised that Gibson's tests had the offending function as the last entry in the metafile, which caused only incorrect sizes to trigger the flaw." We've previous reported on the backdoor claim.
That's quite a long time to have a flaw in your OS. Maybe they should focus more on security rather than a fancy new AeroGlass interface.
My journal: Clicky. Read it because it
> metafile records were completely trusted by the operating system
when there were no disgruntled employees and no spies (international or industrial)
everyone used telnet and ftp
and there was no user 0
There are places where the networks are not touching,and there are places where they are-Boeing's Lori Gunter
Windows 3.0?! Ok, if it was a problem back then, why didn't it get fixed when the security environment changed? Windows has too much of a legacy going for it, and I'm surprised they held on to it this long. Apple realized that it's legacy code was no good years ago and succesfully ditched it in favor of something more modern, why can't windows do the same?
Monstar L
An interesting quote from the first link:
With WMF we want to be very clear: the Windows 9x platform is not vulnerable to any "Critical" attack vector. The reason Windows 9x is not vulnerable to a "Critical" attack vector is because an additional step exists in the Win9x platform: When not printing to a printer, applications will simply never process the SetAbortProc record.
Which makes me wonder, why on earth did they remove that security measure in later versions of Windows?
The Tao of math: The numbers you can count are not the real numbers.
Seeing as I didn't get an answer last time (probably posted too late), I'll re-post my response when this was linked to in a comment in a previous article:
Interesting - according to the article, Win95/98/ME don't actually run the hook set via SetAbortProc when rendering a metafile (unless you're printing it and the print job is aborted), but some change was introduced in 2000/XP such that it was called after the next metafile record is processed (which is an *extremely* odd thing for Windows to do, considering what SetAbortProc was designed to do). This seems to fit with what people are reporting (and explains why the Metasploit exploit, which adds leading and trailing records, works).
Maybe Gibson was accidentally on the mark about it being an intentional backdoor. After all, that's about the same time a vulnerable program able to display metafiles was introduced and bundled with Windows (was that in 2000 or XP?).
I think maybe Windows' landscape has changed but security wasn't so passe' to other software makers. I wonder how much arbitrary code could have been executed by UNIX or even Netware in those days? And I leave open the possibility that it could have. In the long run, this was left uncheck and maybe forgotten for what, 12-15 years now? And more importantly, was brought right into the server code from the desktop code.
I think therein lies the fundamental problem with Windows and why SA's warned for years about Microsoft's assbackwards approach to security. Windows is at it's heart a desktop OS and as such has a reverse understanding of security.
I think that their implementation contains exactly the same bug as Windows (as others have pointed out) and that if you take a look at the code you can easily see why (and it's not a backdoor).
/library/en-us/gdi/metafile_1yec.asp)
/library/en-us/gdi/metafile_8j1u.asp) and is the all important header with the following definition:
/library/en-us/gdi/prntspol_0d6b.asp). If you take a look at the implementation in WINE you see the following code (dlls/gdi/printdrv.c):
First the file dlls/gdi/metafile.c contains a function called PlayMetaFileRecord with the following signature:
BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
Which is simply WINE's implementation of the same Win32 API (which is documented here: http://msdn.microsoft.com/library/default.asp?url=
The third parameter (mr) is a METARECORD pointer (a METARECORD is just an entry in the metafile and is detailed here: http://msdn.microsoft.com/library/default.asp?url=
typedef struct tagMETARECORD { DWORD rdSize; WORD rdFunction; WORD rdParm[1]; } METARECORD, *PMETARECORD;
With the rdSize being the size of the record in words, the rdFunction being the function and the rdParm the data (which in the case of an exploit would be executable code). PlayMetaFileRecord handles META_ESCAPE like this:
case META_ESCAPE:
Escape( hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
break;
You'll note that parameter 3 is a pointer into the metafile parameter block, i.e. if executed parameter 3 would execute code in the metafile. Now Escape has implemented like this (dlls/gdi/driver.c):
INT WINAPI Escape( HDC hdc, INT escape, INT in_count, LPCSTR in_data, LPVOID out_data )
and the SETABORTPROC is handled with the following code:
case SETABORTPROC:
return SetAbortProc( hdc, (ABORTPROC)in_data );
So if you have an ESCAPE/SETABORTPROC record in a metafile then under WINE the AbortProc is set to point into the metafile (since in_data is corresponds to &mr->rdParm[2]).
So it's quite clear from the WINE implementation that this is a way to set a pointer into the metafile for execution. All it would take is that the metafile's AbortProc is called and arbitrary code could be executed.
In WINE at least this looks nothing like an intentional backdoor. It looks more like a bug caused by the fact that Escape is rather powerful and can set a pointer to code.
Now it's possible in WINE (I believe) to force the AbortProc to execute with another ESCAPE record that has NEWFRAME as the function. Again looking at the Escape code you'll see that NEWFRAME has handled like this:
case NEWFRAME:
return EndPage( hdc );
EndPage is a standard GDI function (see here for documentation: http://msdn.microsoft.com/library/default.asp?url=
INT WINAPI EndPage(HDC hdc)
{
ABORTPROC abort_proc;
INT ret = 0;
DC *dc = DC_GetDCPtr( hdc );
if(!dc) return SP_ERROR;
if (dc->funcs->pEndPage) ret = dc->funcs->pEndPage( dc->physDev );
abort_proc = dc->pAbortProc;
GDI_ReleaseObj( hdc );
if (abort_proc && !abort_proc( hdc, 0 ))
{
EndDoc( hdc );
ret = 0;
}
return ret;
}
Note that this function always called the Abo
Ok, i've been reading about this for much too long. It seems that there are two main issues here, how the flaw went unnoticed and why Microsoft didn't reimplement the whole legacy thing.
:-) ), you can also do some other tasks.
Did anybody even RTFA? I've seen a lot of people already writing that Microsoft should have re-implemented the Legacy code, yadayadayada, write a new OS from scratch, introduce a new virtual machine just for OS compatibility. However, you all missed something very important. WMF is a well-defined standard (not saying a good one, but a well-defined one!) which means that Microsoft (or Wine for that matter) HAS TO IMPLEMENT IT WITH CERTAIN CONSIDERATIONS. One of them, is the SetAbortProc procedure that's been causing so much trouble. If Microsoft would failed to implement one part of this standard we would be getting comments like "M$ is 3vil, they don't respect standards...". I bet they're sorry that the security flaw got missed. I think it shows on their stock also! But non the less, it's fixed now.
Come to think of it, I think that, in a world where there were no exploits (PC-wise) the whole callback function scenario was pretty cool. You'd just say that if something fails, notify the user with this procedure in my code, and since you already no it failed (no return false statement
One more sidenote, Microsoft HAS REIMPLEMENTED the code. This is proven by the following statement in the article:
With WMF we want to be very clear: the Windows 9x platform is not vulnerable to any "Critical" attack vector. The reason Windows 9x is not vulnerable to a "Critical" attack vector is because an additional step exists in the Win9x platform: When not printing to a printer, applications will simply never process the SetAbortProc record. Although the vulnerable code does exist in the Win9x platform, all "Critical" attack vectors are blocked by this additional step.
I have no idea why they've let this slip though in the XP.
Something that people don't seem to realize is that when a new OS is created for a particular windows family (95/98/ME or NT4/2000/XP/2003/Vista), functions aren't 'ported'. Instead the same codebase is worked on until you arrive at the next version. So once that function was ported over from the 95 family to the NT4 family, it probably remained untouched, with this vulnerability. So it's not necessarily correct to say 'why did they keep porting this function across OS?!'.
The reality is the windows codebase has a ton of legacy in it. One positive step taken for Vista is that *all* code, including legacy (actually, most importantly, legacy), was SAL annotated so that static analysis of the full codebase could be performed for a large variety of coding mistakes that lead to vulnerabilities. Related to that, all memory/string functions that don't take bounds have been removed from the codebase, which allows SAL to statically analyze for buffer overruns. There's been a few times when thanks to updates to the SAL agent I've had bugs assigned to my code that catch obscure issues. You can read more about the technique at: http://research.microsoft.com/slam/ At the same time, WIM is doing a second security sweep of all windows components. This is in no way complete, given that things like this WMF vulnerability still got through, but still it is a start, and is a process that is evolving every day.
I'd like to point out that in Vista WMF is mitigated by the fact that unless you are logged in as the straight Administrator account, the arbitrary code executed from the WMF exploit will only have limited user access to the system (no access to write to the windows directory, program files directory, and system registry for example) even if the account is part of the Administrators group. Honestly this is probably the #1 reason to move to Vista -- it finally has a coherent LUA story and by default I can run all my apps with low priviledges.