I was chatting a while ago about Windows Messaging with someone and the pitfalls associated with it.
So – if one is unfamiliar with Windows Message Handling here’s a decent brush-up:
http://www.codeproject.com/KB/dialog/messagehandling3.aspx
BTW – the following is pretty much taken from toassa (like one of the best tech books ever written): http://taossa.com/
Essentially – Windows OS’s deliver messages to windows in a FIFO queue. Messages can be generated by system events like mouse movements or key presses. They can also be generated by other threads on the same desktop. Windows messages control most aspects of the UI, including clipboard operations and properties of a window.
There are 4 essential steps in creating a functional windowed application:
1. Creating a WindowProc() function to handle messages.
2. Defining a class that associates this WindowProc() to a window type.
3. Creating an instance of the Window class.
4. Creating a message-processing loop.
Anyways, any process with a handle to a window station can send messages to any other window on a desktop object within that window station (any process can send a message to any other desktop object on the same desktop). All that’s needed is a SendMessage() function.
LRESULT SendMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
So this brings us to shatter attacks.
The Windows API ties a lot of functionality into a simple, unprotected, messaging architecture. Every aspect of the user interface is controlled by window messages, and the design of the API provides no method of restricting or verifying a message source.
The original shatter attack from 2002 – Chris Paget’s paper titled, “Exploiting design flaws in the Win32 API for privilege escalation“) exploited window message design by sending a WM_PASTE message to a privileged process with a message pump on the same window station. The WM_PASTE message allows attackers to place a buffer of shell code in the address space of the privileged process. The attack is then completed by sending a WM_TIMER message that includes the address of the shell code buffer. The default handler for the WM_TIMER message simply accepts the address parameter as a function pointer, then runs the code that it points to. The result is a straightforward privilege escalation.
The immediate response to the shatter vulnerability was to simply filter the WM_TIMER message in any privileged process interacting with a user’s desktop. However, there are many other messages that allow manipulation of memory in a target process.
In 2004 Brett Moore had a talk at BlackHat about this:
http://www.blackhat.com/presentations/bh-usa-04/bh-us-04-moore/bh-us-04-moore-up.ppt
For instance, according to his whitepaper: Previous shatter attacks have been based on the use of messages that accept a pointer as a parameter. This pointer deirects execution flow to data that has been supplied by the attacer, therefore allowing the attacker to have a process execute code of their choice.
Several windows message will accept a pointer to a callback function as one of the parameters to the SendMessage API. One of these is LVM_SORTITEMS…
He also mentions messages like HDM_GETITEMRECT, which accepts a pointer to a POINT or RECT structure which will be used to retrieve GDI information about windows. These pointers do not appear to be validated in any way…
Also – he has an exploit that demonstrates the use of Progress Control message shatter attacks and discusses other vulnerable messages that can come in handy to exploit.
As a matter of fact, he discovered a more recent vulnerability in a Symantec product using a Shatter Attack (Feb. 2008):
http://www.securityfocus.com/bid/27645
For someone looking at the code of the program, toassa summarizes the following steps to identify potential shatter attack exposures for a given service:
1. Check the MMC snap-in for the service to see whether it runs as the interactive user. Use MMC -> open the Properties dialog box for the service -> check the “Log On” tab to see whether the “Allow Service to Interact with Desktop” option is selected.
2. Examine the code to determine whether it manually attaches to the interactive user’s desktop.
3. If either case is true, determine whether a message pump is in operation for receiving window messages. If a message pump is in operation, you can consider the application to be at risk.
Also, according to my favorite reference – taossa, certain COM applications can create background messages windows which can be vulnerable as well.
In Brett Moore’s Blackhat 2004 preso (which I also cited earlier) he also makes references to attacking thick applications on windows using shatter attacks – which will probably hit home a lot more for people who don’t do too much testing on traditional C/C++ programs.
Now Microsoft has done certain things to try to stop shatter attacks over the years – from Wikipedia “In December 2002, Microsoft issued a patch for Windows NT 4.0, Windows 2000, and Windows XP that closed off some avenues of exploitation. This was only a partial solution, however, as the fix was limited to services included with Windows that could be exploited using this technique;”
Also – they did some stuff with Vista using User Interface Privilege Isolation (UIPI).
So most of the vulnerable programs will be third-party applications.
Really – the most devastating scenario that I can think of – and probably the most common is someone with “normal” user privileges exploits a third-party program running as system over Terminal Servers. This would effectively give a normal, segregated user (Term. Services) control over the whole system (system privileges).
Chris Paget originally had these recommendations to solve the problem:
I can see two quick and dirty methods which will break a whole lotta functionality, and one very long-winded solution which is never going to be a total solution. Let me explain.
1. Don’t allow people to enumerate windows Nasty. Multiple breakages. Theoretically possible, but I’d hate to see people trying to work around not knowing what windows are on the desktop when they need to.
2. Don’t allow messages to pass between applications with different privileges Means that you couldn’t interact with any window on your desktop that’s not running as you; means that VirusScan at the very least (probably most personal firewalls, too) would need a whole lotta redesigning.
3. Add source info to messages, and depend on applications to decide whether or not to process the messages Would need an extension to the Win32 API, and a whole lotta work for people to use it. Big job, and people would still get it wrong. Look at buffer overflows – they’ve been around for years, and they’re still fairly common.
So what would someone do if they really wanted to build a safe (not vulnerable to shatter attacks) application that had a desktop GUI?
All would probably agree that it does make sense to run the application as one of least privilege and that might be a first thought – but that’s not always possible as some applications need to communicate to things on a privileged level and make certain system level calls.
To someone that really, really cares about it – I might recommend the following as a solution to shatter attacks for an application (This is actually from Wikipedia – don’t laugh – but I think it makes sense):
…a two-process design where a process is loaded into the user’s session that interacts with the service process through inter-process communication. Additionally, when a privileged operation is required to be undertaken, an authenticated call is made that loads additional service code. Once that privileged code is finished doing what needs to be done, it is unloaded from memory so that it does not remain in memory to be a possible target for later exploitation.
So – essentially one would need to design the window interface with lower privileges and communicate through IPC to another, more higher privileged (server) process to make the calls that require higher privileges.
Brett Moore – in his 2004 whitepaper concludes with the following (after a lot of patches that Microsoft released in 2002 to protect some system applications that the OS’s shipped with):
The exploitation of shatter attacks have come a long way from when the original vulnerability was announced. As we have shown in this document, even the most obscure of messages can be used to make a process execute code that it was not intended to run.
While there have been discussions around the filtering of messages to protect interactive applications that run under a higher security context. It is becoming apparent that the only sure solution is to not have these applications running on an untrusted users desktop.
Application designers and system administrators need to be aware of the dangers associated with running higher privileged applications on a users desktop, and take steps to prevent them from been exploited. The examples included in this paper can be used against any interactive application that runs at a higher level, simply by specifying parameters such as the window title. Successful exploitation would allow a user to then execute commands under this higher-level security context.
So Brett says there’s not too much one can do either to prevent shatter attacks (but he didn’t mention the whole thing where we can split up the program into 2 different processes and have them communicate over IPC).
Of course – this is hard to do – especially when you think your application is not vulnerable because it doesn’t have any windowing GUI’s. According to his post here, he attacked an application that didn’t even have a window – well, not normally anyways:
We discovered that [Service X], that did not normally have a window, could
be enticed into generating an error that would display a window. The
service stored a pointer to a lookup table in the window memory pointed to
by GWL_USERDATA. This lookup table held the address of functions, and was
later used to retrieve an address and pass it to a CALL instruction.
By using the process mapped heap, as explained in my Blackhat presentation,
it was possible to place our shellcode into a known location. We could also
construct a new lookup table, pointing to our shellcode, in a known
location.
Then by using SetWIndowLongPtr() API we replaced the pointer to the lookup
table with the address of our new lookup table. The service would use our
lookup table and execution would therefore reach the shellcode.
We should keep in mind as well – that it could be a whole different ballgame with Vista and Server 2008. Microsoft did a couple of things to try to fix the problem of shatter attacks (that’s a whole other post).
Although – I was just thinking a little while ago, how one could gain a name really quickly and some easy PR through this kind of research. Just find some programs that have a windowed desktop and that run with system level privilege – read up a little more about shatter attack stuff, then just publish a vulnerability like this: http://www.securityfocus.com/bid/27645. I figure it’d be a good way to get one’s name in print – this particular one (also referenced above) was just released in Feb. 08.
Cheers,
Chuck B.
0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment