I need to encrypt sections of my web.config file for a client. Most of the references I've seen are to using aspnet_regiis to do the encryption. However, as far as I can see, this needs to happen on the web server which will host the site, which means the encrypted values will be different for each server. I don't have access to this client's servers. I found a passing reference to the possibility of encryping the web.config data in a way that is portable across servers, but haven't found any more detailed information. Does anyone know how to do this?
you need to encrypt it using RSA because with the RSAProtectedConfigurationProvider you could copy your key across server.
Web Farm Scenarios
You can use RSA encryption in Web farms, because you can export RSA keys. You need to do this if you encrypt data in a Web.config file prior to deploying it to other servers in a Web farm. In this case, the private key required to decrypt the data must be exported and deployed to the other servers.
Using the RSA Provider to Encrypt a Connection String in Web.config in a Web Farm
To do this, you must create a custom RSA encryption key container and deploy the same key container on all servers in your Web farm. This won't work by default because the default RSA encryption key, "NetFrameworkConfigurationKey", is different for each computer.
So, scrool down to the "Web Farm Scenarios" section of the above link and follow the steps.
Related
Looking here: https://msdn.microsoft.com/en-us/library/dtkwfdky.aspx
They encrypt the machineKey in the web.config as well as the ConnectionStrings.
Is this because, when using a custom machineKey per site, it will use the machine key to encrypt the connection string?
Or is the machine key just used for view state encryption? And therefore it's prudent to encrypt it to help protect the application?
MachineKey is used only to encrypt/decrypt/validate ASP.NET cookies and anti forgery tokens and it handles mostly USER data related security. MachineKey has nothing to do with decrypting configuration values. ASP.NET will not use MachineKey to decrypt connection string.
Infact MachineKey is as sensitive as connection string, because after obtaining it, someone can easily create an authenticated cookie which will allow them to login to any user. That's why it should be encrypted.
You have to encrypt MachineKey by yourself.
I was wondering what the best (most secure) way to encrypt Web.Config files in an ASP.Net MVC 4 Application are? I have some background with developing in-house applications using C#, but we never focused too much on encryption due to other security that was already in place.
EDIT: My host Server is ORACLE if that changes anything? A friend mentioned perhaps using aspnet_regiis.exe after deployment of my code with the '-pe' argument. Anyone have any pros/cons for this method?
EDIT2: ORACLE is a Database, not a Server! Can I go home yet?! >_<
The typical way is to use a ProtectedConfigurationProvider to encrypt the sensitive sections. There are several existing implementations. You can also implement your own if needed.
I was wondering what the best (most secure) way to encrypt Web.Config files
"Most secure" depends on what threats you are trying to protect against. You can assume that all the standard cryptographic algorithms are secure, but by encrypting web.config, you've simply exchanged the problem of protecting plaintext credentials in web.config for the problem of protecting an encryption key.
Typically you'll use Protected Configuration to encrypt web.config.
If you use the DPAPI provider, you'll encrypt using the server's machine key. This means that the encryption can be broken by anyone who can log in to the server. Also by anyone with write access to a folder containing a web site on the server, because they can upload code, say an aspx page with embedded script, that can do the decryption. This is a good choice if:
your server is secure (not shared with other untrusted applications, e.g. a hosting environment)
you don't want to copy the web.config to other servers (e.g. in a web farm) - it needs to be encrypted independently on each server.
Alternatively, if DPAPI doesn't meet your requirements, you should probably use the RSA provider. You can protect the key with an ACL against unauthorized access by other users on the same server, and can share it across multiple servers.
You can use the CryptoAPI to encrypt individual configuration values.
You can use the DPAPI to encrypt entire sections.
I am in .NET 4.0 paradigm and I noticed a scenario. My API was using FormsAuthentication.Encrypt method to create a token for the user. the problem is that if I run the API on localhost, call the api to get the key, I can use the same key on subsequent request to the server. Why is this happening? Is this desired behavior? Isn't it a security risk?
The problem was that we were overriding the machineKey value in our applications web.config. So both applications (running on local machine and server) were using same keys to encrypt and decrypt. Hence, it was possible for server to decrypt key encrypted by local machine and vice versa.
I want to encrypt the connectionstrings in my web.config. And my application will be deployed in web farm.
I tried reading some blogs about this, but got confused.
Can somebody tell me a link which they have really tried and got succeded.
You may have considered this, but if not: the RSAProtectedConfigurationProvider can use either machine-level or user-level keys to encrypt. The default is machine-level. This means you can't encrypt your web.config once and deploy it to every machine in your web farm. You must encrypt it on each machine since the key to encrypt and decrypt only exists on that machine.
You can get around this problem by using a user-level key or sharing a key across all web farm machines:
Import/Export keys - http://msdn.microsoft.com/en-us/library/yxw286t2(VS.80).aspx
Machine-level verus user-level key containers - http://msdn.microsoft.com/en-us/library/f5cs0acs(VS.80).aspx
We use the RSA Protected Configuration provider. That page isn't light reading, but it's got what you need.
I recommend the command like so (example from the article):
aspnet_regiis.exe -pef "connectionStrings" C:\Projects\MachineRSA
Before encrypting the connection strings, think about what you are trying to protect against by encrypting them. Your application will need access to the cleartext connection string in order and therefore will need access to the key. Therefore, an attacker who compromises your ASP.Net application will likely be able to steal the key and your protected connection string. So encryption is not really adding much benefit.
Instead of encryption, focus on how that file is handled by operations personnel and the file permissions that are applied in production. Only allow Read access to the ASP.Net worker pool account that your application runs as.
I was wondering if anyone had successfully used DPAPI with a user store in a web farm enviroment?
Because our application is a recently converted from 1.1 to 2.0 ASP.NET app, we're using a custom wrapper which directly calls the CryptUnprotect methods. But this should be the same as the ProtectedData method available in the 2.0 framework.
Because we are operating in a web farm environment, we can't guarantee that the machine that did the encryption is going to be the one decrypting it. (Also because machine failures shouldn't destroy our encrypted data).
So what we have is a serviced component that runs in a service under a particular user account on each one of our web boxes. This user is a set up to have a roaming profile, as per the recomendation.
The problem we have is that info encrypted on one machine can not be decrypted on another, this fails with the win32 error:
'Key not valid for use in specified state'.
I suspect that this is because I've made a mistake by having the encryption service running as the user on multiple machines, hence keeping the user logged in on more than one machine at the same time.
If this is the problem, how are other using DPAPI with the User Store in a web farm environment?
In a web farm environment, rather than using DPAPI to encrypt/decrypt your data directly, you would instead use it to encrypt the key that you later use to decrypt your protected data.
You would "install" the key onto each server as part of the deployment process. The installation script would need to run under the AppPool's identity, and could store the encrypted key either in an app.config file or in the registry.
The encrypted data itself could be stored in a central repository / database, so that it can be accessed by all servers in the farm. To decrypt the data, the web app would retrieve the encrypted key from where it was installed, use DPAPI to decrypt it, then use the result to decrypt data that comes from the central repository.
The downside is that the cleartext key might exist on the local disk for a short time during the initial install process, where it might be exposed to operations staff. You could add an extra layer of encryption, such as with the web.config machineKey, if that's a concern.
The Microsoft poster is wrong.
http://support.microsoft.com/default.aspx?scid=kb;en-us;309408#6
"For DPAPI to work correctly when it uses roaming profiles, the domain user must only be logged on to a single computer in the domain. If the user wants to log on to a different computer that is in the domain, the user must log off the first computer before the user logs on to the second computer. If the user is logged on to multiple computers at the same time, it is likely that DPAPI will not be able to decrypt existing encrypted data correctly."
It appears that DPAPI will not work in a farm setting. I think this is a rather large oversight on Microsoft's part and makes DPAPI almost useless for most enterprise applications.
I just saw this. There is a way you can make this work, and that is to make sure the machines in the farm are in a domain, and use a domain account to encrypt and decrypt the data (ie; run the application under the domain account)
You cannot use DPAPI in the manner you want with local accounts because the key material is not exchanged between servers.
hope that helps!
Twelve years later . . . you can try using CNG DPAPI, which was meant to work in cloud environments that may or may not be load-balanced. From that link (in case it gets taken down):
Microsoft introduced the data protection application programming
interface (DPAPI) in Windows 2000. The API consists of two functions,
CryptProtectData and CryptUnprotectData. DPAPI is part of CryptoAPI
and was intended for developers who knew very little about using
cryptography. The two functions could be used to encrypt and decrypt
static data on a single computer.
Cloud computing, however, often requires that content encrypted on one
computer be decrypted on another. Therefore, beginning with Windows 8,
Microsoft extended the idea of using a relatively straightforward API
to encompass cloud scenarios. This new API, called DPAPI-NG, enables
you to securely share secrets (keys, passwords, key material) and
messages by protecting them to a set of principals that can be used to
unprotect them on different computers after proper authentication and
authorization.
In .NET Core this looks like
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.ProtectKeysWithDpapiNG();
}