30

Before Windows introduced User Interface Privilege Isolation, any application could send all kinds of window messages to any window on the same desktop (a shatter attack), allowing elevation of privilege.

Now, UIPI stops low-privilege applications from sending most window messages to higher-privilege applications. Wikipedia says:

User Interface Privilege Isolation (UIPI) is a technology introduced in Windows Vista/2008 Server to combat shatter attack exploits. By making use of Mandatory Integrity Control, it prevents processes with a lower "integrity level" (IL) from sending messages to higher IL processes (except for a very specific set of UI messages).

That sounds like it ought to deal with the problem - according to this PDF linked in that article, only WM_NULL, WM_MOVE, WM_SIZE, WM_GETTEXT, WM_GETTEXTLENGTH, WM_GETHOTKEY, WM_GETICON, WM_RENDERFORMAT, WM_DRAWCLIPBOARD, WM_CHANGECBCHAIN, WM_THEMECHANGED, and the undocumented 0x313 and 0x31B are allowed. (The PDF does mention a possible denial-of-service attack, starting on page 57, but while a problem, that's not elevation of privilege. I also did a cursory inspection of the DLL responsible, and it seems that on Windows 8 it doesn't actually register the message that leads to the problem.)

It doesn't look like any of those have the problem created by WM_TIMER, which caused the target process to jump to an arbitrary address. However, this article by a Microsoft blogger (Raymond Chen) strongly insinuates that shatter attacks are still a problem:

What you can do is have a service inject the program into the session, and let it run as the logged-on user. (You have to make it run as the logged-on user in order to avoid a shatter attack.)

This Microsoft document on UAC notes that some resources "are still shared between processes at different privilege levels":

  • Desktop window, which actually owns the screen surface.
  • Desktop heap read-only shared memory.
  • Global atom table.
  • Clipboard

Still, just having those things accessible from processes at different privilege levels wouldn't seem to allow the actual jump that causes the elevation of privilege. And even if the jump was made, I'd think that Data Execution Prevention would stop the injected code from actually being run.

So, does having a window from a process running as SYSTEM on a low-privilege user's desktop still give that user the opportunity to elevate privileges?

Ben N
  • 2,491
  • 1
  • 12
  • 22
  • I've started looking into this myself and from what I have gathered and tried so far the WM_TIMER bug is closed (win7/win32). Your assumption that DEP prevents injection is also correct, just different from what I would have exptected. The blogpost by Chen is not an exploit per se, and is even used Windows Sysinternals' PsExec. – Yorick de Wid Aug 29 '16 at 14:05
  • The last paragraph of Joana Rutkowska's [Linux Security Circus](https://theinvisiblethings.blogspot.ch/2011/04/linux-security-circus-on-gui-isolation.html) blog entry leaves me with mixed feelings about this question. She says it's "still easy to bypass this solution", but doesn't elaborate. Here's her saying a bit more about [Isolation](https://theinvisiblethings.blogspot.ch/2007/02/running-vista-every-day.html) (fairly ancient, 2007), but no real pointers about security weaknesses. – Out of Band Feb 28 '17 at 23:13
  • lol, thought you were referencing the shattered attack Google just released on sha1 – MikeSchem Mar 14 '17 at 03:23

1 Answers1

1

UIPI does prevent a process with a lower integrity level from sending either a WM_TIMER or EM_GETLINE message to a higher integrity level process. These were the two message types that could be abused to elevate privileges on a system. Lower integrity level processes can still send limited message types to high level processes, but they cannot be used to take control of the processes execution. As far as DEP being the saving grace, you could use WM_TIMER or EM_GETLINE to start execution of a ROP chain. In this case you would need to find opcodes that would allow you to pivot the stack (this is where the WM_TIMER callback would send execution to) to a new location containing the addresses in your ROP chain.

luizfzs
  • 261
  • 2
  • 12
Joshua Gimer
  • 290
  • 1
  • 5