How to provide private key access to the application pool identity? - asp.net

I have come across this excellent blog explaining how to provide access to private keys and why its needed:
On www.microsoft.com we have a number of applications that use certs
to access other web services, the way we do is by installing the
certificate with the private key into the local machine store and
provide access to the application pool identity to the private key and
use the serial number or the thumbprint of the certificate in the
web.config of the application. One of the key challenge was to script
out the private key access to the application pool identity across the
server farm. (source: http://tinyurl.com/cbsmpqk)
At the time being my silverlight application can't access the database as it seems that it has no access to the installed certification (on Azure Cloud), as this is required to read the encrypted DB connectionString.
It says Failed to decrypt using provider 'CustomProvider' -> Keyset does not exist.
Following the blog above I was able to solve it by changing permissions for the installed certificate to additional read access for 'Authenticated Users' or even to 'Users'.
In both cases it works fine, but I don't understand the security implications. Does it mean now that anybody from Internet is able to read my certificate's thumbprint? Have I mistakenly opened a security hole?
Which username/Role should I rather have given the read access to the private keys of the certificate?
Many Thanks

Grant permissions to IIS AppPool\AppPoolName user. For example, IIS AppPool\DefaultAppPool.
From this answer: https://stackoverflow.com/a/2647003/991267

I don't think it means anyone can access your private key. If you set the 'authenticated user' or 'users' that means only the users in these groups would have the access permission. But if you set 'everyone' that means, everyone.

Related

Error ID1039: The certificate's private key could not be accessed even when app pool account has access to private key

After installing a .pfx cert into the 'Local Machine' store on my laptop, I configured an ASP.NET website in IIS Manager to use that cert in its https bindings.
The application pool, which the website uses, is assigned a user account that has access to the cert. When I navigate to the homepage of the site, I get a 500 error page. In Windows Event Viewer, the following is logged...
Error: 'ID1039: The certificate's private key could not be accessed.
Ensure the access control list (ACL) on the certificate's private key
grants access to the application pool user
This is driving me nuts because, as I mentioned previously, the app pool account already has Full Control and Read permissions granted against the cert in the Local Machine store.
I have already tried the suggestion mention on this webpage...
https://elybob.wordpress.com/2012/07/04/wif-error-id1039/
whereby you grant the IIS_IUSRS account Read permissions against the MachineKeys folder, but that made no different to my situation.
I'm stuck on how to make progress here, so any suggestions would be appreciated.
In IIS, to be able to use Certificates from file (Certificate .pfx file), need to set "Load User Profile" to True in the application pool's Advanced Settings to be able to load a cert by filename & password.
Select Application Pool of your ASP .NET application -> Right Click -> Advanced Settings -> Set Load User Profile to True
For cryptographic operations, Microsoft algorithms may not be FIPS compliant and you may override it by setting Security Policy to support Digital Signature verification in
Administrative Tools -> Tools -> Local Security Policy -> Local Policies -> Security Options -> System Cryptography: Use FIPS Compliant algorithms -> Disabled
Update: Using certificate private key may also require permission to IIS application pool:
Run certlm.msc -> Select certificate -> All task -> Manage private key
-> Give permission to application pool

Using ASP.Net Core v2.2 ProtectKeysWithAzureKeyVault() data protection

Using ASP.NET Core 2.2 I'm trying to configure data protection such that I store the keyring in Azure Blob Storage and protect the keyring with a key stored in KeyVault.
In my ConfigureServices() method I have:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("myblob-sasuri"))
.ProtectKeysWithAzureKeyVault(keyVaultClient, "key-identifier-uri");
}
All looks good, but I am confounded with Forbidden errors in accessing the keyvault. I can't figure out if I have somehow screwed up the key identifier (doubtful) or the keyVaultClient, or the permissions.
I suspect permissions, but nowhere do the docs tell me what permissions the client needs.
Anyone made this work successfully?
Through experimentation I have learned that the KeyVault access policy must have the "Unwrap Key" permission enabled in the Cryptographic Operations section of Key Permissions. So, the service principal you grant access to the KeyVault must be granted that one specific permission in your access policies. We ran into problems because we had not enabled that, we had just Encrypt and Decrypt permissions enabled. This should be documented, I added feedback to the doc here: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2

Storing Azure Vault Client ID and Client Secret

