Getting logged in user from a service?

W

Willy Denoyette [MVP]

Peter Duniho said:
I can't cite an example with respect to WMI, since I haven't used it.
However, Windows services are themselves a broad category of examples of
just what Willy is talking about. The whole point for many services is to
provide a point of access through which users can access
otherwise-sensitive areas of the computer.

The service itself runs at elevated privileges, providing filtered access
to things that no user can with their default privileges access.

As an example: is it a bad thing, in defiance of standard Windows
security, for there to be a SQL Server service that has elevated rights to
access a database, and which delegates those rights (in a controlled way)
to a user that connects to the SQL Server service?

Pete


That's right. I guess Larry has missed the point that WMI is C/S based.
Clients are connecting over DCOM, using highly optimized LRPC's (that is
over shared memory) for local connections, and because of this it enjoys all
the security benefits of DCOM for the session and great performance, but
when it comes to "privileges", he's using his own token or an impersonation
token (it's even possible to use Kerberos delegation) to execute whatever
service implemented in so called loadable service providers (in-proc or
out-proc).This model is exactly what SQLServer uses when connecting using
shared memory as C/S protocol.
Note that it's even possible to inject a (high performance) provider in the
clients code, but this is a discussion for another NG.
Note that WMI uses DCOM over SMB (or should I say CIFS ;-)) when connecting
to a remote instance, however, this is an implementation detail, the same
security rules apply.

Willy.



Willy.
 
L

Larry Smith

Not at all, WMI is client/server based using DCOM, you call a service and
the service executes the service call, when WMI needs to "enable" a
privilege (note that I said 'enable'), it' s up to the caller to ask the
service to enable the required (whatever this one may be)privilege, the
user doesn't need to know the "privilege" required, WMI know which one as
it's stored in it's metabase.
In the exceptional case (there are only a few) that a call requires a
privilege that is not held by the WMI account (say "Network Service"),
then it's up to the caller to run as a more privileged user (or get a
stronger logon token) and ask WMI to impersonate when executing the
service call.

Part of my argument has been in response to these (sometimes) confusiing
comments about security. All WMI would be doing here is enabling privileges
that are already present in the caller's token (not its own). That's what
Ben Voight was referring to in his earlier response. It's a minor
convenience but one that's expected over the native OS since WMI sits on top
of it (providing higher-level services). If you don't have the required
privilege(s) in the first place however then WMI can't help you. Nor should
impersonation be required here since it's not needed. Your earlier comments
such as "... most of these things are taken care of by the framework and
it's underlying services" and " ... WMI makes it possible to call OS
services without YOU having the need to run with these elevated privileges"
are therefore misleading. Security is still an issue that needs to be
considered but you've been implying otherwise. In any case, I can't counter
arguments about ease-of-use in general. Higher-level services are inherently
easier to use by their very nature so it's compelling to champion their use.
They're not always the right tool for the job however. The entire crux of my
argument centers around that and their place in a service in particular. I
find your earlier arguments about monolithic services as self-defeating in
fact since there's no special threshold involved here. Nor is memory
consumption (necessarily) an accurate indicator of just how big these apps
really are (since memory is affected by other things such as the amount of
client data currently being cached). A small footprint is therefore a
relative term. Imagine how much larger and slower those services would be if
they actually relied on .NET instead of C++ and the native OS (which they
most likely do at the core). Do you think MSFT or most organizations would
even consider .NET for most services? Not likely.
 
W

Willy Denoyette [MVP]

Larry Smith said:
Part of my argument has been in response to these (sometimes) confusiing
comments about security. All WMI would be doing here is enabling
privileges that are already present in the caller's token (not its own).
That's what Ben Voight was referring to in his earlier response. It's a
minor convenience but one that's expected over the native OS since WMI
sits on top of it (providing higher-level services). If you don't have the
required privilege(s) in the first place however then WMI can't help you.
Nor should impersonation be required here since it's not needed. Your
earlier comments such as "... most of these things are taken care of by
the framework and it's underlying services" and " ... WMI makes it
possible to call OS services without YOU having the need to run with these
elevated privileges" are therefore misleading. Security is still an issue
that needs to be considered but you've been implying otherwise. In any
case, I can't counter arguments about ease-of-use in general. Higher-level
services are inherently easier to use by their very nature so it's
compelling to champion their use. They're not always the right tool for
the job however. The entire crux of my argument centers around that and
their place in a service in particular. I find your earlier arguments
about monolithic services as self-defeating in fact since there's no
special threshold involved here. Nor is memory consumption (necessarily)
an accurate indicator of just how big these apps really are (since memory
is affected by other things such as the amount of client data currently
being cached). A small footprint is therefore a relative term. Imagine how
much larger and slower those services would be if they actually relied on
.NET instead of C++ and the native OS (which they most likely do at the
core). Do you think MSFT or most organizations would even consider .NET
for most services? Not likely.


