These two APIs are very similar but it is unclear what the differences are and when each should be used (Except that LoadUserProfile is specified for use with CreateProcessAsUser which I am not using. I am simply impersonating for hive accesss).
LoadUserProfile
http://msdn.microsoft.com/en-us/library/bb762281(VS.85).aspx
RegOpenCurrentUser
http://msdn.microsoft.com/en-us/library/ms724894(VS.85).aspx
According to the Services & the Registry article:
http://msdn.microsoft.com/en-us/library/ms685145(VS.85).aspx
we should use RegOpenCurrentUser when impersonating.
But what does/should RegOpenCurrentUser do if the user profile is roaming - should it load it?
As far as I can tell from these docs, both APIs provide a handle to the HKEY_CURRENT_USER for the user the thread is impersonating. Therefore, they both "load" the hive i.e. lock it as a database file and give a handle to it for registry APIs.
It might seem that LoadUserProfile loads the user profile in the same way as the User does when he/she logs on, whereas RegOpenCurrentUser does not - is this correct? What is the fundamental difference (if any) in how these two APIs mount the hive?
What are the implications and differences (if any) between what happens IF
A user logs-on or logs-off while each of these impersonated handles is already in use?
A user is already logged-on when each matching close function (RegCloseKey and UnloadUserProfile) is called?
But what does/should RegOpenCurrentUser do if the user profile is roaming - should it load it?
It doesn't load the profile. Think about it this way: If it did, you'd have to somehow call UnloadUserProfile() when finished with the handle to HKEY_CURRENT_USER.
It might seem that LoadUserProfile loads the user profile in the same way as the User does when he/she logs on, whereas RegOpenCurrentUser does not - is this correct?
Yes.
What is the fundamental difference (if any) in how these two APIs mount the hive?
None.
What are the implications and differences (if any) between what happens IF
A user logs-on or logs-off while each of these impersonated handles is already in use?
They'll get their own handle (to the same key) that's opened and closed.
A user is already logged-on when each matching close function (RegCloseKey and UnloadUserProfile) is called?
Ditto.
As I am currently trying to accomplish the same thing you are I thought I would chime in with what I've found over the last few days.
I'm working in a Windows XP sp3 environment and trying to achieve impersonation with CurrentUser registry access in two different scenarios
If you come across anything useful I would be greatly appreciative if you share your experience. My stack overflow question can be found here
Administrator > Limited User & Limited User > Administrator
What I've noticed so far is (in Windows XP sp3)
LoadUserProfile():
Only works when the impersonating user has SeRestoreName and SeBackupName privileges enabled among others (simply enabling these two for the limited user in question was not enough as it still failed with an access denied error - See my StackOverflow question for more details on that). The only way I'm able to successfully call LoadUserProfile() so far is to do so by an Administrator account before starting impersonation.
RegOpenCurrentUser():
Only works "properly" when the user's profile is already loaded, In every attempt I've made so far I'm only able to get a handle to the S-1-5-18 hive unless the users hive is loaded and accessible under HKEY_USERS already
The two functions are used in different situations.
LoadUserProfile is suitable if the user profile is not already loaded.
RegOpenCurrentUser is suitable if the user profile is already loaded, i.e., if you want to access the registry hive for a user who is already interactively logged on.
Note that LoadUserProfile is usually called without impersonation (because you must have admin privilege to use it) but RegOpenCurrentUser has to be called with impersonation.
Related
I am writing a C++ application with a postgresql 9.2 database backend. It is an accounting software. It is a muti user application with privilege separation features.
I need help in implementing the user account system. The privileges for users need not be mutually exclusive. Should I implement it at the application level, or at the database level?
The company is not very large at present. Assume about 15-20 offices with an average of 10 program users per office.
Can I make use of the roles in postgres to implement this? Will it become too tedious, unmanageable or are there some flaws in such an approach?
If I go via the application route, how do I store the set of privileges a user has? Will a binary string suffice? What if there are additional privileges later, how can I incorporate them? What do I need to do to ensure that there are no security issues? And in such an approach I am assuming the application connects with the privileges required for the most privileged user.
Some combination of the two methods? Or something entirely different?
All suggestions and arguments are welcome.
Never provide authorization from a client application, which is run on uncontrolled environment. And every device, that a user has physical access to, is an uncontrolled environment. This is security through obscurity — a user can simply use a debugger to get a database access credentials from client program memory and just use psql to do anything.
Use roles.
When I was developing an C++/PostgreSQL desktop application I've chosen to disallow all users access to modify all tables and I've created an API using Pl/PgSQL functions with VOLATILE SECURITY DEFINER options. But I think it wasn't a best approach, as it's not natural and error prone to use for example:
select add_person(?,?,?,?,?,?,?,?,?,?,?,?);
I think a better way would be to allow modifications to tables which a user needs to modify and, when needed, enforce authorization using BEFORE triggers, which would throw an error when current_user does not belong to a proper role.
But remember to use set search_path=... option in all functions that have anything to do with security.
If you want to authorize read-only access to some tables then it gets even more complicated. Either you'd need to disable select privilege for these tables and create API using security definer functions for accessing all data. This would be a monster size API, extremely ugly and extremely fragile. Or you'd need to disable select privilege for these tables and create views for them using create view with (security_barrier). Also not pretty.
I'm using NetQueryDisplayInformation (I've already tried the NetUserEnum function) to get the set of user accounts on the local machine. I can get all the accounts this way - but I only want the accounts associated with actual human beings, and not, for example, hidden accounts used for software updates.
After reading the MSDN documentation on the relevant structures and similar Stack questions, I see nothing that can allow me to filter to just the accounts that I need.
Ideally, someone will have a simple and reliable solution that:
Doesn't involve using undocumented registry entries
Doesn't rely on enumerating user folders on disk
I'm not going to try to build an exhaustive list of non-real-user accounts
For technical reasons, WMI is not an option
Any ideas?
[Much later]
Got the answer, but not here - just enumerate the groups for each user. "Real human" accounts will be a member of one or more of Administrator, Power User, User, Guest.
You may be able to use the NetUserEnum function. It should return a list of all the user accounts on the system. I've not had to use this function personally so I can't provide any spectacular code examples, but the MSDN information sounds like what you are looking for.
You can use NetQueryDisplayInformation API, combine with bitwise check on user info flag.
I have exactly the same requirements, so I cook sample code (modified from MSDN GROUP query).
The user flags I used are:
UF_NORMAL_ACCOUNT
UF_ACCOUNTDISABLE
UF_PASSWD_NOTREQD ---> this ensure we get Human account, Human account always requires password.
working code at: http://www.cceye.com/list-system-normal-user-account-only/
I have two computers, named A and B, they are in different domain and don't have trust connections between them, can I use WMI on A to operate B, or the opposite?
Yes per the answers from you and MSDN I know I can achieve it.
The fact is though I use administrator to do WMI operations, the process that remote started by WMI still does not have administrator privilege(In task manager the process user name still show as administrator).
Could you please tell me the reason?
thank you in advance.
If I understand your question correctly:
WMI (windows management instrument) by itself can operate in conditions that you've mentioned. It's like sql style database, it works on computer.
If this is not the answer you expected, please clear up your question...
The biggest limitations of WMI is, it requires Admin level credentials for WMI operations.
Now in your case, You can connect to machine B (in different domain) using local admin level user(which has administrator rights for his local machine B). You can also use domain level admin user which has administrator rights for domain of machine B.
The answer is WMI does not pass your authentication level on to the remote host by default. To do so your account would need the right "Trusted for Delegation", which gives the very dangerous right to act as any account on the domain, and then you would need to change the authentication type in your WMI code to match this level. See this MS link:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa389288%28v=vs.85%29.aspx
In Windows would it be possible to protect data within a single program? I have been looking into CryptProtectData but whis is by user basis I would like something simular but on program basis. My program will have multiple users that require access to the same data, but the data is sentitive and I dont want any user to read it.
First of all, if your user has administrator privileges, there is no definite way to keep them out.
Second, even if they didn't, you'd have to implement part of your software at ring 0, so it would have a higher privilege than the user, which would make it harder for them to get access to the process' memory or executables. You could then encrypt your data and decrypt it when you serve it to the user.
If all of the above is not possible, you can employ the same obfuscation techniques that software developers use against cracking.
That usually comes down to preventing debugging or preventing patching. Some advice here: http://www.woodmann.com/crackz/Tutorials/Protect.htm
CryptProtectData (indirectly) uses user's credentials to encrypt the data.
On Windows (as well as on most other general-purpose computer platforms) it is not possible to encrypt the data on per-application basis cause the computer belongs to users and the user is the master, not the application.
If you don't want the data to be accessible for the user (and other applications running under user's account), you need to move this data out of the computer, store it on the remote system and control user's access to this data.
If your users do not have administrator privileges then what I would do is have your program create an account for its own purposes. When your program creates its data files, it would set the ACLs on those files so that the account it created is the only one with any access to those files. Whenever your program needed to read/write those files, it would need to temporarily login using its special account. The problem is then to keep the login credentials for that account secret. That's another problem entirely.
I've written a small service (plain Win32) and I'd like to know if it's possible to run multiple instances of it when multiple users are logged on.
Basically, let's say we've got UserA and UserB for UserA the service would log on as "domain\UserA" and for UserB the service would log on as "domain\UserB" - this is from the same executable of course. I can change the logon dynamically using the ChangeServiceConfig() function, but it changes it system-wide it seems, while I'd like each user to have his own copy of the service running only for him.
Thank you in advance for any pointers.
Win32 services are designed to be system-wide, and start running before any user is logged in. If you want something to run on a per-user basis, it's probably better to design it as a regular application and run it from the user's Startup group.
Is it possible to perhaps have the service create child processes which then adopt the user credentials (or be started with them)? This way you're still limited to a single instance of the service, but it is able to do its per-user jobs all the same. IIRC the Windows Task Scheduler service does this.
The whole concept of a service is that it is started before any user is even logged on. so even if this was possible, you wouldn't be able to choose between userA and userB when the service starts because none of them is logged on yet.
A possible direction would be for the service to run as SYSTEM And every few minutes check if there is a user logged in, if there is- impersonate that user and do this stuff.
Yes, that sounds close (I'm answering comment from Greg, but comments are too short to fit my reply).
I don't know the list of users beforehand, but there's a GUI control application that would be used to enter username/password pairs for each user. So, userA would log on, run the application, enter his credentials and service would use that. At the same time (after userA has logged off, but the service is still running with userA's credentials) userB logs on, uses the app, and another copy of the service starts running as logged on userB. Thus, at the same time userA and userB services are running.
Is that possible?
You are probably looking to Impersonate the users. Check out some references I found with a quick Google search here:
MSDN Article on WindowsIdentity.Impersonate
.Net Security Blog Article
It sounds as if you actually have two different, conflicting requirements, as to timing and identity.
Run as each logged in user
Run automatically even if no user is logged in.
No way to do this trivially, instead consider wrapping your program in a service; the program will run normally on startup for each user (either thru the startup folder or taskscheduler), and in addition create a service to run your app as a system user (or any other user you define).
Since you also need (you mention this in the comments) the app to keep running as the enduser even after he logs out, you can have the service manage this process for you.
HOWEVER this might not be the best idea, since the user is still effectively logged in. This can have numerous side effects, including security, performance (too many users logged in at once...), etc.
You could create an service application and a non-service(normal) application and make them communicate through IPC (Mapped File, Pipes, MailSolts ... you name it).
This way you solve all the troubles.
NOTE: The same application can behave differently - when started as a process and when started by a user, but in the end it is the same thing, you still have 2 applications (no matter if you got only one executable).
Running with different accounts is possible. In fact, this is common. See svchost.exe, which implements a bunch of OS services.
I just don't get how you determine which accounts. In a big company, many PCs are set up so all 100.000+ employees could use it. You don't want to run your service as the logged-in users, nor can you want to run it for all 100.000 users. So for which accounts, I have to ask?
A Windows process can only execute with the privileges of one single user at a time. This applies to services and other processes. With enough privileges it is possible to "switch" between different users by using impersonation. The most common pattern for what you are trying to do is to have one instance of a privileged service which registers to log in/log out events and creates children processes accordingly, each one of them impersonating the logged in user. The pattern will also simplify UI as each process runs on each separate user's Desktop, as if it were a regular application.
If you keep the privileged service's code as simple as possible this pattern has the added benefit that you are minimizing the attack surface of your code. If a user finds a security problem on the "running as user" side of your service it is a non-issue, while security problems in the privileged services could lead to privilege escalation. In fact, before Vista privileged services implementing a Windows message processing loop are vulnerable to a type of attack called Shatter attacks, which you should be aware of given what you are trying to do.
You want this running all the time, so you want a service.
You want something tracking each user, so you want an application which runs in the user session and communicates with the service (using named pipes or DCOM or whatever fits your requirements).
You don't need multiple instances of your service. From the description of your problem it looks like what you need is one service that can impersonate users and execute jobs on their behalf.
You can do this by implementing a COM object hosted in a service. Your client application (that the end user runs) will call CoCreateInstanceEx on your CLSID. This would cause new instance of your COM object to be created in your service. Then the application can use a method on one of your interfaces to pass the collected user credentials to the COM object (though I'd be wary of collecting credentials and instead see if I can pass the user token instead). The COM object which is running in the context of the service can then call LogonUser() to log on the user and impersonate it, so it can do whatever on her behalf (like finding the user local appdata folder :-)). Other answers havve good links to impersonating users using credentials or token.
If you feel comfortable with COM, I'd suggest you create your objects as multithreaded (living in the MTA), so that their execution is not serialized by COM. If not, the default single threaded model would be good enough for you.
The Visual Studio ATL wizard can generate the skeleton of a COM object living in a service. You can also read about implementing Windows Service with ATL here: http://msdn.microsoft.com/en-us/library/74y2334x(VS.80).aspx
If you don't know COM at all, you can use other communication channels to pass the credentials to your service.
In any case, once your service gets the credentials, all the work on behalf of the user will have to be executed on a background thread, so as to not block the application running as the user.