In my applications web.config file I have a connection string stored.
I encrypted it using
'---open the web.config file
Dim config As Configuration = _
ConfigurationManager.OpenWebConfiguration( _
Request.ApplicationPath)
'---indicate the section to protect
Dim section As ConfigurationSection = _
config.Sections("connectionStrings")
'---specify the protection provider
section.SectionInformation.ProtectSection(protectionProvider)
'---Apply the protection and update
config.Save()
Now I can decrypt it using the code
Dim config As Configuration = _
ConfigurationManager.OpenWebConfiguration( _
Request.ApplicationPath)
Dim section As ConfigurationSection = _
config.Sections("connectionStrings")
section.SectionInformation.UnProtectSection()
config.Save()
I want to know where is the key stored, and also if somehow my web.config file is stolen, will it be possible for him/her to decrypt it using the code above.
The user keys are stored in:
[Letter]:\Documents and Settings\[User]\Application Data\Microsoft\Crypto\RSA
Machine keys are in:
[Letter]:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
If someone has the file and the keys then yes, they'll be able to decrypt. If only the file, no they won't be able to.
Also, if they decrypt using the same code on the same server, then yes. However, if they reach your server, it's all over anyways.
EDIT to add into the answer from comments:
Q: If I copy the key and paste it in some other PC along with the web.config, will it be decrypted?
A: If i'm not mistaken, the key will only work on that machine unless you do an import/export. However, as I say, if someone has gained access do this, you will be "dead in the water" already, as the compromised server will be devastating.
Q: I created one more web application and encrypted it.I see that no new key is created there.Did it use the same key for the 2nd application?
A: As far as I know, yes. The keys are generated per machine, per user to my knowledge.
Related
I have an encrypted password in a connection string, contained in a web.config file. I do not know what the password is, and thus cannot connect to my database.
I ran aspnet_regiis.exe -pdf against the web.config and received the following:
Decrypting configuration section...
Succeeded!
I guess I had assumed that the password would be displayed on the screen, or something close to that? Then I thought the program might create a log file with the information in it? Couldn't find one.
I know I am missing something fundamental, I just don't know what it is.
You cannot decrpty the encrypted password.
The whole point of encrypting the password is so that no one is able to decrpty and find what the password is unless you know the key.
When you encrypt the connection string, the key is automatically created and stored in the machine where the encryption was done.
So, if you copy the web.config file to some other machine and do the decryption using:
aspnet_regiis.exe –pdf “connectionStrings” YourPathToWebConfigFile
This won't work.
And to answer your question, if the encryption and decryption was done on the same machine, then your web config file will change automatically with the plain text (decrypted data) for connection string , not that the password would be displayed on the screen.
Run below command
aspnet_regiis.exe –pdf “connectionStrings” C:\inetpub\wwwroot\MyApplication
C:\inetpub\wwwroot\MyApplication needs to be the path where your web.config file is. Once you finish executing above command check your web.config file. If it worked OK you will have decrepted connection string section.
I have done the following...
private static IDbConnectionProvider CreateSqlConnectionProvider(DbConfig dbConfig)
{
return new QcDbConnectionProvider(() =>
{
SqlConnectionStringBuilder csBuilder = new SqlConnectionStringBuilder();
if (!string.IsNullOrEmpty(dbConfig.DataSource))
csBuilder.DataSource = dbConfig.DataSource;
if (!string.IsNullOrEmpty(dbConfig.Database))
csBuilder.InitialCatalog = dbConfig.Database;
.
.
.
.
return new SqlConnection(csBuilder.ConnectionString);
});
}
The client is using VERACODE tool for doing code analysis and the VERACODE has detected a flaw "Untrusted initialization" at
return new SqlConnection(csBuilder.ConnectionString);
Also, the dbConfig is being initialized as shown below...
DbConfig configDbConfig = new DbConfig
{
Database = codeFile.ConfigurationDb,
DataSource = codeFile.DataSource,
IntegratedSecurity = sqlCredentials.UseWindowsAuthentication ? 1 : 0,
UserId = sqlCredentials.UseWindowsAuthentication ? null : sqlCredentials.SqlUserName,
ClearTextPassword = sqlCredentials.UseWindowsAuthentication ? null : sqlCredentials.SqlUserPassword
};
What else I need to do in order to fix this flaw? Also as per this link, I am creating the connection string using the SqlConnectionStringBuilder which is safe of creating the connection string.
Thanks in advance...
Description for Untrusted initialization issue is:
Applications should be reluctant to trust variables that have been initialized outside of its trust boundary. Untrusted initialization refers to instances in which an application allows external control of system settings or variables, which can disrupt service or cause an application to behave in unexpected ways. For example, if an application uses values from the environment, assuming the data cannot be tampered with, it may use that data in a dangerous way.
In your case you're reading data for dbConfig from file:
if (TryReadCodeFile(configurationProfileFile...)) {
DbConfig configDbConfig = new DbConfig...
}
Note that warning you get should also come with a line number (to circumscribe erroneous code). Almost everything in code you posted can generate this issue (I don't see where sqlCredentials comes from but it may even be another source of security problems if they're in clear text - or code to decrypt is accessible in your application).
From cited paragraph: "...application allows external control of system settings or variables, which can disrupt service...". This is the core of this issue: if your application uses external data without a direct control over them then its behavior can be changed modifying that data. What these external data are? List is all but not exhaustive:
Environment variables (for example to resolve a path to another file or program) because user may change them. Original files aren't touched but you read something else.
Paths (to load code or data) because user may redirect to something else (again original files aren't touched but you read something else).
Support files because user can change them (in your case, for example, to point to another server and/or catalog).
Configuration files because user can change them (same as above).
Databases because they may be accessible to other users too and they may be changed (but they may be protected).
How a malicious user may use this? Imagine each user is connected to a different catalog (according to their rule in organization). This cannot be changed and it's configured during installation. If they can have access to your configuration files they may change catalog to something else. They may also change DB host name to a tunnel where they may sniff data (if they have physical access to someone else's machine).
Also note that they also say "...assuming the data cannot be tampered with, it may use that data in a dangerous way". It means if, for example, your application runs on a web server and physical access is secured then you may consider that data safe.
Be aware your application will be secure as less secure item in your whole system. Note that to make an application safe (I know, this term is pretty vague) to encrypt password is not enough.
If support files may be manipulated then best thing you can do is to encrypt them with a public/private key encryption. A less optimal solution is to calculate a CRC or hash (for example) you'll apply to configuration files before you use them (they are able to change them but your application will detect this issue).
To summarize: you can ignore this issue but you have to prove your customer that data you rely on cannot be tampered. You can reasonably prove if at least one of these conditions is satisfied:
1) System where support files reside is not accessible by anyone else than your application. Your application security cannot be higher than system security.
2) Your support files are valid per-machine (to avoid copies between different machines) and they're encrypted in a way they cannot be changed (intentionally or not) by anyone.
3) Your support files are valid per-machine and they're hashed in a way your application can detect external changes.
4) It doesn't matter what users do with your configuration files, application itself cannot change its behavior because of that (for example it's a single installation where only one DB and one catalog exist).
The most important for connection strings is how they are stored. If they are stored in plaintext, this poses a security risk. So, it is advisable to store them in encrypted format and in application decrypt and use it.
The code on the Site here (shown below) encrypts app.config. I ran this on a button press to encrypt my config.
When am i supposed to run the code - (e.g at application start-up in case it is not already encrypted)?
In my bin folder i have 2 xml configuration files (Applicationname.exe.config and Applicationname.vshost.exe - this code only encrypts the first one of them - When i deploy my program how do i ensure that the my customer doesn't accidentally get the unencrypted file also as this would be a major issue ?(Or does the windows installer take care of ensuring this)?
C# Code
Configuration config = ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
SectionInformation appSettingsSecInfo = config.GetSection(
"appSettings").SectionInformation;
if (!appSettingsSecInfo.IsProtected)
{
Console.WriteLine("The configuration file has NOT been protected!");
// Encrypt this section by using security provider
// (RsaProtectedConfigurationProvider or DpapiProtectedConfigurationProvider).
appSettingsSecInfo.ProtectSection("RsaProtectedConfigurationProvider");
appSettingsSecInfo.ForceSave = true;
config.Save(ConfigurationSaveMode.Full);
}
Please follow steps at this page. Author of the code snippet that you reference also does mention this page. But he is wrong about it not working on app.config files. All you have to do is rename yourapp.exe.config file to web.config, encrypt the sections you want and rename back to yourapp.exe.config.
Now to your scenario. The page that I have referenced also states the following:
You can easily export and import RSA keys from server to server. This makes RSA encryption particularly effective for encrypting configuration files used on multiple servers in a Web farm.
And it has a section about exporting and importing RSA keys.
So you could encrypt the configuration on your PC, export RSA key used for encryption and put it in your installer. The installer would then import the RSA encryption key into machine or user store on PC on which the application is being deployed.
But you should realize that when the application is starting, encrypted configuration has to be decrypted using private part of RSA encryption key (that we imported or it originated on the PC). Therefore if the application can get access to the private key so might the customer (I presume that the customer has physical access to the PC with your application). What you could do is use a user key container of user that only the application will run under for RSA encryption key but if the customer has administrator rights you will not be able to forbid him from decrypting the configuration.
So much for standard solutions. But you can always put sensitive data in a custom xml file, encrypt it and the encryption key compile into you application. Then the application would have to implement a logic to decrypt the xml itself. The customer would have to decompile your application to get to the RSA encryption key.
I want to encrypt my "ConnectionString" settings which is located in app.config.
But at the Runtime, I want to use( read ConnectionString ) it directly, without decrypt it.
I mean, I don't want to anyone to decrypt the string. There should be NO decryption method.
I'm thinking; it should be like embed .net/asp.net/iis feature to use.
Like "Windows Login" ( you can enter it, use it, but you can't decrypt )
===
An Example Usage; You have small website with some critical data.
You have no money to buy private server,
so you are working on shared server, if the server hacked somehow,
you application and database will be stolen.
But if you put encrypted connectionstring in app.config,
This will be hard to decrpt it and see what is inside in Database.
Encrypting and decrypting configuration settings in a config file can be done from the command line using the aspnet_regiis.exe tool.
The details are described in the following MSDN article:
Encrypting and Decrypting Configuration Sections
As the tool is mainly intended to be used with Web applications, it expects the config file to be named 'web.config'. This means that you temporarily will have to rename your app.config file to web.config:
rename App.config web.config
aspnet_regiis -pef connectionStrings . -prov DataProtectionConfigurationProvider
rename web.config App.config
DPAPI might be a solution.
You can connect your usr/pwd/credentials to the machine. JGalloway knows more about this than I. JGalloway knows more about anything dotnet than I.
http://weblogs.asp.net/jgalloway/archive/2008/04/13/encrypting-passwords-in-a-net-app-config-file.aspx
If I haven't mixed things up this creates a usr/pwd combination that is bound to the very hardware of the machine. I.e. change network card and stuff might break. Also; one cannot create the usr/pwd/creds one machine and then transfer to another. In short this means that you have to do whatever you have to do on the production machine - might give you a headache if you are targeting continuous delivery.
Caveat: I haven't tried it myself. Instead I opted for a "regular" encryption. If someone got hold of my encrypted string and bytecode and reverse engineered it I would be smoked. But it was enough of security for me.
I've successfully signed my XML files using the RSACryptoServiceProvider. My key is stored in the Machine Key Store.
Now, I would like to check if the machinekeystore already contains the key that is related with the keycontainername or if the rsacryptoserviceprovider will need to create a new one.
How may I accomplish this?
Appreciate for your help!
Camille.
According to Key Storage and Retrieval, when Windows creates a Machine key store, it creates a file in the Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\Machine Keys directory. You could loop through the files and search for the file. See the example here called TryKeyContainerPermissionCheck for a way you might find the file.