I'm really, really disgusted that this even got posted. This isn't a Win32 vulnerability, it's a Virusscan vuln. (Watch my karma burn, I'm actually defending MSFT... but hear me out.)
For those of you who aren't familiar with Windows programming, here's what he's doing. Viruscan's GUI is very poorly written and doesn't check for a maximum length on a text box's input. So, he adjusts the size of a textbox using an outside program to 4GB. (Windows unfortunately allows this, since the message format doesn't include a "sender" field to check against the owner handle.) He then inserts shellcode in it, attaches a debugger to the process and searches all of memory for the start of the shellcode. Real efficient, this one.
He then sends it a WM_TIMER message to trigger it. WM_TIMER is usually sent to your window on a regular interval when you've called SetTimer(), and contains either an integral ID or a pointer to a callback in memory. So, he sends it a fake WM_TIMER, and Viruscan executes the callback blindly.
You know what, I use WM_TIMER too in my apps - but, there's two simple ways to defend against it.
if ((void *) msg.lparam != known_cb_address) { return false; }
if (0 != IsBadCodePtr((FARPROC) msg.lparam)) { go_fuck_yourself(); }
And if I'm not using it, special-case it so that it doesn't fall through to DefWindowProc().
Seriously, all this guy is doing is buffer overflowing a poorly written program to get Administrator privs. That's like claiming that glibc is insecure and should be thrown out because it has sprintf() or gets(). Ya know, I can buffer overflow a poorly written suid app too, but that doesn't make the libc to blame, nor have we published articles lambasting the GNU Project for not putting bounds checking into those functions.
This guy's just trying to sell himself [tombom.co.uk], and you guys were more than helpful. Maybe I should write a system service that subclasses MSIE's WndProc with a single function that calls ExitProcess(1), and see if Slashdot will find me a security job.
Sorry, I disagree with many of your comments here. While you've successfully tried to be objective without flamebait, some of the facts you have aren't true. I will try to be equally objective
This isn't a Win32 vulnerability, it's a Virusscan vuln It is a Win32 vulnerability in that it is even possible to have this kind of elevation of priveleges by "poorly written" services. Basically, any system service that interacts with the desktop is vulnerable (virus scanners). McAfee interacts with the desktop. This is bad too.
Viruscan's GUI is very poorly written and doesn't check for a maximum length on a text box's input It does, it has a set a maxlength of 4. Unfortunately, the vulnerability allows this to be bypassed. I'm sure the GUI will complain when you press the OK button but since we never get that far, the app never gets a chance to check the length change.
He then sends it a WM_TIMER message to trigger it... but, there's two simple ways to defend against it That's good practice but the real problem is where you comment yourself... And if I'm not using it, special-case it so that it doesn't fall through to DefWindowProc(). It's too much to ask any app that doesn't use WM_TIMER to put in this handler in all their apps. Further, I bet WM_TIMER isn't the only message he could use to trigger code.
Seriously, all this guy is doing is buffer overflowing a poorly written program to get Administrator privs Not any poorly written program but all desktop interactive services in existance.
Ya know, I can buffer overflow a poorly written suid app too Fortunately, the community tends to be able to fix these things by patching the source. There is no fix for this problem
This guy's just trying to sell himself OK, I will agree with you here... a little
Maybe I should write a system service that subclasses MSIE's WndProc No no no... you've cheated. As a system service, you already have priveleges. The exercise of this paper was to do with with Guest priveleges
>It is a Win32 vulnerability in that it is even >possible to have this kind of elevation of >priveleges by "poorly written" services. >Basically, any system service that interacts >with the desktop is vulnerable (virus scanners). >McAfee interacts with the desktop. This is bad >too.
If that is so, how do buffer overflow cracks manage to run themselves with elevated priviledges? Answer, they don't because the security level of the attacker is not the point of this 'flaw.' The point is that you can execute code at the level of another process by exploiting this 'overflow' like condition. Just as you can with many *nix applications. The fix for this IS the app. Of course, in fantasy land, the fix would be the OS...
It is a Win32 vulnerability in that it is even possible to have this kind of elevation of priveleges by "poorly written" services. Basically, any system service that interacts with the desktop is vulnerable (virus scanners). McAfee interacts with the desktop. This is bad too.
By the same token, is it a UNIX or Linux vulnerability if I run an insecure daemon suid root and someone buffer overflows it to get root privs?
It does, it has a set a maxlength of 4. Unfortunately, the vulnerability allows this to be bypassed. I'm sure the GUI will complain when you press the OK button but since we never get that far, the app never gets a chance to check the length change.
I'd disagree with you there. Viruscan's assuming that nobody will fuck with its code (the worst mistake you can make when dealing with crackers) and that it'll never get more than 4 characters. Maybe it's just me, but I automatically check length whenever I do ANYTHING with a buffer, and usually I make a quick call to IsBadWritePtr(buf, len) or IsBadCodePtr(callbk) while I'm at it.
Yes, technically you can't prevent him from changing the text box's maxlength, short of subclassing the text box with a custom WndProc after initializing that discards said messages. But that doesn't mean you can't write your code in a robust manner.
It's too much to ask any app that doesn't use WM_TIMER to put in this handler in all their apps. Further, I bet WM_TIMER isn't the only message he could use to trigger code.
I grant you that - MSFT fucked up by writing DefWindowProc() to blindly execute a callback. However, while tricky, I don't think it's fair to say that it's an unfixable problem, or that this is any different from some of the assumptions made in glibc's functions.
Fortunately, the community tends to be able to fix these things by patching the source. There is no fix for this problem.
Yep.
No no no... you've cheated. As a system service, you already have priveleges
By the same token, is it a UNIX or Linux vulnerability if I run an insecure daemon suid root and someone buffer overflows it to get root privs? There is a similarity and a distinction. The similarity is that yes, Mc Afee shouldn't make its service interact with the desktop. (Sidenote: Coulda sworn you could disable desktop interactivity... maybe it should be forced). The distinction is that *any* such app, no matter how well written is vulnerable.
Maybe it's just me, but I automatically check length whenever I do ANYTHING with a buffer Same here but nobody a range check for *every* single text box you have on every *keypress* event. It's not even an industry standard to do that. That makes this buffer overflow is far more subtle than most.
Same here but nobody a range check for *every* single text box you have on every *keypress* event. It's not even an industry standard to do that. That makes this buffer overflow is far more subtle than most.
Of course not - but if my keypress event involves copying text into a buffer, I'll be damned if I do it blindly. Doesn't mean I need to range check every single box, just the one that's being changed (and hence needing to be recopied).
"Not an industry standard" is hardly a valid excuse. You don't need to be paranoid on every single app and event you write, but "checking a buffer you're about to write into" is hardly some guru concept, it's damn near common sense.
You're right in everything you say. Unfortunately, it's the Windoze code that is putting the text into the buffer when the WM_PASTE is issued, not you. You only get to know about it *after* it has been put into the buffer with some windows event.
If we wanna get real technical, Windoze *does* do a range check on the text box buffer on WM_PASTE... unfortunately, the previous window message set the buffer length to 4GB! You can't account for such code, hence it is not industry standard (or any standard for that matter) to check the text buffer on every change event since it is outside your code's juristiction
Very true. However, keep in mind that it's not really an exploit to do this. We would like to hope that we could prevent anyone from changing its parameters except us, but short of subclassing a text box, we can't do that.
(Well, it actually wouldn't be too bad. We write a single WndProc that discards all messages except the essentials for operation (and NOT setup) and then call SetWindowLong after every initialization to "lock" it, call it again to unlock it with the default WndProc from the TEXT atom.)
Also consider that WM_PASTE is being issued from the textbox, and it's the textbox wndproc that's doing a DDE copy (or whatever they use these days for transfer in 2K/XP) from the clipboard to the text box's internal buffer. That's entirely client side.
The real vulnerability in this exploit is the lack of sanity checking on DefWindowProc's WM_TIMER handler, not the text box, since you could still look up the shellcode in the text box's buffer without having to copy it into your own. The text box is just one of the many unfortunate ways it could be abused, and a decent example of the more general problem of insecurity in the message dispatch design. However, there's no way to fix the general problem without breaking a number of apps - and we also can't really dismiss said apps as legacy, either. There's also a problem in that Windows doesn't take advantage of the x86's ability to mark blocks of memory as non-executable... but that's a whole other rant.
The only way I can see to prevent such abuses is to write a homebrew set of widgets that use genuine transactions to perform operations, providing security at the cost of performance. But then, if you allow the hacker to have a debugger installed on the system and ready to go, then you're also likely allowing him to replace the USER32 and KERNEL32 libraries with dummied ones, and really, nothing is safe.
Linux and FreeBSD don't really take advantage of the x86 ability to mark code as executable either. It's not just WinNT. Well technically the non-x86 ports do in the VM code, but the x86-specific VM code simple considers "executable" and "readable" the same thing.
No OSes these days really use segmentation to its slowness and complexity. They prefer to handle everything at page (VM) level, which really differentiates between system (ring0-2) and user (ring3) privilege levels. Also, x86 paging cannot change execution privileges on the code (this goes back to the design elements of the x86).
In order to implement something your suggesting would mean always screwing around the with GDT and LDT, and define regions in the virtual address space for each process for different purposes, in a manner which is inflexible.
No - the problem still occurs even if VirusScan does check the size of the edit control. It occurs even if VirusScan never looks at the contents of the edit control. The edit control automatically allocates memory when it receives a PASTE message. Even if you then access the edit control and say "give me your first 4 bytes" (or "truncate to 4 bytes"), the entire paste is still in the allocated memory, which is enough for this exploit to work.
To prevent this paste you would have to either filter WM_PASTE messages (and any other messages that have similar functions), and/or filter the message which sets the maximum length of text.
After all is said and done, a hell of a lot more is said than done.
What a load of tripe. (Score:5, Informative)
For those of you who aren't familiar with Windows programming, here's what he's doing. Viruscan's GUI is very poorly written and doesn't check for a maximum length on a text box's input. So, he adjusts the size of a textbox using an outside program to 4GB. (Windows unfortunately allows this, since the message format doesn't include a "sender" field to check against the owner handle.) He then inserts shellcode in it, attaches a debugger to the process and searches all of memory for the start of the shellcode. Real efficient, this one.
He then sends it a WM_TIMER message to trigger it. WM_TIMER is usually sent to your window on a regular interval when you've called SetTimer(), and contains either an integral ID or a pointer to a callback in memory. So, he sends it a fake WM_TIMER, and Viruscan executes the callback blindly.
You know what, I use WM_TIMER too in my apps - but, there's two simple ways to defend against it.
if ((void *) msg.lparam != known_cb_address)
{
return false;
}
if (0 != IsBadCodePtr((FARPROC) msg.lparam))
{
go_fuck_yourself();
}
And if I'm not using it, special-case it so that it doesn't fall through to DefWindowProc().
Seriously, all this guy is doing is buffer overflowing a poorly written program to get Administrator privs. That's like claiming that glibc is insecure and should be thrown out because it has sprintf() or gets(). Ya know, I can buffer overflow a poorly written suid app too, but that doesn't make the libc to blame, nor have we published articles lambasting the GNU Project for not putting bounds checking into those functions.
This guy's just trying to sell himself [tombom.co.uk], and you guys were more than helpful. Maybe I should write a system service that subclasses MSIE's WndProc with a single function that calls ExitProcess(1), and see if Slashdot will find me a security job.
Re:What a load of tripe. (Score:4, Informative)
This isn't a Win32 vulnerability, it's a Virusscan vuln
It is a Win32 vulnerability in that it is even possible to have this kind of elevation of priveleges by "poorly written" services. Basically, any system service that interacts with the desktop is vulnerable (virus scanners). McAfee interacts with the desktop. This is bad too.
Viruscan's GUI is very poorly written and doesn't check for a maximum length on a text box's input
It does, it has a set a maxlength of 4. Unfortunately, the vulnerability allows this to be bypassed. I'm sure the GUI will complain when you press the OK button but since we never get that far, the app never gets a chance to check the length change.
He then sends it a WM_TIMER message to trigger it... but, there's two simple ways to defend against it
That's good practice but the real problem is where you comment yourself... And if I'm not using it, special-case it so that it doesn't fall through to DefWindowProc(). It's too much to ask any app that doesn't use WM_TIMER to put in this handler in all their apps. Further, I bet WM_TIMER isn't the only message he could use to trigger code.
Seriously, all this guy is doing is buffer overflowing a poorly written program to get Administrator privs
Not any poorly written program but all desktop interactive services in existance.
Ya know, I can buffer overflow a poorly written suid app too
Fortunately, the community tends to be able to fix these things by patching the source. There is no fix for this problem
This guy's just trying to sell himself
OK, I will agree with you here... a little
Maybe I should write a system service that subclasses MSIE's WndProc
No no no... you've cheated. As a system service, you already have priveleges. The exercise of this paper was to do with with Guest priveleges
Regards,
Re:What a load of tripe. (Score:1)
If that is so, how do buffer overflow cracks manage to run themselves with elevated priviledges? Answer, they don't because the security level of the attacker is not the point of this 'flaw.' The point is that you can execute code at the level of another process by exploiting this 'overflow' like condition. Just as you can with many *nix applications. The fix for this IS the app. Of course, in fantasy land, the fix would be the OS...
Re:What a load of tripe. (Score:3, Informative)
By the same token, is it a UNIX or Linux vulnerability if I run an insecure daemon suid root and someone buffer overflows it to get root privs?
It does, it has a set a maxlength of 4. Unfortunately, the vulnerability allows this to be bypassed. I'm sure the GUI will complain when you press the OK button but since we never get that far, the app never gets a chance to check the length change.
I'd disagree with you there. Viruscan's assuming that nobody will fuck with its code (the worst mistake you can make when dealing with crackers) and that it'll never get more than 4 characters. Maybe it's just me, but I automatically check length whenever I do ANYTHING with a buffer, and usually I make a quick call to IsBadWritePtr(buf, len) or IsBadCodePtr(callbk) while I'm at it.
Yes, technically you can't prevent him from changing the text box's maxlength, short of subclassing the text box with a custom WndProc after initializing that discards said messages. But that doesn't mean you can't write your code in a robust manner.
It's too much to ask any app that doesn't use WM_TIMER to put in this handler in all their apps. Further, I bet WM_TIMER isn't the only message he could use to trigger code.
I grant you that - MSFT fucked up by writing DefWindowProc() to blindly execute a callback. However, while tricky, I don't think it's fair to say that it's an unfixable problem, or that this is any different from some of the assumptions made in glibc's functions.
Fortunately, the community tends to be able to fix these things by patching the source. There is no fix for this problem.
Yep.
No no no... you've cheated. As a system service, you already have priveleges
I was being sarcastic by that point. ^_^
Re:What a load of tripe. (Score:1)
There is a similarity and a distinction. The similarity is that yes, Mc Afee shouldn't make its service interact with the desktop. (Sidenote: Coulda sworn you could disable desktop interactivity... maybe it should be forced). The distinction is that *any* such app, no matter how well written is vulnerable.
Maybe it's just me, but I automatically check length whenever I do ANYTHING with a buffer
Same here but nobody a range check for *every* single text box you have on every *keypress* event. It's not even an industry standard to do that. That makes this buffer overflow is far more subtle than most.
Re:What a load of tripe. (Score:1)
Of course not - but if my keypress event involves copying text into a buffer, I'll be damned if I do it blindly. Doesn't mean I need to range check every single box, just the one that's being changed (and hence needing to be recopied).
"Not an industry standard" is hardly a valid excuse. You don't need to be paranoid on every single app and event you write, but "checking a buffer you're about to write into" is hardly some guru concept, it's damn near common sense.
Re:What a load of tripe. (Score:1)
If we wanna get real technical, Windoze *does* do a range check on the text box buffer on WM_PASTE... unfortunately, the previous window message set the buffer length to 4GB! You can't account for such code, hence it is not industry standard (or any standard for that matter) to check the text buffer on every change event since it is outside your code's juristiction
Re:What a load of tripe. (Score:1)
(Well, it actually wouldn't be too bad. We write a single WndProc that discards all messages except the essentials for operation (and NOT setup) and then call SetWindowLong after every initialization to "lock" it, call it again to unlock it with the default WndProc from the TEXT atom.)
Also consider that WM_PASTE is being issued from the textbox, and it's the textbox wndproc that's doing a DDE copy (or whatever they use these days for transfer in 2K/XP) from the clipboard to the text box's internal buffer. That's entirely client side.
The real vulnerability in this exploit is the lack of sanity checking on DefWindowProc's WM_TIMER handler, not the text box, since you could still look up the shellcode in the text box's buffer without having to copy it into your own. The text box is just one of the many unfortunate ways it could be abused, and a decent example of the more general problem of insecurity in the message dispatch design. However, there's no way to fix the general problem without breaking a number of apps - and we also can't really dismiss said apps as legacy, either. There's also a problem in that Windows doesn't take advantage of the x86's ability to mark blocks of memory as non-executable... but that's a whole other rant.
The only way I can see to prevent such abuses is to write a homebrew set of widgets that use genuine transactions to perform operations, providing security at the cost of performance. But then, if you allow the hacker to have a debugger installed on the system and ready to go, then you're also likely allowing him to replace the USER32 and KERNEL32 libraries with dummied ones, and really, nothing is safe.
Re:What a load of tripe. (Score:2)
No OSes these days really use segmentation to its slowness and complexity. They prefer to handle everything at page (VM) level, which really differentiates between system (ring0-2) and user (ring3) privilege levels. Also, x86 paging cannot change execution privileges on the code (this goes back to the design elements of the x86).
In order to implement something your suggesting would mean always screwing around the with GDT and LDT, and define regions in the virtual address space for each process for different purposes, in a manner which is inflexible.
--JQuirke
Re:What a load of tripe. (Score:2)
To prevent this paste you would have to either filter WM_PASTE messages (and any other messages that have similar functions), and/or filter the message which sets the maximum length of text.