Prev: Mirror Driver Architecture
Next: LowLevelHooksTimeout?
From: Pavel Lebedinsky [MSFT] on 8 Mar 2006 02:55 "Stefan Kuhr" wrote: >> Impersonating a client does not automatically give you the full >> token. You need to initiate elevation from the client side. > > And that automatically involves the consent-UI beforehand, right? There > really is no way to get the full token of a consent admin without an > intermediate invocation of consent.exe? I don't really know the details but it appears that you can either run an app that has a manifest requesting elevation, or use CoCreateInstanceAsAdmin. The point is that UAP is designed to put the user in control. If the user does not want to elevate, there's nothing your service can do about this. (Of course, since you're running as LocalSystem, you can technically do anything, and there's probably some unsupported way get the user's full token, but it is assumed that well-behaved services won't do this). By the way, why do you need to impersonate an admin? Since you run as system, you already have administrator privileges in your service. > If so, is there a way to make another administrator a non-consent-admin > like the first administrator user that is auto-generated during > installation (which apparently needs no consent ui)? BUILTIN\Administrator is the only account that always runs elevated. Other members of Administrators group get a limited token when they log on. -- This posting is provided "AS IS" with no warranties, and confers no rights.
From: Skywing on 9 Mar 2006 00:14 IIRC, any privileges that are in the token but not enabled get stripped away across impersonation boundaries, so - you might try turning on all privileges present before the security context is captured by impersonating, transmitting the "real" privilege state with an RPC message or whatnot, then restoring the original privilege state on the impersonating end when you get the appropriate message. (Note that I don't really know if this will do what you need to do in Vista -- however I have succcessfully used techniques similar to this to get the "important" parts of the token saved across an impersonation boundary in <=Windows Server 2003. So it's probably worth a shot, at least.) "Stefan Kuhr" <kustt110(a)gmx.li> wrote in message news:440C4A01.E31D0B85(a)gmx.li... > Hello everyone, > > I want a service running on Vista as LocalSystem to act like the > elevated administrator by impersonating the client, which is an > administrator running with the restricted token of a normal > administrator on Vista. > > I followed the guidelines laid out in the section "Summary of Choices > for Designing Administrative Applications"-"The Back-End Service Model" > of the following document: > > http://msdn.microsoft.com/windowsvista/default.aspx?pull=/library/en-us/dnlong/html/AccProtVista.asp > > I created a Service running as LocalSystem, that exposes an RPC > interface via LRPC to which a client app, marked with > "requestedExecutionLevel" to be "asInvoker", then makes an Rpc call. > However, when the server code impersonates the client, the token that > the thread now uses is still the same restricted token that the client > has. In one of the Vista Ascend Training classes that I attended, I was > told that the service, when it impersonates the client, will receive the > full token part of the client's split token, not the restricted token. > What am I doing wrong? > > My code in the server part roughly looks like so and it runs without > problems in an XP environment: > > /* [fault_status][comm_status] */ error_status_t StartCommandShell( > /* [in] */ handle_t Binding) > { > if(!Binding) > return ERROR_INVALID_PARAMETER; > > DWORD dwResult = RpcImpersonateClient(Binding); > if(ERROR_SUCCESS!=dwResult) > return dwResult; > > HANDLE hClientImpToken = NULL; > > if(!OpenThreadToken(GetCurrentThread(), > TOKEN_READ|TOKEN_IMPERSONATE|TOKEN_DUPLICATE /*TOKEN_QUERY*/, TRUE, > &hClientImpToken)) > { > DWORD dwLastErr = GetLastError(); > VERIFY(ERROR_SUCCESS==RpcRevertToSelf()); > return dwLastErr; > } > > VERIFY(ERROR_SUCCESS==RpcRevertToSelf()); > > HANDLE hPrimaryToken = NULL; > > > if(!DuplicateTokenEx(hClientImpToken, TOKEN_ALL_ACCESS, NULL, > SecurityImpersonation, TokenPrimary, &hPrimaryToken)) > { > DWORD dwLastErr = GetLastError(); > VERIFY(CloseHandle(hClientImpToken)); > return dwLastErr; > } > > VERIFY(CloseHandle(hClientImpToken)); > ASSERT(hPrimaryToken); > > /// > /// now we have the client's token as a primary token, ready for CPAU > /// > PROCESS_INFORMATION pi; > STARTUPINFO si; > ZeroMemory(&si, sizeof(STARTUPINFO)); > si.cb = sizeof(STARTUPINFO); > si.dwFlags = STARTF_USESHOWWINDOW; > si.wShowWindow = SW_SHOW; > si.lpDesktop = CSTR2STR(_T("winsta0\\default")); > > if (!CreateProcessAsUser(hPrimaryToken, NULL, CSTR2STR(_T("cmd.exe")), > NULL, NULL, FALSE, > CREATE_NEW_CONSOLE|NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) > dwResult = GetLastError(); > else > { > VERIFY(CloseHandle(pi.hProcess)); > VERIFY(CloseHandle(pi.hThread)); > } > VERIFY(CloseHandle(hPrimaryToken)); > > return dwResult; > } > > > Any help appreciated. Ivan? > > -- > Stefan
From: Stefan Kuhr on 9 Mar 2006 06:33 Hi Skywing, Skywing wrote: > > IIRC, any privileges that are in the token but not enabled get stripped away > across impersonation boundaries, so - you might try turning on all > privileges present before the security context is captured by impersonating, > transmitting the "real" privilege state with an RPC message or whatnot, then > restoring the original privilege state on the impersonating end when you get > the appropriate message. > > (Note that I don't really know if this will do what you need to do in > Vista -- however I have succcessfully used techniques similar to this to get > the "important" parts of the token saved across an impersonation boundary in > <=Windows Server 2003. So it's probably worth a shot, at least.) > I am aware of the fact that those privileges that the client process has not explicitely enabled before making the RPC are stripped from the token that the impersonator gets. Actually, my test client tries to enable all poossible privileges. However, privileges are not the primary problem with admin elevation on Vista. The restricted token of a non-elevated administrator manifests itself first and foremost in the group sid of builtin\administrators being SE_GROUP_USE_FOR_DENY_ONLY (it is SE_GROUP_OWNER in a full token) and two new SIDs of type label (which apparently is not yet documented). These two label SIDs can successfully be elevated to the values in a full admin token using SetTokenInformation(..., TokenIntegrityLevel...) and (obviously) well-known SID using the approach outlined here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ProtectedMode.asp but the group SID for builtin\administrators with SE_GROUP_USE_FOR_DENY_ONLY cannot be replaced because SetTokenInformation(..., TokenGroups, ) won't succeed (if that would work, any service running as LocalSystem could masquerade as any user). Anyway, thanks for helping. -- Stefan
From: Stefan Kuhr on 9 Mar 2006 06:57 Hi Pavel, "Pavel Lebedinsky [MSFT]" wrote: > > "Stefan Kuhr" wrote: > > >> Impersonating a client does not automatically give you the full > >> token. You need to initiate elevation from the client side. > > > > And that automatically involves the consent-UI beforehand, right? There > > really is no way to get the full token of a consent admin without an > > intermediate invocation of consent.exe? > > I don't really know the details but it appears that you can either > run an app that has a manifest requesting elevation, or use > CoCreateInstanceAsAdmin. And as far as I can see, both variants require the consent UI. > > > By the way, why do you need to impersonate an admin? > Since you run as system, you already have administrator > privileges in your service. Good point. I have to elaborate a bit: We have a script language that has a script command named "RunAs" which works like the command line app runas. The point is, that on Vista, interactive tokens created by the secondary logon are restricted tokens as well. Our customers expect that they can use this runas command and pass it credentials of a local admin (which usually is a domain user and thus a consent admin) and get privileged things done on the otherwise unprivileged desktop of a normal user. Please let us not talk about how insecure this all might be or how we store passwords and so on, it is just the state of affairs right now. If now this runas command only creates a restricted token of an admin, probably most of the time the privileged actions that our customers want to perform won't work anymore. So my idea was to create an intermediate process of ours first, which then talks to our service via RPC to create the process that the customer wants to run as the full admin. Another point where we would need similar functionality is the usage of the UpdateDriverForPlugAndPlayDevices API which requires full administrative privileges but also desktop interaction in order for installation of unsigned drivers (and IIRC also drivers with CoInstallers that have UI) to succeed. In this case we also need a privileged process with a full token, not running within some private winsta\desktop of a non-interactive service but instead on a non-privileged user's desktop. This will not work anymore with Vista's implementation of CreateProcessWithLogonW. -- Stefan
From: Pavel Lebedinsky [MSFT] on 10 Mar 2006 05:57
I might be wrong, but I suspect that there is no supported way to launch an elevated app without going through consent UI, and this is probably by design. You can try asking this question in the UAC team blog: http://blogs.msdn.com/uac/default.aspx -- This posting is provided "AS IS" with no warranties, and confers no rights. "Stefan Kuhr" wrote: > In this case we also need a > privileged process with a full token, not running within some private > winsta\desktop of a non-interactive service but instead on a > non-privileged user's desktop. This will not work anymore with Vista's > implementation of CreateProcessWithLogonW. |