All WMI's security levels are highly customizable, the namespaces are all
protected by DACL's you can adjust, you can prevent certain user to access,
read, write, execute etc...it's namespaces, if a user is allowed to execute
a method, WMI will simply enable or add the privilege (to it's own
token)when needed on a per call basis.

Some classes and methods need an impersonation token from the base client,
if the token holds a needed privilege to execute or access a namespace
class, WMI enables this privilege, when the token misses the privilege, the
call fails.
That way it's possible to perform some administrative tasks without you, the
client, to run as an administrator, you are simply delegating the task to
another more privileged process, which on it's turn is rather restricted.
Look back at what Nicholas proposed, get the Handle of another process, if
you don't run in the same logon session, you won't be able to access to
process object to obtain the Handle (that is, Win32 OpenProcess will return
access denied) unless you are running as administrator and even then, you
won't probably be able to get all handles, there is nothing you can do
without a process handle, game over. This is not an issue when using WMI (or
System.Management, this is .NET right!).

Just try this as non administrator,

Process [] procs= Process.GetProcesses();
foreach(Process pro in procs)
{
try {
IntPtr handle = pro.Handle;
}
catch( Exception ex){Console.WriteLine(ex);}
}
and watch all:
System.ComponentModel.Win32Exception: Access is denied
at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32
access, Boolean throw
IfExited)
thrown on you ...

This is exactly why so many programs run in the "administrators" account
these days, worse some have "SeDebugPrivilege" enabled, talking about a
surface attack.

Willy.
 
W

Willy Denoyette [MVP]

Larry Smith said:
Part of my argument has been in response to these (sometimes) confusiing
comments about security. All WMI would be doing here is enabling
privileges that are already present in the caller's token (not its own).
That's what Ben Voight was referring to in his earlier response. It's a
minor convenience but one that's expected over the native OS since WMI
sits on top of it (providing higher-level services). If you don't have the
required privilege(s) in the first place however then WMI can't help you.
Nor should impersonation be required here since it's not needed. Your
earlier comments such as "... most of these things are taken care of by
the framework and it's underlying services" and " ... WMI makes it
possible to call OS services without YOU having the need to run with these
elevated privileges" are therefore misleading. Security is still an issue
that needs to be considered but you've been implying otherwise.

Really where? The client doesn't need to run with elevated privileges to
perform a task, which otherwise would require administrator privileges, see
my other reply concerning the OpenProcess API call. All there is done is
delegate the request to another Service that runs with restricted privileges
(NOT as SYSTEM), you the clients needs higher privileges than thos taht can
be enabled or added to the service access token, the Client will need to run
with higher privileges or the call will fail, this is basically DCOM
security and access control, and privilege management combined. If this is
not secure, then tell me what's more secure, however, don't tell me that you
call security API's (as you suggested from the beginning), because most
important will require you to run with high privileges (see LogonUser,
OpenProcess etc..)


In any case, I can't counter
arguments about ease-of-use in general. Higher-level services are
inherently easier to use by their very nature so it's compelling to
champion their use. They're not always the right tool for the job however.
The entire crux of my argument centers around that and their place in a
service in particular. I find your earlier arguments about monolithic
services as self-defeating in fact since there's no special threshold
involved here. Nor is memory consumption (necessarily) an accurate
indicator of just how big these apps really are (since memory is affected
by other things such as the amount of client data currently being cached).
A small footprint is therefore a relative term. Imagine how much larger
and slower those services would be if they actually relied on .NET instead
of C++ and the native OS (which they most likely do at the core). Do you
think MSFT or most organizations would even consider .NET for most
services? Not likely.

so what? MSFT doesn't consider .NET to build SQLServer or Office either,
does that mean you shouldn't use it either? However it uses .NET for
Bizztalk and Windows Live services.


Tell me what do you call low-level services then, what makes you think that
native code services are more low level than .NET services, for the SCM they
are exactly the same , at run-time all there is executed is native code,
point.
What makes you think that .NET services are that much slower than native C++
services, they are performing largely at the same level, with only a slight
advantage for native C++ in some special cases, but that's not important for
a Service anyway, services are not the applications that consume a lot of
CPU or other resources, question is do they perform at an acceptable level,
and here the answer is YES in most cases.
Is it because you have the .NET BCL loaded in that process that you think
they are high level?, what if you are using native C++ using ATL "service"
templates, is this low level enough? Do you think MSFT services are using
ATL, sure they don't, but what does this prove, that *you* shouldn't use ATL
either?

