Reputation: 4416
Here is the scenario:
1. The app is already running as a local admin
2. It impersonates as a domain account, which is also an admin on the local box
3. While impersonated, the app is trying to create a regkey under the key that has Full Control to the Administrators group for "This key and subkeys."
This step fails with UnauthorizedException "Access to registry key .." is denied. Now, if I explicitly ACL the regkey for the domain user, the creation of the regkey goes through. But then this solution defeats the purpose of being in the admin group.
Any ideas what could go wrong here?
EDIT: I'm running on Windows Server 2008 R2. I figured this issue is due to UAC enabled. LogonUser method returns a restricted token, which does not have elevated access to the registry. Any ideas on how to get an elevated access using LogonUser method?
Here is how I call it:
IntPtr token = IntPtr.Zero;
LogonUser(username, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, out token)
Upvotes: 2
Views: 2682
Reputation: 69
I will suggest several things to check:
You should attribute your class (that executes impersonation) for a full trust mode request, which you can do using
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
Also, you should import "advapi32.dll" and LogonUser to be used later.
Within this you should be calling it like this (*using LOGON32_LOGON_INTERACTIVE since BATCH will not work*)
LogonUser(userName, domainName, password, 2, 0, out safeTokenHandle);
After getting a handle, you should use it to perform any action:
WindowsIdentity impid = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
After getting it, encapsulate your actions:
using (WindowsImpersonationContext imp = impid.Impersonate())
{
// myActions
}
This should enable you to do it correctly and detect how it went.
I have now tried to do this in an ASP.NET application and succeded. Here is a working code for an MVC application controller:
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Web.Mvc;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
namespace StackOimpersonationExample.Controllers
{
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class HomeController : Controller
{
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out TokenHandle phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public ActionResult Index()
{
ViewBag.Message = "This line contains status info.";
#region ImpersonateTestUserAndWriteToRegistry
try
{
const string domainName = "W8CP";
const string userName = "testadmin";
const string password = "sxt";
TokenHandle tokenHandle;
bool returnValue = LogonUser(userName, domainName, password, 2, 0, out tokenHandle);
if (returnValue == false)
{
int retVal = Marshal.GetLastWin32Error();
ViewBag.Message = String.Format("Failed logon: {0}", retVal);
throw new System.ComponentModel.Win32Exception(retVal);
}
using (tokenHandle)
{
ViewBag.Message = "Logon successful!";
var newId = new WindowsIdentity(tokenHandle.DangerousGetHandle());
using (newId.Impersonate())
{
RegistryKey parentKey = Registry.LocalMachine;
RegistryKey softwareKey = parentKey.OpenSubKey("SOFTWARE", true);
if (softwareKey != null)
{
RegistryKey subKey = softwareKey.CreateSubKey("StackAnswer");
subKey.SetValue("CreatedAs", WindowsIdentity.GetCurrent().Name, RegistryValueKind.String);
subKey.SetValue("Website", "http://codecentral.org", RegistryValueKind.String);
subKey.SetValue("Email", "[email protected]", RegistryValueKind.String);
}
}
}
}
catch (Exception ex)
{
ViewBag.Message += String.Format(" Exception: " + ex.Message);
}
#endregion
return View();
}
}
public sealed class TokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private TokenHandle(): base(true){}
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
}
Upvotes: 2