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
It's nice to know they are taking such a proactive stance on the issue of security. http://news.com.com/2100-1001-816880.html
Join the Slashcott! Feb 10 thru Feb 17!
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?).
Has anyone looked at the leaked source code to determine anything from the code written there? I've never actually seen or possessed the code and I wouldn't know where to look even if I did. But I'm sure SOMEONE out there still has it and so I wonder if anyone has examined the source to see if anything interesting appears there?
What I found interesting was this quote:
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.
Well, that explains (sort of) why they didn't feel obligated to update the 9x series, but it lacks a great deal of explanation as to why they would:
a. Keep what they knew could be a problem,
b. Make it even worse in their "new" edition.
I can see why they might have put it in in the first place, as a way to cancel printing, but what I still can't understand is why you'd extend to that extent.
Oh... yeah... it's Microsoft!
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.
Thinking back to http://it.slashdot.org/article.pl?sid=04/03/02/07
Was M$ helpeing to add a little extra into the USSR as US software flooded east?
The fun of a free door into any network thanks to M$ moving around the world?
In America bad code is no problem, it is just for end users.
In Soviet Union, expensive stolen code kills YOU.
Was M$ just a CIA front company gone too far?
Domestic spying is now "Benign Information Gathering"
I wonder whether the reason the wmf vulnerability was fixed in 9X and then broken in XP/2000 has to do with the way the NT stream was created. If I understand it correctly the initially diverged from Win 3.0. Perhaps the code was "fixed" in 9X but they reverted to the NT core code as the development went on into 2000/XP. I hear a lot about the compartmentalisation at MS.
I am inclined to believe in incompetence before conspiracy theories... (although incompetence does not leave me all warm and glowy)
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
Windows 95/98/Me operating systems are more secure than Windows 2000/XP.
The funny thing is, the statement is not as ridiculous as it sounds. They are of course not more secure, but they are actually less likely to get compromised by an attack. Since most of the current malware and virus uses newer functionality which do not exist or function slightly different on the older systems. Resulting in the malware simply not working on those old systems. I guess the mallware writers are not too concerned about backwards compability.
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.
Get over yourself.
.exe or .scr file.
And for what it's worth, I don't consider it a bug, or a failure, or anything else like that. It's a feature that was implemented in the format. You should always be careful when running formats that can contain executable code, just as you would with a
From MSDN:
A metafile contains records that describe a sequence of application programming interface (API) calls. Metafiles can be recorded (constructed) and played back (displayed).
A metafile is not a 'graphics format' exactly. It is rather a macro of API calls. Obviously one would suspect that such a thing could be used to execute malicious code.
Big ones, small ones, some as big as yer 'ead!
Give 'em a twist, a flick o' the wrist...
This should have never even been in the WMF specification in the first place .
It was a bad idea then.
It's a bad idea now.
What else is in their specs that's a bad idea?
Something like this WMF exploit, or perhaps less problematic but still annoying,
like GetTempFileName- where in 16 bits, you used a zero for the main drive and
a 1, 2, or so forth for the drive you wanted it to and in 32 bits, it's a string
with a canonical path to the place you want the temp file to be generated. Oh,
and by the way, zero's what most people used for their 16-bit code and a null
(zero on machines of the day...) produced undetermined results from the 32-bit
version of the API. Sometimes it'd work, sometimes it wouldn't. To be sure,
that sort of problem code wouldn't have gotten out the door. But if they've done
that sort of thing with their API's, I wouldn't trust that something never went
out with issues due to lurkers in the API's and specs that will come back to
bite someone on the ass down the line.
What else is lurking in MS' products that we don't know about? If they didn't design
it with security in mind then, what possesses you to think that they can go back
after the fact and bolt it on afterwards without causing it's own set of problems?
That'd be like using a hollow core door on the entry or exit of a house, and
not having a lock or deadbolt on the door- and then putting just a deadbolt on the
selfsame door when your house gets entered and people take things from you.
MS just simply needs to work at some solution to the issue of backwards compatibility
for their current OS products and start fresh with security in mind when they
do things. Anything else is like the door analogy I just gave.
I am not merely a "consumer" or a "taxpayer". I am a Citizen of the State of Texas
I'd even go so far as to say that when used as designed (single-user clients) were more secure. A box that runs no services listens on no ports, and a box that listens on no ports cannot be compromised remotely. Unbind NetBIOS from TCP/IP (5 minutes) and you eliminate the only attack vector on an out-of-the-box 9x installation. On XP (pre-SP1), you had to manually disable the uPnP service, NetBIOS service, Messenger, probably half a dozen other services that I'd forgotten, and use third-party tools (software "firewalls") to block port 135 and friends. Just about every service that came bundled with XP turned into a hole over the past few years. People running 9x was never affected.
People running IE (especially with the insecure default settings that enabled Javashit and ActiveX), or Outleak, were hosed -- but they got just as hosed on XP as they did on 9x.
It's not just that more people are targeting XP - it's that XP presented itself as a much bigger target.
It's important (from MS' viewpoint) because Gibson used the incorrect data to support a claim that this was an intentional backdoor. Given Gibson's general modus operandi, I'm sure the data being entirely incorrect won't slow him down a bit, but at least anybody with a somewhat unclouded view of reality realizes he was full of nonsense.
While you can trigger this with broken data, those who RTFA realize that the broken data is entirely incidental.
The universe is a figment of its own imagination.
So that's what the "wow" in wowexec means . . . and here I always thought it was some overworked coder saying "wow, we actually managed to get this ancient crapola working". You learn something new every day!
Read more closely. Where does Microsoft actually say that Gibson is wrong? Gibson claimed that Windows XP would read a .wmf file
and begin executing a portion of the data file contents as executable
code if a metafile record was encountered with a length of one
byte. Since the minimum length of a valid metafile record is 6
bytes, Gibson suggests that the behavior was intentional rather than an
accident. Microsoft doesn't actually SAY in their response that
any of what Gibson claims is wrong:
Gibson: Except that, when I was pursuing this and finally got it to work, what Windows did when it encountered this Escape function, followed by the SETABORTPROC metafile record, was it jumped immediately to the next byte of code and began to execute it. That is, it was no longer interpreting my metafile records record by record, which is the way metafiles are supposed to be processed.
Microsoft: If you are seeing that you can only trigger it with an incorrect value, it's probably because your SetAbortProc record is the last record in the metafile.
Gibson: It turns out that the only way to get Windows to misbehave in this bizarre fashion is to set the length to one, which is an impossible value. I tried setting it to zero. It didn't trigger the exploit. I tried setting it to two, no effect. Three, no effect. Nothing, not even the correct length. Only one.
Microsoft: The vulnerability can be triggered with correct or incorrect size values.
Even though the Microsoft guy claims he is going to "get rather technical here" he never specifies what he considers an 'incorrect' or 'correct' size value to be. More importantly, he never refutes the claim that a record with a length of one byte would always cause Windows to spawn a new thread and begin executing 'data' as code.
I think we should leave all technology decisions up to politicians. They know what's best for the rest of us. As a matter of fact, I'm thinking of putting up a Web site to encourage companies like Google, IBM, Microsoft and Apple to put politicians on all of their boards so that we're sure to get what's best for the people. Clearly in this case the Korean's are ahead of us!
Comments like this show that you probably don't have a lot of programming experience. The fact that they know what went wrong is because they already investigated it and fixed it. If they fixed it and still couldn't explain the problem, I'd worry that they didn't really fix it at all.
Hindsight is 20/20. Foresight is a little trickier.