I am using .NET Core 2.0 and ASP.NET Core 2.0 for application development. The "test" application is a .NET Core Console application. The core code I am writing is a class library. Once proper testing. I choose to do this since I won't be putting this to use for awhile (it's replacing older ASPNET code).
Anyway, since I have to work with a LOT of API keys for various services I decided to use Microsoft Azure Key Vault for storing the keys. I have this all setup and understand how this works. The test application uses a test Azure account so it's not critical. And since this is replacing legacy code and it's in the infancy, I am the sole developer.
Basically, I'm running into this issue. There's not too much information on Azure Key Vault from what I can see. A lot of examples are storing the Client ID and Secret in a plain text json file (for example: https://www.humankode.com/asp-net-core/how-to-store-secrets-in-azure-key-vault-using-net-core). I really don't understand how this can be secure. If someone were to get those keys they could easily access stored information Azure, right?
The Microsoft MSDN has a powershell command that grants access (I lost the original link, this is closest I can find: https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/setting-up-and-configuring-an-azure-key-vault/) My development operating system is Windows 10 and my primary server operating system is Debian.
How would I approach this?
Yes, you are right, the plain text config file could be used only during development, not for production purpose. And in general, available options depend on where and how you host an App.
If you have an Azure Web App, you have at least next built-in options (from the documentation):
add the ClientId and ClientSecret values for the AppSettings in the Azure portal. By doing this, the actual values will not be in the web.config but protected via the Portal where you have separate access control capabilities. These values will be substituted for the values that you entered in your web.config. Make sure that the names are the same.
authenticate an Azure AD application is by using a Client ID and a Certificate instead of a Client ID and Client Secret. Following are the steps to use a Certificate in an Azure Web App:
Get or Create a Certificate
Associate the Certificate with an Azure AD application
Add code to your Web App to use the Certificate
Add a Certificate to your Web App
You may also find an approach that uses env variables to store credentials. This may be OK only if you can guarantee that it's not possible to do a snapshot of env variable on prod machine. Look into Environment Variables Considered Harmful for Your Secrets for more details.
And the last one thing: there is also a technic that based on the idea, that you need to store/pass only a ClientSecret value while ClientId should be constructed based on machine/container details where the App is hosted (e.g. docker container id). I have found an example for Hashicorp Vault and an App hosted on AWS, but the general idea is the same: Secret management with Vault
In addition to the first answer, with the context of running applications on Azure VM, instead of using client_secret to authenticate, you can use client certificate authentication as explained in this documentation: Authenticate with a Certificate instead of a Client Secret.
In the picture above:
Application is authenticating to AAD by proving that it has the private key of the certificate (which is basically stored in CNG if you are using Windows).
Application get back the access_token and then use it to access the Key Vault.
The developer does not need to know the private key value of the certificate in order for their app to be successfully authenticated. Instead, they only need to know the location of the imported pfx (a container for private key and its certificate) in the Certificate Store.
At least on Windows, you as secret administrator can convert the private key and the certificate into pfx format which is password protected, and then deploy it into the Windows Certificate store. This way no one could know the private key unless they know the password of the pfx file.
The other approach specifics for Azure Compute, is to use Azure Managed Service Identity. Using Azure MSI, Azure will automatically assign your resources such as VM with an identity / Service Principal, and you can fire requests at a specific endpoint that are only accessible by your resource to get the access_token. But be wary that Azure MSI are still under public preview, so please review the known issues before using it.
The picture above explain how Azure Resource Manager assign a Service Principal identity to your VM.
When you enable MSI in a VM, Azure will create a service principal in your AAD.
Azure will then deploy a new MSI VM extension to your VM. This provides an endpoint at http://localhost:50432/oauth2/token to be used to get the access_token for the service principal.
You can then use the access_token to access the resources such as Key Vault which authorize the service principal access.

How to use File.Encrypt from ASP.NET

I have a simple C# ASP.NET MVC app (on Windows Server 2012 R2 & IIS 8.5) for uploading files to a server. I would like to automatically encrypt these files using File.Encrypt(path-to-file), but I get
System.IO.IOException occurred
HResult=-2146499771
Message=The requested operation cannot be completed. The computer must
be trusted for delegation and the current user account must be
configured to allow delegation.
IIS is running under the default IIS_IUSRS account, which has "Full Control" rights to the folder in question.
What I am trying to accomplish is a simple Web app where sensitive files can be uploaded by clients, which then can be accessed by authorized users only via the Web app (with no direct access via the file system, since only the encrypting user account can decrypt the files).
I realize that this solution has shortcomings, but so does public / private key based solution (you get stuck with the problem of where to securely store the private key for decryption). What I am primarily interested is a solution to my specific scenario.
How can I get this working?
I got this working by creating a user (with minimal rights and a strong password) specifically for the app pool and using it as the App Pool Identity.
I originally wanted to avoid doing this (I thought it would be less secure), but according to Microsoft's "Security Best Practices for IIS 8" (https://technet.microsoft.com/en-us/library/jj635855.aspx), it is not a problem:
Using a custom identity account is acceptable, but be sure to use a different account for each application pool

Risks of a Non Trusted Connection to SQL Server?

What is the risk of not using a trusted connection?
For example here is a scenario: I have created a very simple application which only has 4-5 lines of codes which uses an SQL connection with my connection string within web.config, and sends a select command to my database, and display results in an interface.
What are the security weakness here?
Edit:
I know trusted connection is related to authentication, what I wonder is I don't know how can the system be hacked if I don't use it ? (I will use my application at my company's servers and the application is a public application, so every company member can use it, so why do I need a trusted connection if it is a local company application ?)
To look at it the other way around, the main benefit of trusted connections is that you do not have to manage passwords in your application. If your application needs a password to connect to SQL Server, then where do you put the password (or connection string) so that the application user (or other developers, or sysadmins, or external consultants, etc.) cannot read it but you can still change it easily when required?
Passwords in files or the registry can often be read by users because when they run the application it has to retrieve the password, therefore the user needs access. Or a sysadmin or consultant has access to the filesystem where an application config file is. Obfuscating the password with some form of encryption is possible, but then you have to secure and manage the decryption key. Hard-coding the password in the application makes it difficult to change and also makes it highly likely that the password will be visible in the source control system, which is typically a relatively insecure system (in practice, if not by design). You can create a web service that the application gets the password from on startup but then you have to authenticate access to the service somehow.
Using trusted authentication avoids all of this completely by making the operating system responsible for authentication and unless you are a world-class security programmer, the odds are good that Windows provides a more reliable mechanism than you can create yourself.
I will use my application at my company's servers and the application
is a public application, so every company member can use it, so why do
I need a trusted connection if it is a local company application ?
Security risks in non trusted connection lies how you store SQL server passwords and use them in application. if you store passwords in config file or hard code in program, any other developer who has access on your code can view it and on the worst can change database in such a way that may break application or steal sensitive information. it will be a privacy breach as well and your company may be sued for this ( you can't just imagine what can happen).
#Pondlife has also elaborated very well.
AFAIK, the only extra layer of security a trusted connection gives is authentication. If you use a trusted connection then Windows will authenticate your connection in Active Directory.
A quick google yields this link:
What is a Trusted Connection?

Resources