Note that this discussion is getting largely OT, the OP has a Service built
using C# and he's allready using System.Management (aka native WMI
wrappers), I answered his question based on his usage scenario, I'm not here
to tell people not to use .NET for this really.
In your opinion he should use low-level stuff, by which I guess you mean
native C++ calling Win32 API's, not using WMI (this, while almost all MSFT's
Services expose their state and a lot of their management functions through
WMI).
If this is the case, I'm afraid we will have to agree to disagree.

Willy.
 
L

Larry Smith

... WMI will simply ... add the privilege (to it's own token)when needed
on a per call basis.

That would be surprising considering that privileges can't be added to an
existing token since tokens are mostly immutable. There is no function that
does this. You need to add it to an existing account first and create a new
logon session. At least that's the way Windows security has always worked
assuming MSFT hasn't made any radical changes lately (which would greatly
surprise me in this area). Of course MSFT can always make their own code do
anything it wants but I don't see why they would breach their own security.
Some classes and methods need an impersonation token from the base client,
if the token holds a needed privilege to execute or access a namespace
class, WMI enables this privilege, when the token misses the privilege,
the call fails.
That way it's possible to perform some administrative tasks without you,
the client, to run as an administrator, you are simply delegating the task
to another more privileged process, which on it's turn is rather
restricted.
Look back at what Nicholas proposed, get the Handle of another process, if
you don't run in the same logon session, you won't be able to access to
process object to obtain the Handle (that is, Win32 OpenProcess will
return access denied) unless you are running as administrator and even
then, you won't probably be able to get all handles, there is nothing you
can do without a process handle, game over. This is not an issue when
using WMI (or System.Management, this is .NET right!).

An administrator can do anything it wants including accessing all handles.
It just has to enable the SeDebugPrivilege privilege in its own token. I
don't follow the other details however. If a program has the correct
privilege(s) to do something then it doesn't need to delegate it to someone
else. It can just do it on its own though it may have to enable a given
privilege first (a simple task). If by delegating however you mean allowing
WMI to peform the privileged operation using its own credentials (on the
client's behalf), then this itself would be a a serious security violation
by allowing an ordinary user to perform a privileged operation. I therefore
don't see how WMI eliminates security issues for the programmer. It might
simplify the housekeeping which is good and useful but you still need to
consider the security environment you're running in (since WMI will fail if
you access something you don't have permission for). This is no different
than when you roll your own code without WMI.
Just try this as non administrator,

Process [] procs= Process.GetProcesses();
foreach(Process pro in procs)
{
try {
IntPtr handle = pro.Handle;
}
catch( Exception ex){Console.WriteLine(ex);}
}
and watch all:
System.ComponentModel.Win32Exception: Access is denied
at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32
access, Boolean throw
IfExited)
thrown on you ...

This is exactly why so many programs run in the "administrators" account
these days, worse some have "SeDebugPrivilege" enabled, talking about a
surface attack.

Only administrators normally have SeDebugPrivilege by default though it's
not enabled by default (which is the reason you can't end another session's
process from the task manager for instance, even as an administrator). The
administrator can easily enable this privilege on-the-fly however. In fact,
if you do this using some utility for instance (which is easily written
yourself), you'll find that you can end another session's process from the
task manager. In any case, a rogue process that compromises the administor
account can do whatever it wants.so the SeDebugPrivilege is irrelevant
(since it can easily be enabled if required)
 
J

JamesB

JamesB said:
I am writing a service that monitors when a particular app is started.
Works, but I need to get the user who is currently logged in, and of
course Environment.UserName returns the service logon
(NT_AUTHORITY\SYSTEM).

I understand that when the service starts, no user may be logged in, but
that's ok, as the app I am monitoring can only be run by a logged in user.
Do I need to use WMI to get the user context of Explorer.exe or is there a
neater way?

James.

Many thanks for the replies - after following the advice here and doing a
bit more playing around, I seem to have got it working.
Seems I also kicked off an interesting debate as well, which I'll digest
when I have a bit of time, the various viewpoints are probably worthy of
checking out!
James
 
W

Willy Denoyette [MVP]

Larry Smith said:
That would be surprising considering that privileges can't be added to an
existing token since tokens are mostly immutable. There is no function
that does this. You need to add it to an existing account first and create
a new logon session. At least that's the way Windows security has always
worked assuming MSFT hasn't made any radical changes lately (which would
greatly surprise me in this area). Of course MSFT can always make their
own code do anything it wants but I don't see why they would breach their
own security.

