Re: Privilege-escalation attacks on NT-based Windows are unfixable

From: Alun Jones (alun@texis.com)
Date: 08/22/02


From: alun@texis.com (Alun Jones)
Date: Thu, 22 Aug 2002 17:15:12 GMT

In article <3D645D37.507D3489@zetnet.co.uk>, David Hopwood
<david.hopwood@zetnet.co.uk> wrote:
>If the OS doesn't provide any information about message source, how is the app
>supposed to know? The OS kernel is the only component that can reliably provide
>information about privilege levels. If we were talking about newly defined
>message protocols, then there might be at least a possibility of rectifying
>this problem, but we're not.

That's my point - a secure application shouldn't be accepting input from an
unsecured source, or from a source that it cannot tell is reliably secured.
In other words, no secured, high-privilege application should be running with
a Windows message queue attached to the user's desktop. It's rather like
having a setuid program that accepts keyboard input and passes it, unchecked,
to a library routine. You're not going to do that, and it's especially stupid
if the library routine has known exploitable problems as well.

># The final message that we're going to make use of is WM_TIMER. This is a
># slightly odd and very dangerous message, since it can contain (as the second
># parameter) the address of a timer callback function. If this second parameter
># is non-zero, execution will jump to the location it specifies. Yes, you read
># that right; you can send any window a WM_TIMER message with a non-zero second
># parameter (the first is a timer ID) and execution jumps to that address. As
># far as I know, the message doesn't even go into the message queue, so the
># application doesn't even have the chance to ignore it. Silly, silly, silly...
>
>(I'm actually a little skeptical that there are messages that don't go into
>the message queue, but I can well believe that it would be difficult to do
>strict filtering of messages and still use any of the Windows common controls.)

Paget's comment is very vague with its "as far as I know". Why doesn't he
know? Why didn't he test this out? The documentation of WM_TIMER indicates
that it is similar to most other messages, in that the GetMessage call pulls
it out of the queue (this is in the message loop, a part of the code that the
application controls), and that it's then passed by the application to the
functions TranslateMessage and DispatchMessage. TranslateMessage does a
little manipulation of messages in the queue, so that "WM_KEYDOWN, WM_KEYUP,
WM_SYSKEYDOWN, or WM_SYSKEYUP" messages get translated into WM_CHAR,
WM_DEADCHAR, WM_SYSCHAR, and WM_SYSDEADCHAR messages, which is essentially a
mapping from keyboard matrix positions through the current locale/language
code-page to an actual character code. That's probably more information than
you cared to know :-)

DispatchMessage actually passes the message to the target window's WindowProc.
 One simple way for an application to cripple the WM_TIMER attack would be to
add a few lines of code after calling GetMessage, and prior to calling
DispatchMessage, that checked the WM_TIMER messages coming in against timers
known to the application, and discarded (i.e. never called DispatchMessage
with) those WM_TIMER messages that were not for timers that the app had
created, or whose function pointers did not match known locations of timer
control functions.

Since the documentation for DispatchMessage specifically notes WM_TIMER as
carrying a function pointer that is called instead of the window's WindowProc,
it would seem likely that this is the only message that can be exploited as
easily as this. But I wouldn't like to bet my security on it, so I repeat - a
component that accepts window messages from the user's desktop should not have
higher privilege than the user whose desktop it accepts messages from.

>You seem to have completely missed the point. What I said in my original
>post was:
>
> [...] it is impossible in principle on Windows {NT,2000,XP,CE} for any
> process that has a window on the desktop (including invisible windows)
> to protect itself from any other process running on the same machine,
> regardless of the privilege levels of either process.

That is correct. Any other process can engage in a number of message-based
attacks - denial of service, by posting large numbers of expensive-to-process
messages (I can't think of a specific message to choose as an example, but
that's not important). I haven't missed that point.

>You're saying that privileged processes should not have windows on the
>desktop; they should communicate via IPC with an unprivileged process
>instead (never mind that many privileged processes written by Microsoft
>fail to do this). Fine, but that doesn't contradict the above statement,
>and it also doesn't solve the problem: because the "desktop component" can
>still be taken over, there's no way for the service component to require
>that the unmodified desktop component is the only way to interact with it,
>no matter what "validation" it does.

What is the attack we are prote[sc]ting against? Privilege elevation. This
is counteracted by having a communication layer between the unprivileged
desktop component and the privileged service. In that way, while the attacker
may indeed get to make as many accesses as the service allows the user to
have, the attacker does not get to run in the process of the service. A good
design of a secure service will limit the information and control that is
available to a 'regular joe' user, so what you're arguing here is that if an
attacking process runs as the regular user, it has the same access to the
service as the regular user does. Uh... yes. I'm not disputing that, I'm
saying that this is an indication that the user has been "owned". The
service, however, has not.

Or are you suggesting that the unprivileged component is able to completely
control the privileged component? Ask yourself if that really sounds like a
competent, secure design.

>Also note that this approach at best only allows for two privilege levels.
>If there are really only two non-equivalent privilege levels in NT, many of
>the security APIs are ineffective and redundant. The original NT security
>design based on VMS clearly wasn't intended to reduce to only two levels,
>and it is disingenous for Microsoft or anyone else to try to claim that
>this attack isn't the result of a design flaw.

That's rubbish. This approach allows for two privilege levels in any
communication between two components. Gee, how many privilege levels are two
components supposed to have? Each has its own privilege level, there are two
of them communicating, that adds up to two. The system as a whole, however,
in which there are possibly multiple communicating components, clearly has
room for multiple privilege levels. You're arguing as if cryptography is only
available to people called Alice and people called Bob, because those are the
examples used.

>Compare with, say, X-Windows, where it's perfectly possible to have windows
>owned by processes with different privilege levels on the same desktop. If
>by design, any process could simulate keystrokes in an xterm where the user
>was logged into an administrative account, we'd consider X-Windows to be
>hopelessly insecure and unfit for purpose.

Others have addressed this issue, explaining that indeed another process can
do this, unless you specifically protect the xterm. Unix isn't my field, so
I'll leave it to them to argue that point.

Alun.
~~~~

[Please don't email posters, if a Usenet response is appropriate.]

-- 
Texas Imperial Software   | Try WFTPD, the Windows FTP Server. Find us at
1602 Harvest Moon Place   | http://www.wftpd.com or email alun@texis.com
Cedar Park TX 78613-1419  | VISA/MC accepted.  NT-based sites, be sure to
Fax/Voice +1(512)258-9858 | read details of WFTPD Pro for XP/2000/NT.



Relevant Pages


Quantcast