security exception accessing registry when the program runs as scheduled task - c#

the following small line throws a System.Security.SecurityException: Requested registry access is not allowed:
RegistryKey _key = HKLM.OpenSubKey("path\\to\\my settings", false);
Now.. what's the point some would ask? The point is that this runs ONLY when I am logged on. The exception is thrown if the program runs as scheduled task and nobody is logged on.
the user who runs that task is local administrator
the program does not run from a network share, it is located on the local disk
I even tried setting Code Access Security
the user has the rights to log on as a batch job
I have XP SP3 with all patches applied. The program is written in C# .Net 2.0 (tested 3.5 too)
Does anyone know whats the point here?
Torsten
EDIT: see http://gist.github.com/638576

Mhhhh...it seems related to Authorization problem too. Have you tried to use the API: OpenSubKey(...., RegistryKeyPermissionCheck) to see if something change? I guess it could be related to parent key and its authorization.
Try to see: http://msdn.microsoft.com/it-it/library/microsoft.win32.registrykeypermissioncheck.aspx (in your language). I hope it could help you...

Can you adapt this
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
string isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator) ? "Yes" : "No";
to check that the process really is successfully impersonating when there's no current user?

It seems that this is a problem of this specific computer. I tested it on another workstation and it works even without administrator privileges.
I assumed this - the program did run for years without any problems... Anyway, thanks to all!

Related

C# EventLog.Delete Access Denied

