PAM "session required module" equivalent in Windows - windows

I have this nifty PAM module that validates each session (like a desktop session) on authentication and, based on some criteria, either allows or prevents it. I would like to do the same on Windows 7.
Now, this may sound silly or trivial to no extent, but I really don't know my way around Windows systems, and would thus like a few pointers on how to achieve something similar (i.e. a service or a module that is queried when e.g. a user tries to start a session.)

I think what you are looking for is a Subauthentication Package, but you could get some mileage with a Credential Provider.
A Subauthentication Package is a dynamically linked library that the local security authority or the Kerberos Key Distribution center (KDC) will call after authentication has succeeded, but before access is granted to the user.
Windows will authenticate the user locally or through Kerberos, depending on your configuration. You must build a DLL that exports the two functions:
Msv1_0SubAuthenticationRoutine (not called for interactive logons or Kerberos)
Msv1_0SubAuthenticationFilter
You put your code in that DLL, and return STATUS_SUCCESS if the user is allowed to log on, or one of the other error codes. You cannot assume that you will have access to the password.
If you log on through Kerberos, you must register your DLL on the KDC. It makes it hard to authentication against some local information, like a hardware or biometric device.
So maybe a Credential Provider could help you, but it is not the most elegant solutions. It was designed to capture credentials and feed them to an authentication package. But Microsoft made shure a credential provider will not lock a user out, so it might not always be called (in safe mode) and the user could install another CP, etc. So I mention it for the sake of completness.

Related

CoRegisterClassObject acess class from different integrity level or privileges

I'm using WinRT for showing ToastNotification. While working on this, I stumbled across the more generic problem that when a class factor is registered via
::CoRegisterClassObject(
callbackGuid,
winrt::make<NotificationCallbackFactory>().get(),
CLSCTX_LOCAL_SERVER,
REGCLS_SINGLEUSE,
&registration))
from a server process running with admin rights, a client process running with normal rights cannot instantiate it. The call
CoCreateInstanceEx(callbackGuid, NULL, CLSCTX_LOCAL_SERVER, pcsi, 1, &mq);
fails with error 80040154 Class not registered. I know that from a security standpoint this makes sense, but I was wondering if there is a way to bypass the check without using changing the running privileges of my process and without using global modifiers like CoInitializeSecurity. Basically I need a way to say "this class is accessible to everyone". Also I don't have a AppID.
EDIT: I forgot to say that the final solution must be on the server side, because for the original task of the Toast Notification I have no control on the client
COM weighs 3 main factors when deciding whether a running out-of-proc server is visible to a client attempting to activate that server’s CLSID: the configuration of the CLSID (typically in the registry), the server identity (as described by its token), and the client identity. The main security concern you’re trying to evaluate at that point is not access, as implied by the original question. Access is controlled by launch permissions (part of the CLSID configuration) and access permissions (configured via CoInitializeSecurity), and the server can use those security descriptors to describe which clients are allowed to respectively activate and call them. Those permissions can be made extremely broad, if the server so chooses. But they’re not relevant if the server isn’t even visible to the client.
The security concern you’re dealing with when evaluating activation visibility is actually squatting: can the client trust that the server is who they expect it to be?
If the CLSID configuration describes exactly what the server identity should be (e.g. a RunAs=System CLSID), then COM can reject any servers trying to CoRegister with an inappropriate identity; since there’s no squatting risk to any clients at that point, you can make that server visible to all clients. But at the other extreme, if the CLSID configuration doesn’t constrain the server identity at all, then making the server visible to a broad range of clients would have a significant squatting risk.
That latter case is referred to as “Activate-As-Activator” (AAA), because the server is only visible to the client (i.e. activator) if their identities match. If the CLSID has no configuration at all, or if the configuration doesn’t sufficiently constrain server identity, the CLSID is considered activate-as-activator. Since the server is only visible to clients with sufficiently similar identities, a non-admin client won’t be able to activate an admin server (or vice versa for that matter). You can’t prevent squatting attacks by verifying the server identity for these CLSIDs, so you can only allow activations that don’t cross any security boundary at all.
So if the server is some high-privileged known account such as System or LocalService, you would need to configure the CLSID with a RunAs APPID for that account. If the server’s identity is “the same as the client’s but elevated”, you don’t have a RunAs that describes that. What you do have for that case is the elevation moniker. You configure the CLSID as Activate-As-Activator, and add some extra configuration to make it compatible with the elevation moniker. You also need different client code which explicitly activates through the elevation moniker. And the activation would pop up a UAC prompt. Unfortunately, if you can’t alter the client code, and you’re in that latter “the same as the client but elevated” case, I don’t believe there’s any way to make the activation succeed directly. You could probably introduce another layer to make it work (original CLSID starts up an exe under the client’s token through AAA activation; then that intermediary process does an elevation moniker activation of the real CLSID running as admin). But it would be far cleaner to change the client code.