Sorry, the above (...add the privilege ) is completely wrong, sure you
can't add privileges to a token, just forget about it, sorry for the
confusion.
There is nothing to fear, MSFT did not breach their own security. Basically,
what a "regular" client" running in a normal (non system logon session) can
do depends on:
1. His own token, if he specifies "Impersonation" when creating an instance
of a WMI class, then all he can do is specified by his own privileges. Note
that here the DCOM (RCP) rules, like authentication and authorization apply,
and the server will handle the request on a thread that has called
"CoImpersonateClient", no surprises here.
2, When using "identity" as impersonation level, the client request runs on
a thread that impersonates the WMI process token, per default, this is the
"Local Network" account token. However, other accounts are possible as well,
all depends on which account was specified when the "DCOM Launcher" (aka.
COM SCM) started the WMI service using CreateProcessAsUser. The DCOM
Launcher process runs in the TCB, and sometime you'll notice a WMI service
processes running as SYSTEM as well, but this is only to handle some OS or
Kernel space requests (WMI enabled drivers ).
3. And when using "Delegate" as impersonation token, WMI is able to
delegate, that is perform remote requests on behalf of the client he's
impersonating.

What a "non-regular user" client can do is a bit different, when running in
the debugger, I've seen threads running with higher privileges enabled than
those contained in the "Local Service" token. It looks like WMI using the
highly privileged token (duplicated) of the DCOM launcher to create a
restricted token when impersonating. So apparently, MSFT uses a backdoor, in
order to execute with elevated privileges without the need to launch a WMI
instance running as "SYSTEM".


An administrator can do anything it wants including accessing all handles.
It just has to enable the SeDebugPrivilege privilege in its own token.

