In a CodingHorror blog post a commenter made the observation that it is more difficult to obscure sensitive configuration information (e.g. SQL Server connection strings) in a program than it used to be, because the obscuring algorithm can be disassembled quite easily with Reflector.
Another commenter suggested that encrypted appSettings could be used as an alternative.
How secure is encrypted appSettings? Is it a bank vault, a locked door, or an open window, and why? Is it ever safe to store "sensitive information" in an executable?
Encryption algoriths are secure: the main issue with using encryption for security is the secure management of keys.
Hiding keys in the application executable was never secure, but it's probably true to say that they would be easier to find in a managed executable using a tool like Reflector than in a traditional unmanaged executable.
Encrypting a configuration file can be useful on a server. For example, if you encrypt web.config using DPAPI with the machine key, only users who can log in to the server or have write access to the server disk will be able to decrypt it:
Anyone with read access to the server disk over the network, or access to a backup copy of the application directory won't be able to decrypt it.
The real question is who are you trying to shield the user and password from? On a desktop app the user is likely to have access to the database with his/her own account, no pwd needed (trusted). On a web app, the config file sits on a (hopefully) protected place. So far I didn't find many reasons to encrypt the config file.
Related
Our application has an xml file that contains information for the application to work properly. This file is generated by our web api server and sent to the client application. The client application needs to be able to read from this file, but we don't want our users to see or modify it. This file exists in their file system for a period of time while they will need to read from it. In this scenario, they are disconnected from the internet or network. We can of course encrypt it on our server before we send it, but the question remains about decryption.
If I use a public/private key method, this is sort of a pointless effort because I have to store the private key somewhere with the client. My other question, is in this way, why would I need to store the public key on the server? (especially if this file is generated every so often with a new private/public key pair when the file is requested from the server again).
I could use a symmetric algorithm, but again I have to store something with the client.
I also thought about just generating a hash for the file, but again I would have to store the salt with the client to compute the same hash and compare if the file has been tampered with (thus not offering encryption, but at least a way to know it has been modified).
At the end of the day I'm looking for a solution that just keeps our users from
seeing the blatantly obvious.
I've gone through all the XMLEncryption stuff on Msdn and SO articles, these all require key management of some kind, but are there other solutions for this scenario? Or am I stuck storing a private key with the client so they can decrypt the file?
I was here making an sql connection in a class library and I was wondering how can I encrypt/decrypt an SqlConnectionString (or other things, if need be) in a config file (whether it's config from desktop, mobile or web)?
I already have functions to encrypt/decrypt strings. But I want to have it encrypted even when outside the program, so even if someone gets to the config file he won't know what the string is.
Must I do it "manually" (encrypt it in a program and copy/paste it to the config file) or is there another way to do it?
EDIT: I just read that it'd be best if the connection string was on the internet, in an API, only. Is it true? If it's true it'd be perfect because, I'm making an app/desktop/website that all connect to the same database, which is on a server. So, all of them have to connect to the internet anyway.
If you encrypt the connection string (or any other sensitive information) using an algorithm that the app, sitting on the user's PC, can decrypt, then anyone who gets to the config file AND the app executable can decipher how it is encrypted and get to the original connection string.
For the web app, this shouldn't be an issue (assuming you secure your server so that unauthorized people cannot access it), for the desktop app, it will be.
You could put some kind of gateway in front of the cloud database such that the desktop user would have to authenticate to obtain the connection string. That, or abstract the database access by building a web API, which you can secure by OAuth or something similar, and have the desktop user authenticate before using the app. Given that the database is on the internet, that's what I would do.
What is the best method for saving passwords on a computer so that they can not be accessed? I would like to store them in the Registry encrypted. I would like you to be able to reset the password but this is not for the server. This is for storing them on a computer to remember them and sign in automatically.
IMPORTANT EDIT: I need to be able to retrieve the plain-text password from within the program, just not anywhere else.
CryptProtectData and CryptUnprotectData are your best bet on Windows. They encrypt the data using login credentials, so the passwords are safe from attacks to the disk. However, they can be accessed by any program running under the same user. I would recommend storing them in a file whose permissions prevent other programs from accessing them (such as a file that requires administrator privileges to access).
The managed class ProtectedData uses these function, so it can be used from C#.
You can also use these functions directly using P/Invoke. There is some example code that does exactly that here.
Expansion in response to additional requirements:
There is a way to ensure that your program is the only one able to access the password without needing your program to be launched with administrator privileges, though it will take a lot more work.
The basic idea is this: you create a Windows service that is installed when you install your application. It should be launched on demand from your application when it wants to store/retrieve the user's password. The service will simply provide read/write access to a file with permissions set so that only administrators can read/write it. The additional security comes from the IPC connection to the process, which will use a Named Pipe. You can then use GetNamedPipeClientProcessId (sorry, you need P/Invoke) to authenticate the request by looking up the process ID of the client that connected to the pipe.
Depending on how worried you are about security, you can verify the process ID using code signing, if you have access to a valid certificate. Or, you can verify the checksum of the executable or something of that nature.
This is the only way I can think of to create the security you are looking for on Windows. Your application should also use ProtectedData to encrypt the data before handing it over to the Windows service to protect against hard disk attacks.
I believe what I'm looking for is AES. This seems like an easy way to store a password. Of course, this is only for remembering a password on the computer so the user does not have to type it.
http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
I have created a forms application for my project. I want to host on my website for users to download and test it. Because I am using a configuration manager I have to include the config file along with the .exe as there is a back end remote database for the application. And of course I only now realize my connection string is there for all to see. I tried renaming the app.config to web.config, but the aspnet_regiis -pef command just returns a help menu when ran as admin on my vista machine! Even if this command works and I rename web.config back to app.config, will the machine which runs the app when downloaded automatically decrypt the connection string? So in conclusion what is the best way for a novice like to approach this dilemma? Why does aspnet_regiis -pef not run? I have also looked at other posts about this topic but unfortunately they have not worked for me so far.
Either create user/specific connection string, or wrap all your data access in some web services, where you can control the autorization.
Creating user specific connection string is the simplest, but may have impact on the DB charge. You can still keep one connection string, but using windows identity to connect. In both case, you will have to spent some effort to ensure users won't able to do more than what they are allowed to do.
Wrapping your data access in web services is far more manageable but will require an extra work to make it works. Maybe you can take a look at RIA Services. The advantages are multiples: you can control the permissions within the web services, and you are reducing the exposure of unwanted queries.
Please also note that even if you encrypt the connection string in the configuration file, any malicious user will be able to decrypt it. A simple decompiler will highlight your decryption key.
You could just store an encrypt the connection string in the app.config but you will have to include the encryption key somewhere in the application. Therefore this is not safe because everyone can just decompile the application or attach a debugger and extract the connection string. Or monitor the network traffic. Actually there is now way you can prevent this from happening - whatever your application can do can be done manually by everyone (with access to the application).
The flaw in the design is that the application needs direct access to the database in the first place. It is close to impossible to ensure that the database can not be corrupted in this scenario (unless the database is only used for reading data). Essentially you would have to replicate a large portion of your business logic at the database server to ensure that no sequence of requests will corrupt the state.
A better solution would be accessing the database only indirectly through a web service. This allows you to perform better and easier to implement server-side validation and even authentication and authorization per user.
I have a requirement to allow the user specify, at time of first use, the connection string with which to connect to a database, and change it later on, in Windows client application. My current idea is to store the information in a text file which is checked each time user opens the application for use, and prompts user for update if information has been deleted or is invalid. I am not however confident that this is a secure approach to handling this issue and would appreciate other suggestions to help me better manage this.
I'd store them in the app.config, as is the usual practice. You can modify the settings in code easily. Here's how
They should also probably be encrypted, which can also be done in the applicaiton's launch. You can encrypt/decrypt from code just as easily as you can modify the settings. Here's how.
You can
Use Windows Authentication for SQL so that you don't need to manage passwords.
Use CryptProtectData to encode / decode the password and save in on disk
From CryptProtectData documentation
The CryptProtectData function performs encryption on the data in a
DATA_BLOB structure. Typically, only a user with the same logon
credential as the user who encrypted the data can decrypt the data. In
addition, the encryption and decryption usually must be done on the
same computer. For information about exceptions, see Remarks.
So even though SQL and windows might have a different login if there is a 1-1 mapping your saved password encrypted text is relatively safe
I would store the connection string in either the App.Config or the registry. I do not think you can modify the App.Config at runtime, so if your application is using a database, that should be your first choice. If not, go with a flat file or the registry. You will definately want to encrypt it. See this question on how to encrypt and decrypt string and Base64 Encode it.
To start with, I would not write your own dialog to get the initial connection string; instead you could use the VS2010 database connection dialog that Microsoft have released (download from here). This will do exactly what you want without you having to do the hard work (and for pretty much any remote connection you want).
No, your persistance of the connection string information, should not cause any major security issues; as it is the connection string itself that should provide the security to the connection; you will have to ensure that the saved connection string does not contain the password - and bring up the dialog for each successive connection. If you use Windows Authentication, without passwords then of course there could be a security issue, but I would say it is down to the users to use the correct security.
If the above is not sufficent, I would store the connection string in Properties.Settings.Default and encrypt the string using one of the .NET libraries, or even a hash. There are many approaches to this, but I would go with the referenced dialog to get the initial connection string, then persist this in the app's .config with properties. Simple.
I hope this helps.