When is SeTcbPrivilege used? ("Act as part of the operating system.)

For what purpose(s) is the SeTcbPrivilege privilege in Windows used? Can it be used, for example, to run a program under the SYSTEM account?
Acting as a part of the operating system allows you to do things like create login tokens. It's unlikely that you would ever need to write a service that uses this privilege unless you're writing an authentication provider.
Since you can create access tokens, you can act as any user. Of course, this means that you can run programs under the SYSTEM account, but there are much easier ways to run something as SYSTEM.
To add to Gabe's answer, here is what MS says,
Allows a process to assume the identity of any user and thus gain
access to the resources that the user is authorized to access.
Typically, only low-level authentication services require this
privilege.
Default setting: Not assigned.
Note that potential access is not limited to what is associated with
the user by default; the calling process might request that arbitrary
additional privileges be added to the access token. The calling
process might also build an access token that does not provide a
primary identity for tracking events in the audit log.
When a service requires this privilege, configure the service to log
on using the Local System account, which has the privilege inherently.
Do not create a separate account and assign the privilege to it.
Source: Microsoft TechNet
SeTcbPrivilege is very useful for debugging purpose. For example, if you are developing Windows service that has to be run under system account and perform impersonate things it is conveniently to run this service as standalone exe. SeTcbPrivilege will allow to do this.

How to securely store database credentials for Windows application?

I have a python application designed to run as a service on Linux, and I've been asked to install it on a Windows XP box in an office where there are no Linux machines (for me, this makes it a bizarre and confusing place as I have virtually no experience developing for Windows).
On Linux the application has its own user, and the application and database credential file reside in an encrypted folder accessible only by that user. (I'd like to state that I am not a cryptologist, and that if there are already glaring security errors in this set up I'm very happy to have them pointed out to me!)
How can I achieve an equivalent level of security by similar or different means on a Windows XP machine? That is to say, how can I prevent those who have access to the computer or the disk altering the program or reading the credentials?
A little background: the host windows box is a workstation used every day by users with non-administrative privileges. The secure assets are personal data roughly as sensitive as, for example, a school report. The application is intended to be used by about 10 people who authenticate to the application with individual passwords (stored salted and hashed in the database).
There is a very similar question that received the answer:
on Windows you would store the credentials in the registry in a location protected by an ACL
However, it doesn't touch on the aspect of protecting the program files, and further it seems to assume a higher level of Windows experience than I currently enjoy :) I have no idea how to protect registry items with an ACL, nor how I would then be able to access the protected keys from my program. Simple instructions for a developer in an unfamiliar environment would be greatly appreciated!
Your question is unclear about what your application does and what your security requirements are. I'm going to make some assumptions, and provide an answer based on them. If these assumptions are incorrect, please clarify in a comment and I'll update.
I'm assuming you have an application that:
stores sensitive data in a database stored in a DBMS installed on the workstation
is installed on a shared workstation
each user has their own login (non-admin)
allows different users to log on and interract with their data
user runs applicaiton which connects to a service
service connects with database, delivers data to users
service runs under its own user account
If this is correct, then you shouldn't have much issue.
The service can run under any account, but it would be easy enough to have it run under one of the standards (Local Machine or Network Service). Configure the database so that only this account can access it. In Sql Server, I'd only grant that user account (and admins on the box) login and access rights to the database.
This is the only security you need, if the users aren't admins. Now, when the frontend connects to the service, the user can provide the username/password and the service can authenticate against salted and hashed passwords stored in the database. All this is secure as long as 1) each user has their own login 2) communications are secure (using named pipes or SSL) and 3) no virii or keyloggers are running under an admin's credentials.
You can configure your service as to what account it runs under by running services.msc (or right-clicking on MyComputer and selecting Manage or clicking on Services under the Admin tools menu in Control Panel or probably in a number of different ways).
Bring up the list of services, right click on your app and hit Properties. From there, make it look like this:

Is it possible to programmatically backup/restore Windows domain/certificate credentials?

I've been trying to use the Windows Authentication low level credential API functions to backup/restore credentials.
http://msdn.microsoft.com/en-us/library/aa374731%28VS.85%29.aspx#low_level_credentials_management_functions
However, I've found that while I can use CredEnumerate to obtain every credential on the system, all the passwords are missing for domain type credentials (which is documented). Is there any way to backup/restore these credentials in the same way as the windows GUI tool can?
Hmm, it looks like I've found the answer although I don't like it. The only way to do this seems to be to CreateRemoteThread() to create a thread in lsass.exe (The windows security subsystem) and then to enumerate the credentials from within that thread using undocumented function LsaICryptUnprotectData exported from Lsasrv.dll to decrypt the credentials buffer.
It works but I'm not sure I have the stomache to put this into my software...

WIN32 Logon question

We have developed a ASP.NET 3.5 web application with Web Server 2008 and has implemented a custom authentication solution using active directory as the credentials store. Our front end application uses a normal login form to capture the user name and password and leverages the Win32 LogonUser method to authenticate the user’s credentials. When we are calling the LogonUser method, we are using the LOGON32_LOGON_NETWORK as the logon type.
The issue we have found is that user profile folders are being created under the C:\Users folder of the web server. The folder seems to be created when a new user who has never logged on before is logging in for the first time. As the number of new users logging into the application grows, disk space is shrinking due to the large number of new user folders getting created.
I need to get the token back after the authentication (authenticated \ password locked \ wrong password ) its futher use and based on logic showing different web pages
Has anyone seen this behavior with the Win32 LogonUser method?
Please answer the following issue:
Is it possible to disable this behavior to create the folder as taking 2.78 MB of space for every new user and it eating my disck space?
I have tried LOGON32_LOGON_BATCH but it was giving an error 1385 in authentication user.
For any solution related to LOGON32_LOGON_BATCH, can you please confirm if that will stop creating the folders at location C:\users.
Also for any possible solution I need either
I am able to disable the folder to be created at C:\user or
Any other option to authenticated user which will not creat folders.
Pass LOGON32_LOGON_BATCH and grant the users permission to log on as a batch job on that machine using Group Policy.
The MSDN documentation for LogonUser recommends LOGON32_LOGON_BATCH as the logon type for web services:
This logon type is intended for batch
servers, where processes may be
executing on behalf of a user without
their direct intervention. This type
is also for higher performance servers
that process many plaintext
authentication attempts at a time,
such as mail or Web servers. The
LogonUser function does not cache
credentials for this logon type.
Have you tried that?
You don't write any information about the version of products (.NET, Windows Server which you use) and the best answer on your question can depend on this. Moreover the best way for your solution depend on what you want to do with the users token after logon. Do you really want to use this token or you want only verify the user? So I try to answer most general on your question.
In general, error 1385 (ERROR_LOGON_TYPE_NOT_GRANTED) means following (see http://support.microsoft.com/kb/155012/en):
A user has requested a type of logon,
such as interactive or network, that
was not granted. An administrator has
control over who may logon
interactively and through the network.
There are SE_BATCH_LOGON_NAME and SE_DENY_BATCH_LOGON_NAME (NTSecAPI.h) privileges which can be disabled/enabled in your case (see http://msdn.microsoft.com/en-us/library/bb545671%28VS.85%29.aspx for description). Use Process Explorer started with administrator rights (see http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) to see which privileges has a process and which from there are enabled (see "Security" tab of a process). If your account used for the application pool don't have SE_BATCH_LOGON_NAME granted or this privilege is not enabled before call of LogonUser, you should add the corresponding code in your program.
By the way sometimes you don't really want to do much with an user account and want only verify a password. To do this you can use an old way with SSPI (see http://support.microsoft.com/kb/180548/en) which are used inside of LogonUser implementation. This way is the most smart and quick way to verify an user account which I know.
You can look at "The SSPI Workaround" (see http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook/HowToGetATokenForAUser.html) for more information of usage SSPI in .NET 2.0.

Resources