I have read other questions on SO in regards to security and registry keys, nothing has helped me solve my particular use case scenario.
Here's my scenario:
What I'm Trying To Do
I want to, in code, delete a windows event log.
The Problem
When executing the function, I receive a System.ComponentModel.Win32Exception. The exception message is "Access is denied".
How I Am Doing It Currently
I am using an impersonator function that I wrote which wraps around the EventLog.Delete function, it drops me into a user context that has full access to the EventLog Registry Hive. Subsequently the logs I am interested in also have full access for this particular user.
My Question
Why do I receive a "Access Is Denied" if the user I am running under (through impersonation) has full access to the log in question? I've tested my Impersonation function and it works as expected for other code I've written. I don't get why I would get access denied for this.
In another scenario with my impersonation function it works just fine, for example if I tried to write to a file that the user context that is running the program does not have write access to, then I would not be able to write to the text file, however if I use my impersonation to drop into a user context that does have write access then it works just fine (I can write to the file). So I just don't understand why the same concept can't be applied to registry keys.
What am I missing here?
The Code
Exception Message
My Test
Where sw-test is a user I created for testing purposes, it has full access permissions to the registry we are trying to delete.
[TestMethod]
public void DeleteEventLog_ValidatedUser_DeleteLog()
{
using (new Impersonator(Environment.UserDomainName, "sw-test", "pswd"))
{
Logging logging = new Logging();
logging.DeleteEventLog("testLog");
}
}
Okay I eventually got around to figuring this out, there were two issues at play here that were causing the mentioned exception being thrown, they are as follows:
1. Visual Studio was NOT running in administrator mode.
Not running visual studio in administrator mode was one part of the problem, this seems to be associated with access tokens in the windows OS. According to a source I read, if I run a program without UAC on (which is my scenario, I have it off), then the program being run gets a copy of my access token. However if I have UAC enabled, the program gets a copy of my access token but it is a restricted access token. (see: What precisely does 'Run as administrator' do?) - To be honest this doesn't really make sense in my case, why do I have to run as admin if I have UAC off? Shouldn't visual studio have an unrestricted copy of my access token? I am in the administrator group with UAC off...
2. Not Specifying NewCredentials As a Logon32Type In Impersonation
I don't really understand it but as soon as I specified this for my impersonation everything started working perfectly, I read a blog about it, it talks about how it was introduced in the VISTA days and how it was mainly used to specify credentials to outbound network connections to servers, and was mainly used to remedy security-related issues server-side. Don't see how it correlates to interfacing with local event logs though. (see: https://blogs.msdn.microsoft.com/winsdk/2015/08/25/logonuser-logon32_logon_new_credentials-what-is-this-flag-used-for/)
Code
using (new Impersonator(Environment.UserDomainName, "sw-test", "pswd", Advapi32.Logon32Type.NewCredentials))
{
EventLog.CreateEventSource("testSource", "testLog");
EventLog.Delete("testLog");
}
Where the NewCredentials is an int 9

Find out if another application is running as admin

I'm trying to determine if another application is running as an administrator. There are 100's of SO questions about finding if your application is or not, but not for another application.
If I do var processes = Process.GetProcesses(); and loop through them, they don't appear to have any "Elevated" or "IsAdministrator" properties on them. I also found a function on here to get the Owner but they all come back as "My-Laptop\Me" so that's not working for me the way I hoped it would.
Is there a way to find this? I'm on Win 8.1 and would prefer something that works for 7 as well, but if it only works for 8.1+ that's totally fine.
Thanks!
EDIT:
My application has to run as an administrator.
You can use the technique from this answer, just replace Process.GetCurrentProcess().Handle with the Process.Handle of the other process.
If you look at the code (there's quite a bit of code there) it get the process "user token" (the permissions the process is running under) and checks if this token has the administrator role or not,
Assuming your process is not running as administrator, trying to get information about a process that is elevated via UAC (such as its MainWindowTitle) will throw an AccessDenied exception, where a non-elevated process will permit you access to that information. This assumes you also verify the owner of the process to check that it's you.
try
{
var foo = process.MainWindowTitle;
return false; //Process is not elevated
}
catch (Win32Exception ex)
{
return true; //Process is elevated if ex error code is AccessDenied
}

Writing to registry local machine error

I want set default icon of some extension by C#. But this gives me error -> Security Exception was unhandled
RegistryKey FileExt = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes", RegistryKeyPermissionCheck.ReadWriteSubTree);
How can I do that?
try to run your application as administrator.
Maybe the user you are using to log in on the machine does not have privileged to access or modify the registry. try run the code with administrator account and see what happens. also if there is no user logged in the same error maybe occurs for instance check this.
I presume this is on Windows Vista or 7.
You may need to have elevated privileges to change some values in the registry. Even a user with administrative privileges will get the UAC pop up to ask permission before a program can do this.
Have a look at a question about this.
Here is a codeproject article about gaining elevated privileges.
try this method instead of yours:
public RegistryKey OpenSubKey(
string name,
bool writable
)
Maybe a true is enough ;-)
Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes", true);

Disabling Task manager using c# in OS Hardened machine

I am using the below code to disable the task manager for a kiosk application which works perfectly
public void DisableTaskManager()
{
RegistryKey regkey;
string keyValueInt = "1";
string subKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
try
{
regkey = Registry.CurrentUser.CreateSubKey(subKey);
regkey.SetValue("DisableTaskMgr", keyValueInt);
regkey.Close();
}
catch (Exception ex)
{
MessageBox.Show("DisableTaskManager" + ex.ToString());
}
}
But when i run this in OS hardened machine i get the following error,
DisableTaskManagerSystem.UnauthorizedAccessException:
Access to the registry key 'HKey_Current_User\Software\Mictrosoft\Windows\CurrentVersion\Policies\System' is denied.
at Microsoft.win32.RegistryKey.win32Error(int32 errorcode, String str)
How can i overcome this ? I need to do this for a Kiosk application.
take a look at this, im not yet a good enough C# Developer to comment but i know that during my work with other developers they came accross the UAC In windows 7, If thats what were talking about here.
http://www.aneef.net/2009/06/29/request-uac-elevation-for-net-application-managed-code/
Well the guy that set up that machine basically asked the reverse... "How do I prevent a non-administrator from messing with group policy". So rather engaging in a group policy arms race, you can either do it at install time when running as an admin, or just skip that part of the code when not running as a user that has permission to do so.
Don't have your application disable task manager but instead use a windows service or scheduled task. Your application is going to run in the context of the current user and won't have rights to the registry key. Instead you can create either a windows service or a scheduled task which can run as a user with higher privileges and can write to the registry.
With a windows service you can communicate it through any IPC mechanism such as custom service messages, Sockets, .NET Remoting, WCF, or whatever, to tell it to turn task manager on/off.
the code requires an elevated privilege to access registry. However there is just a fragment of code that requires these extra permission. To handle such scenarios impersonation is used i.e. you will execute this application as normal user only but that particular piece of code will be executed as if you were an Administrator.
http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx

Impersonation to get user HKEY_CURRENT_USER does not work?

I am attempting to Impersonate an administrator account from a LocalSystem Service in order to get data from administrators HKEY CURRENT USER registry - in order to impersonate I am using the codeproject code found at the following site written by Uwe Keim: Impersonator
My source code is as follows:
using (new Impersonator("user", ".", "pass"))
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\CompanyName");
string sValue = rk.GetValue("Value", "").ToString();
rk2.Close();
}
My expectation was that sValue would be from the user/pass account (as I am impersonating it) but oddly enough it is still the sValue from the LocalSystem account where my service is runnning ...
Any clues on what I am doing wrong? Any help would be much appreciated.
Thanks,
I know this is an old thread but I recently came across the same issue (albeit from a C++ Windows service) and thought I'd share my findings, because many forums have asked the same question and none have left a satisfactory answer.
Basically, I've found two ways to approach this, though this is an answer more for C applications rather than .NET (I haven't tested with pinvoke but it may work).
Solution 1:
Instead of using RegOpenKey, use RegOpenCurrentUser() to get the key handle. Apparently, the reason RegOpenKey doesn't get the impersonated user's key is because HKEY_CURRENT_USER is cached in the running thread.
Solution 2:
RegDisablePredefinedCache(). This disables the cache mentioned above and lets subsequent calls to HKEY_CURRENT_USER be of the actual impersonated user. This is the solution I went with.
Hope this helps.
Everything I've read on the subject seems to indicate that impersonation should get you access to the HKEY_CurrentUser for the impersonated account. However, it could be a quirk in the .NET Registry implementation.
This is just a hunch, and an untested one at that, but have you considered using Registry.Users instead of Registry.CurrentUser?
You'll need to find the SID for the Administrator account, but you should be able to deduce that using Regedit
By default the HKEY_CURRENT_USER handle is cached on a process wide basis. So when you impersonate a user and then access the current user hive you will be accessing the hive of the user that started the process not the user being impersonated. This is true for all Win32 processes not just .Net. If you wish to disable this caching so that all current user calls go to the correct user hive under HKEY_USERS then you must call RegDisablePredefinedCache via pInvoke.
Be warned that if the user being impersonated has not had their profile loaded then any CurrentUser requests will be forwarded to the .DEFAULT user. So you may also need to call LoadUserProfile.
Disabling the handle caching will also cause a slight slowdown in all CurrentUser requests.
I'm guessing you're going to find that you're out of luck. It can't be done.
If applications were able to impersonate an Administrator account and write values to the Registry in Windows, it would present a huge security hole. My guess is that the Registry.CurrentUser property will ALWAYS reference the user running your application...whether or not you try impersonation or not.
EDIT
Turns out that I didn't read the implementation details of the Impersonator code you were using. Your problem could be something completely different.
Does your code refer to the Registry static class prior to your impersonation code being run? If so, that would be the problem. If you look at the Registry.CurrentUser property in Reflector, you'll see that it is set by the static constructor of the Registry object. Static constructors get called when the static object is first referenced.
In your case, if you're referencing the Registry object (whether it involves CurrentUser or not) the static constructor is being called which is setting CurrentUser to your original user...not the Impersonated account.

Categories