And this is exactly my point. Using WMI, you don't need to run as
administrator (or with SeDebugPrivileges") enabled, to get at the process
handle. The process properties are stored in the WMI metabase at process
creation time by the OS loader (right, the OS is highly WMI aware). Once WMI
has the process handle he can query for the current properties (no special
privileges needed here).
Of course, some methods on the class needs specific privileges, for instance
a non admin client cannot kill processes other than those created by the
impersonating user.
I don't follow the other details however. If a program has the correct
privilege(s) to do something then it doesn't need to delegate it to
someone else. It can just do it on its own though it may have to enable a
given privilege first (a simple task). If by delegating however you mean
allowing WMI to peform the privileged operation using its own credentials
(on the client's behalf), then this itself would be a a serious security
violation by allowing an ordinary user to perform a privileged operation.
I therefore don't see how WMI eliminates security issues for the
programmer. It might simplify the housekeeping which is good and useful
but you still need to consider the security environment you're running in
(since WMI will fail if you access something you don't have permission
for). This is no different than when you roll your own code without WMI.
Just try this as non administrator,

Process [] procs= Process.GetProcesses();
foreach(Process pro in procs)
{
try {
IntPtr handle = pro.Handle;
}
catch( Exception ex){Console.WriteLine(ex);}
}
and watch all:
System.ComponentModel.Win32Exception: Access is denied
at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32
access, Boolean throw
IfExited)
thrown on you ...

This is exactly why so many programs run in the "administrators" account
these days, worse some have "SeDebugPrivilege" enabled, talking about a
surface attack.

Only administrators normally have SeDebugPrivilege by default though it's
not enabled by default (which is the reason you can't end another
session's process from the task manager for instance, even as an
administrator). The administrator can easily enable this privilege
on-the-fly however. In fact, if you do this using some utility for
instance (which is easily written yourself), you'll find that you can end
another session's process from the task manager. In any case, a rogue
process that compromises the administor account can do whatever it
wants.so the SeDebugPrivilege is irrelevant (since it can easily be
enabled if required)

Again this is the whole point, this requires the process to run with
elevated privileges. Go back at the sample above (C# code) You can't
enumerate the running processes to get the handles when not running as
administrator (SeDebugPrivileges needed to get the handle), but you need the
handle to call "OpenProcessToken" as per Nicholas suggestion. The result of
this is that many application run as "administrator" or with
"SeDebugPrivileges" (wrong wrong) and the developers/users are surprised
when their application fails when moving to Vista. Keep in mind that the
Framework does NOT offer the possibility to "enable" privileges, so here
again you have to adjust the token privileges using a PInvoke call.
There are many other samples I can give that are nicely solved by delegating
to WMI, because WMI is based on a database (the metabase) that stores a lot
of information you can't directly obtain without running with elevated
privileges when calling Win32 API's.
Look back at the code I initially posted (which requires XP or higher), no
special privileges needed no single PInvoke call - problem solved, try to
implement the same using Win32 API calls without the need to run with
elevated privileges.

Willy.
 
L

Larry Smith

In all honesty your explanation of the situation is very puzzling. If I
undserstand what you're saying then my contention is that WMI is providing
access to something that non-admin users don't normally have access to. If a
regular user tries to access another logon session's handle via
"OpenProcess()" then it will fail because they don't have "SeDebugPrivilege"
in their token. Based on what you've described however, WMI *will* provide
access to the same (or related) information by specifying "identity" as the
impersonation level (which apparently is something different than
"SecurityIdentification" in the WinAPI - see here
http://msdn2.microsoft.com/en-us/library/aa379572.aspx). My question then is
why? There's a dual and conflicting system of security here. Either MSFT
considers it safe for a normal user to access another logon session's
process or they don't. It makes no sense to say you're not allowed to do
this using "OpenProcess()" because you lack a required privilege but OTOH
(wink, wink) just use WMI as a (wide-open) backdoor. If so then why isn't
this privilege simply removed as a prerequisite for calling "OpenProces()"
in the first place. Perhaps it's for backwards compatibility reasons but
obviously it's not a security issue anymore (according to MSFT). In fact,
your contention that WMI is much easier and safer because users don't need
to run with these elevated privileges (for some things) doesn't apply in an
environment where those privileges *are* needed. Therefore, it's not only
*not* a problem to have them, but it's an intrinsic requirement though it
should be kept to a minimum of course (where access is always govenred on a
need-to-know basis). In our on-going example then if you really don't need
these privileges then sure, don't grant user rights that they don't need.
Again however, why does "OpenProcess()" say that you *do* need them.
Finally, as for DCOM, this is the distrbuted component of the COM SCM.
They're not the same so I don't see why it even comes into the picture
unless a remote call is required (and even then why is DCOM used given its
notorious configuration problems and issues with firewalls). My experience
with WMI is limited so I can't really comment on its particular security
requirements. After considering what you've said however coupled with a
quick scan of links such as
http://msdn2.microsoft.com/En-US/library/aa390428.aspx and
http://msdn2.microsoft.com/En-US/library/aa389290.aspx, I maintain it's not
as simple as you would have me believe (from a security perspective anyway).
I think I'll put the issue to rest now however but will read any final
follow-up you might want to provide :)
 
B

Ben Voigt [C++ MVP]

Larry Smith said:
In all honesty your explanation of the situation is very puzzling. If I
undserstand what you're saying then my contention is that WMI is providing
access to something that non-admin users don't normally have access to. If
a regular user tries to access another logon session's handle via
"OpenProcess()" then it will fail because they don't have
"SeDebugPrivilege" in their token. Based on what you've described however,
WMI *will* provide access to the same (or related) information by
specifying "identity" as the impersonation level (which apparently is
something different than "SecurityIdentification" in the WinAPI - see here
http://msdn2.microsoft.com/en-us/library/aa379572.aspx). My question then
is why? There's a dual and conflicting system of security here. Either
MSFT considers it safe for a normal user to access another logon session's
process or they don't. It makes no sense to say you're not allowed to do
this using "OpenProcess()" because you lack a required privilege but OTOH
(wink, wink) just use WMI as a (wide-open) backdoor. If so then why isn't

I believe that OpenProcess() requires different permissions depending on the
required level of access, and the .NET Process.Handle request
PROCESS_ALL_ACCESS or whatever that constant is, and therefore fails,
whereas calling OpenProcess directly would be allowed.

To get the user owning a process, I think only PROCESS_QUERY_INFO (again,
possibly mangled the name slightly) would be required, and it should be
equally possible with or without WMI.
 
B

Ben Voigt [C++ MVP]

Tell me what do you call low-level services then, what makes you think
that native code services are more low level than .NET services, for the
SCM they are exactly the same , at run-time all there is executed is
native code, point.
What makes you think that .NET services are that much slower than native
C++ services, they are performing largely at the same level, with only a
slight advantage for native C++ in some special cases, but that's not
important for a Service anyway, services are not the applications that
consume a lot of CPU or other resources, question is do they perform at an
acceptable level, and here the answer is YES in most cases.

The .NET GC is optimized for user-interactivity (either with mouse/keyboard
or over network). It significantly delays freeing memory to gain
performance, and this is only appropriate for an active request. For a
background service to allocate hundreds of megabytes of memory more than it
needs would be rather poor.
 
W

Willy Denoyette [MVP]

Larry Smith said:
In all honesty your explanation of the situation is very puzzling. If I
undserstand what you're saying then my contention is that WMI is providing
access to something that non-admin users don't normally have access to. If
a regular user tries to access another logon session's handle via
"OpenProcess()" then it will fail because they don't have
"SeDebugPrivilege" in their token. Based on what you've described however,
WMI *will* provide access to the same (or related) information by
specifying "identity" as the impersonation level (which apparently is
something different than "SecurityIdentification" in the WinAPI - see here
http://msdn2.microsoft.com/en-us/library/aa379572.aspx). My question then
is why?
I know, WMI is a complex distributed architecture.
Talking about processes, WMI does give access to process INFO, that doesn't
mean that you are also allowed to perform all possible actions on the
process object.
WMI is a provider/consumer based architecture. One of the most important
providers is CIMWIN32 (WMI's root\cimv2 namespace), a number of system
components do load provider components (COM DLL's), or do keep dynamic
structured info for the providers to be picked-up when needed (through
shared memory segments), this complex structure forms the cimwin32
provider. Each provider is also registered with WBEM (which is WMI) which
keeps a repository describing the providers features (classes properties
etc) , and WMI keeps also static and semi-dynamic instance data in this
store, this sore plus the dynamic instance data held by the components is
what is called the metabase. You can check the repository is
%Windir%\system32\wbem\repository.

There are different provider types, like there are instance providers,
method providers, event providers etc.
When we talk about Process info we are talking about the Win32_process class
"instance" provider, a consumer can ask about the state of a specific
process by means of a WQL query.
Say a consumer needs the status of a process with PID = 123, for this he
issues a query like :
Select * from WIn32_Process where processid=123 ,
this one is passed to WMI, WMI authenticates and performs an access check to
see whether the caller is allowed to "read" properties from this namespace
class (subject of WMI's security settings). When this check succeeds, he
loads the provider for the Process class (that is cimwin32 in root\cimv2),
if not already loaded, and passes the query to the provider. One step
performed by the provider in this case is a call to "OpenProcess" passing
the pid requested as argument. When the thread has no "SeDebugPrivilege" in
its token, the call will fail and the provider will pick-up the data
provided by the system component, in case of the above query this is the
handle value of the corresponding process. Note I said the "handle value",
which is nothing special as the handle value is the same as the PID and is
nothing else than an index in the process handle table. The caller cannot do
anything with this handle value, security is not compromised. With this
handle value as key, WMI picks the instance from the dynamic data blob
provided by the system component, this structured data blob is precisely
described in the repository and is returned to the consumer as instance data
for the process with PI=123.
You can check this process yourself by means of the wbemtest utility, run it
as non admin and do some experiments.
Now, the Win32_process class has also an associated method provider, and
this one implements methods like Create, Terminate, AttachDebugger etc..
Say that a consumer wants' to terminate a process, to do this he has to get
the instance like above and when done he has to execute a method on the
class (Win32_Process) of this instance. In this case WMI will perform an
access check to see whether the consumer is allowed to execute methods on
this namespace class, when it's the case, he will call the "Terminate"
method of the provider (remember providers are COM servers), the Terminate
method will call Win32 TerminateProcess as part of it's implementation and
when when the issuer (that is the impersonator) is allowed to kill the
process the API will succeed, else the API fails.
So in case the client had specified impersonate when connecting, the
provider will execute on a thread that impersonates the consumer and the
call will succeed for all process owned by this caller, all others will
fail. If the caller is an "administrator" he can do pretty much what he
likes, if he's a standard user he can only do what a standard user can do,
no security is compromised.
If the caller sets "identity" when connecting, he can pretty much do
nothing, as the thread will now impersonate "Local Service" and this one is
not allowed to execute any method.
There is a lot more to tell about this, the above is only a small fraction
of the total picture, just experiment yourself, run wbemtest, look at the
processes using tools like "processexplorer", attach a debugger to the WMI
hosting process, look at the providers getting loaded, check the executing
threads tokens and set breakpoints on critical API's you want to trace. This
will take some time, but if you are interested you will sure understand how
things fit together. Take also special notice of the DLL's loaded in several
service process (you'll see a lot of the load wbemcore.dll), also take note
of the shared memory segments like there are:
\BaseNamedObjects\__ComCatalogCache__
and the events like:
\BaseNamedObjects\EVENT_READYROOT/CIMV2PROVIDERSUBSYSTEM

these form the channels over which WMI communicates with the system
components.
Watch the WMI hosting process getting active and getting turned of (DCOM
lifecycle management comes into play here).

There's a dual and conflicting system of security here. Either MSFT
considers it safe for a normal user to access another logon session's
process or they don't. It makes no sense to say you're not allowed to do
this using "OpenProcess()" because you lack a required privilege but OTOH
(wink, wink) just use WMI as a (wide-open) backdoor. If so then why isn't
this privilege simply removed as a prerequisite for calling "OpenProces()"
in the first place.

See above, WMI does not pass a usable handle back to the consumer, only an
handle value, which you can even guess as it's the same as the PID.
Also keep in mind that you can't use an arbitraty handle across process
boundaries, unless the owner pushes the handle in your process handle table
by means of a DuplicateHandle call.


Perhaps it's for backwards compatibility reasons but
obviously it's not a security issue anymore (according to MSFT). In fact,
your contention that WMI is much easier and safer because users don't need
to run with these elevated privileges (for some things) doesn't apply in
an environment where those privileges *are* needed. Therefore, it's not
only *not* a problem to have them, but it's an intrinsic requirement
though it should be kept to a minimum of course (where access is always
govenred on a need-to-know basis). In our on-going example then if you
really don't need these privileges then sure, don't grant user rights that
they don't need. Again however, why does "OpenProcess()" say that you *do*
need them.

"OpenProcess" is the oldest API that exists in WIN32, it's also what I call
a "gateway "API, if you can call it to get a process handle, you can use
that handle without needing any further access checks. Why it requires
"SeDebugPrivileges" is because it was supposed to be called from Debuggers
only (and administrators and the TCB). But there is nothing inherently
dangerous about calling OpenProcess to get an handle, what should have been
protected is what you do with this handle, but MSFT choosed to protect the
root of all the API's that needed a process handle, so they did not need to
enter the kernel each time a handle was passed in another API (obviously for
performance reasons). This is much like there is done at the Filesystem
level, here access checks are only done when you open a file, no further
checks are done when you access the file!!

Pre-XP requires a caller to run in the TCB in order to call LogonUser, lucky
for us all MSFT has lifted this requirement as from XP on.
I'm pretty sure they cannot lift this requirement on "OpenProcess" without
breaking a lot of code, and without the need to change a lot of their own
API's.


Finally, as for DCOM, this is the distrbuted component of the COM SCM.
They're not the same so I don't see why it even comes into the picture

DCOM is a location independent IPC mechanims which can be used
"cross-process, local system" and "cross-process, remote systems". What we
are talking here (what the OP was talking about) is "cross-process, local
system". local DCOM uses shared memory as RPC channel, also called LRPC,
this is an highly optimized IPC mechanism. There ar no security mechanisms
involved no network components are used, thisngs get completely different
when talking cross machine. Note, however, that WMI can also ise COM, that
is it can load providers in-process of the consumer, VISTA and Windows 2008
provide more of these providers, but this is FAR beyond the scope of this NG
and thread.
unless a remote call is required (and even then why is DCOM used given its
notorious configuration problems and issues with firewalls). My experience
with WMI is limited so I can't really comment on its particular security
requirements. After considering what you've said however coupled with a
quick scan of links such as
http://msdn2.microsoft.com/En-US/library/aa390428.aspx and
http://msdn2.microsoft.com/En-US/library/aa389290.aspx, I maintain it's
not as simple as you would have me believe (from a security perspective
anyway). I think I'll put the issue to rest now however but will read any
final follow-up you might want to provide :)

I never said it was simple, basically it's simple, but it can get pretty
complex, as long as you are talking about local server/client connections
(cross-process same machine) over DCOM, there is no issue with firewalls, if
you are talking about cross machine DCOM then there are. This is the case
with all distributed systems, all of hem are using the network so all of
them are confronted with firewalls these days. Note also that WMI is about
enterprise management, it's not something you will use at home.


Willy.
 
W

Willy Denoyette [MVP]

Ben Voigt said:
The .NET GC is optimized for user-interactivity (either with
mouse/keyboard or over network). It significantly delays freeing memory
to gain performance, and this is only appropriate for an active request.
For a background service to allocate hundreds of megabytes of memory more
than it needs would be rather poor.

Not true, there are different modes of GC, there is the server GC and there
is the workstation GC, the upcoming version of the CLR will allow you to
further tune the GC behavior, it will be possible to delay the GC until the
process is ready to take the hit. Note that when I read the above that I
have to assume that you think you can't write Web services and Remoting
services using .NET either! IIS 's worker processes that load .NET web
applications and Webservices are just services right! Grab a copy of Vista
or Longhorn and watch, WCF endpoints are hosted in a "managed code" service,
more will come in the picture when the product matures, and a lot more will
come with the next version of the OS ;-)
Note that I'm still trying to prove myself that .NET cannot be used for
certain scenarios, I have quite a list of NO NO's, like stay away from
kernel space (Drivers etc), stay away from the Explorer shell (add-ins),
don't use it to mimic COM components like Active X, stay away from
multimedia stuff that requires nearly real-time responses, don't use managed
code when memory footprint is really a concern, but "generic application
services" implemented as Windows Services are not one of them.
Note, that you should be careful when implementing a service, be it in
native code or managed code, and like I've said before this my real concern
with .NET, some people think that because it's easy with .NET to implement
Windows Services, that they must implement a lot as a service. I've seen
people using .NET Windows Service just to kick-off batch processes at
several intervals ( once per day, per week you name it), jeez what a waste
of resources, but years ago I've noticed the same when ATL Service templates
became made available for the C++ community.

Note also that the GC out-performs the native memory manager in most cases.
But don't let us start this old discussion again.


Willy.
 
W

Willy Denoyette [MVP]

Ben Voigt said:
I believe that OpenProcess() requires different permissions depending on
the required level of access, and the .NET Process.Handle request
PROCESS_ALL_ACCESS or whatever that constant is, and therefore fails,
whereas calling OpenProcess directly would be allowed.

To get the user owning a process, I think only PROCESS_QUERY_INFO (again,
possibly mangled the name slightly) would be required, and it should be
equally possible with or without WMI.



True, but this is not the case here, WMI does not call OpenProcess with
PROCESS_QUERY_INFO, convince yourself, attach a debugger to the WMI process
and set a breakpoint on kernel32!openprocess, issue a "select * from
win32_process" from a WMI client and you see that the dwDesiredAccess is not
PROCESS_QUERY_INFO, notice that the call fails with an HR=0xc0000022 which
will get translated into a "dos" error 5 (access denied), when the base
client is not an admin.
Now, WMI does not need the "handle" to interrogate the process properties,
he doesn't need to get the process token, he can get all relevant info
directly from the System (notably from the "process manager "in ntdll.dll,
which is WMI aware), only thing is that it might be a bit slower than using
the "normal Win32 API's".
The process manager stores the info about the running processes in a list,
that is mapped on a shared memory segment. This list holds all properties as
defined in the WMI schema for the Win32_Process class., and it's that blob
of data that gets translated by the WMI provider into Win32_ process
instance data.
The process manager is also an event source, signaling events like "Process
creation", "Process deletion", "Thread Creation" etc... to registered event
handlers (notably the WMI event providers). The eventing architecture is
implementation dependent, and most of it's functionality is only available
on XP and higher. On W2K (with limited functionality) and XP the event
system is WPP based, while W2K3 and up uses ETW as an high speed eventing
architecture. On Vista and Longhorn everything is ETW based.
So, if you go back to my original reply to the OP, where I said that he
should use "Win32_ProcessStartTrace" to get at the process identity, is
because this is the fastest way to get at the process owner, the process
manager fires an event and the eventhandler gets all properties he needs,
just with a few lines of C# code, mission accomplished.

Willy.
 
W

Willy Denoyette [MVP]

Willy Denoyette said:
True, but this is not the case here, WMI does not call OpenProcess with
PROCESS_QUERY_INFO, convince yourself, attach a debugger to the WMI
process and set a breakpoint on kernel32!openprocess, issue a "select *
from win32_process" from a WMI client and you see that the dwDesiredAccess
is not PROCESS_QUERY_INFO, notice that the call fails with an
HR=0xc0000022 which will get translated into a "dos" error 5 (access
denied), when the base client is not an admin.
Now, WMI does not need the "handle" to interrogate the process properties,
he doesn't need to get the process token, he can get all relevant info
directly from the System (notably from the "process manager "in ntdll.dll,
which is WMI aware), only thing is that it might be a bit slower than
using the "normal Win32 API's".
The process manager stores the info about the running processes in a list,
that is mapped on a shared memory segment. This list holds all properties
as defined in the WMI schema for the Win32_Process class., and it's that
blob of data that gets translated by the WMI provider into Win32_ process
instance data.
The process manager is also an event source, signaling events like
"Process creation", "Process deletion", "Thread Creation" etc... to
registered event handlers (notably the WMI event providers). The eventing
architecture is implementation dependent, and most of it's functionality
is only available on XP and higher. On W2K (with limited functionality)
and XP the event system is WPP based, while W2K3 and up uses ETW as an
high speed eventing architecture. On Vista and Longhorn everything is ETW
based.
So, if you go back to my original reply to the OP, where I said that he
should use "Win32_ProcessStartTrace" to get at the process identity, is
because this is the fastest way to get at the process owner, the process
manager fires an event and the eventhandler gets all properties he needs,
just with a few lines of C# code, mission accomplished.


Oh, forgot to add that PROCESS_QUERY_INFORMATION is only able to Open
Processes running in the same logon session.

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top