Why the SYSTEM account is not able to access the user's certificate store?
At the same time the SYSTEM account is able to read the certificate (through the CSP dll) from the smart card and put it in the certificate store (CSP is being used by winlogon.exe in this case, so I guess the winlogon.exe has some magic inside).
For example, calling CertOpenSystemStore( NULL, L"MY" ) under system account will succeed, but CertFindCertificateInStore() will not find anything, because it looks like the store is empty. When I log on, the CertFindCertificateInStore() will find the requested certificate.
Every user has a different MY Store, So If you are able to find something in USER A login My Store, you might not be able to get that from User 2.
Try using MMC for accessing Certificate Stores of other users and service accounts.
Either you need to put the relevant certificates in the SYSTEM cert store or you need to impersonate the user whose store you wish to access. Impersonation can be done in multiple ways, I would suggest start looking at MSDN.
Related
Is there a way to securely store and retrieve an API key in windows?
For instance, is there a windows service/api that can be used by a (c#) desktop app to store and retrieve a key?
If the key has to be placed on a client machine, it can be read out. Which language you use or what kind of storage doesn't matter. At the end you'll have to send that API key to your server to authenticate yourself and at this point someone can use a proxy like Fiddler to inspect the data and record that API key.
To accomplish this issue you need a (web) interface for your customers, where they can log-in and manage their API keys, so they can request new or revoke old keys. Also your desktop tool needs in that case some input mask, where the user can enter that key (and you store it in registry or file system).
By using this approach each customer can use its own key and if it is compromised you (or the customer) have only to revoke this single key without affecting the other customers.
Sorry to answer my own question, but it appears Windows Credential Manager and the underlying Data Protection API is designed for this very purpose. It's the same vault used by Windows to store it's various passwords.
And it has a nice c# API.. https://learn.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection
Answered more fully here.. PasswordVault security when used from Desktop app
Background info
Developed a web app that uses IIS8. Currently using IIS to perform client authentication. Server self-signs a certificate and the certificate is imported on specific PCs.
User access site from browser and browser prompts for SSL cert. (Cert is imported to Personal Folder).
For PCs with single accounts there is no issue as i just import the certificate to that account.
For PCs with multiple accounts, if i import the certificate to the Local Computer account the different accounts are unable to access the certificate.
Query
How do i allow multiple accounts to access a single certificate? Tried to grant individual permissions to the individual accounts from the Local Computer Certificates console but to no avail. I do not want to issue the certificate individually to each account.
Is there a solution or alternative to this query?
You should try and separate authentication (using client certs) from account management, meaning authorization.
A good approach might be to use client certificates only to identify the user accessing your application (with exactly 1 certificate for each user). Then setup an n:m mapping to determine that user's groups, which in turn are given specific rights within your application. This is a common way to decouple users and their rights, to facilitate managing each.
I am importing X509 from PKCS #12 file (using PFXImportCertStore Cryptographic API) in Computer's Personal Store.
Problem:
Any process running under "Local Service" account or any non-admin account can not access privates key (restricted to Admin user by Windows).
How to give access to private keys of a certificate to non-admin users and local service?
Note:
Since multiple process use certificates, I preferred using Computers store instead user's store.
This is a tricky one with some pitfalls. I had the same problem and was close to despair, when I finally found the remark which saved me in this post
I succeeded to do this for a local service running under the Network Service account.
First, there is the option to grant other users access to the private key of a certificate in the MS certificate store. Already this I'd classify as druid knowledge: this option is available in the context menu (right click the certificate), but only if the certificate resides in the localMachine\Personal store. There, in the entry All tasks, you will find the sub entry Manage Private Keys. This is not available in other stores, not even in the CurrentUser\Personal store.
This entry opens a dialog which allows you to add access rights to the certificate for other users. Here, the next hurdle waits for you: the default setting is to search for users in the domain, not on the local machine. The desired user may not be found, unless you change the search filter.
To this result I came very fast by googling, but it did not help. I could get the service to run, but only if I changed the service user to the logon account, which is not what I wanted (this leads, btw, to a workaround: create a local user account for services and import the certificate from within that user account. You can then place the certificate in almost any store and it will work fine)
This is where the post cited above comes in, the last hurdle for me: the procedure described above seems to work only if you import the certificate into the certificate store from within the MMC snapin. Select the store localMachine\Personal and use the context menu to import the certificate in question. (I chose to make the private key exportable, this may or may not be relevant here). If you import the certificate by double clicking on it in the file system, it will be imported into some store in the Current User location. I used to do this and then move it into the localMachine\Personal folder and changed the access right -- this did never work for me. Only after importing it from within localMachine\Personal in the MMC certificate snap-in it worked immediately...
(Also note that you have to place the certificate into a store which can be found by the service user. Your current user stores usually does not allow this, so localMachine is the better choice, anyway)
I don't know whether you can move the certificate around afterwards, but that's easy to check in the system..
Is there any more securely way to protect and store a password than Windows DPAPI do?
My program needs to store a secret (something like credentials) to do automatic logins on Windows, and this secret have to be shared with other users accounts because the program can be run on different accounts but sharing the credentials.
I need to protect this secret from tampering to avoid an attacker to inject his own credentials and take the control. If the attacker has phisical access I know that there is nothing we can do, but.... currently, what is the best way to store and protect this secret?
If you want to secure something against tampering, you are probably better off with a multi-level approach. The drawback to this is that gaining access (even with all secrets) is an astronomical feat and will bump up your login time on this.
Keep in mind, however, that a system is only as secure as its weakest point; you can have a file in a hidden encrypted volume behind even more layers of custom encryption, but if you have the passwords on a post-it note by your desk at work, odds are that it wont be secure for long.
The same applies with security on windows. ACLs and encryption are only as strong as your administrators' accounts. For tips on security, try Server Fault.
As for the system itself, implementing public-key cryptography (asymmetric encryption) through keys or digital certificates somehow and giving every user their own individual keys/IDs is a much safer alternative with far fewer risks.
Windows has supported pubkey infrastructure since at least windows server 2000; you can even use a smartcard logon if you have the hardware for it.
Consider the following:
1. An attacker obtains a private key (with protection on it) from a user. This can be broken #2048bit in an hour or two on average hardware. With this example, you need only remove the public key of the user and have them re-generate a new key.
2. An attacker obtains a user's digital certificate, then you have two options:
1) Remove their certificate from the Active Directory store, ACL or other certificate store.
2) Issue a revocation on the certificate, and forceably expire it. This assumes your are acting as the certificate authority.
In short, this answer states one thing: If you are worried about password security that much, then you should not be using passwords. If you make your system take forever to break, then the alternative route is a botnet bruteforce of a password.
What is the best way to send a password to a Windows Service? Our application needs a password in order to start. I don't care that services are "normally" supposed to run without user interaction. Its good enough for us that an operator can start the application and then log off.
On a unix system, I would just echo the password over stdin but the service has no stdin.
Currently, we use the DPAPI to just store the password using CryptProtectData. While this, works, it presents other problems that are beginning to become troublesome.
I'm guessing that I'll need to use some form of IPC between the service and the application that is sending the password but I'm not sure which method is appropriate, if any.
Thanks
Two main options:
You could listen on a socket on startup and wait for the required password to be supplied (maybe embed an SSH server in there, so that the password cannot be snooped over the wire)
My preferred option would be to read the password from a configuration file (that can be secured to the minimum readership) or registry setting (again, sufficiently secure such that only your service and administrators can read/change it)
Thanks for responding Rowland.
You could listen on a socket on
startup and wait for the required
password to be supplied (maybe embed
an SSH server in there, so that the
password cannot be snooped over the
wire)
I considered that but without certificate verification, wouldn't that leave us open to a man in the middle attack?
My preferred option would be to read
the password from a configuration file
(that can be secured to the minimum
readership) or registry setting
(again, sufficiently secure such that
only your service and administrators
can read/change it)
We're trying to follow "defense in depth" as much as possible such that if an attacker compromised the machine, he would not able to access our application.
You can use kerberos mutual authentication. There are few options and examples there.
But just wondering. On a compromised machine, There may be a key logger. So typing the password is never secure if you want to maintain security in this environment. The same problem exist afaik for unix terminals.
DPAPI in UserMode is really the best option, and storing the encrypted data in a protected location, e.g. registry key with limited ACL.
What exactly were the problems that are beginning to be troublesome? Maybe we can just solve those...
What exactly were the problems that
are beginning to be troublesome? Maybe
we can just solve those...
Currently, the application runs as the Local System account.
Our application stores a number of credentials in an encrypted file and uses the DPAPI (in UserMode) for the encryption.
Thus, when the application is installed, the installer is run as the Local System account. We also have a set of tools that ship with the application, some of which need access to this encrypted file and thus, they too need to run as the Local System account.
By the time the application is installed and started, we're heavily dependent on that account.
We're running into problems because one of our users wants to use the application to access a shared network drive. The Local System account has no such privileges and we can't simply run our service as a different user because our encrypted information is protected under the Local System Account.
We've tried to avoid the process of setting up a user account just for our application because it is installed across many different customers and environments, all of whom have wildly different security policies.
You can access a remote drive from a service running under system account. However, you will need to have credentials & share information to connect to the remote machine. You can use the API wnetaddconnection to gain access. Probably your encrypted file can store this credential as well.