Storing and encrypting SMTP credentials in the registry - c#

I have a username and a password for an smtp server. Currently they are hardcoded in my code:
string userName = "username";
string password = "password";
Currently, anyone who disassembles my dll could see these strings, correct?
I wish to store these securely in the registry, in case of future changes to the smtp server, and/or the credentials. I am not worried about the smtp server address string's security. I am only worried about the credentials' security.
How do I do this without hard-coding the credentials anywhere? I wish to see encrpyted strings in the registry.
I can encrpyt the password, then store the encryption in the registry, delete the password from the code, and use the decrypted password assuming that it is correct. However, wouldn't someone who disassembles my code still be able to decrypt the encrypted string stored in the registry?
What is the safest way?

At some point, no matter how many layers of security you have, the code will have to use the unencrypted password. That means that someone with enough access to your system to view and/or modify the registry probably has plenty of access to your code to get your password no matter what you do.
I know as developers we tend to work with paranoia = Paranoia.Maximum; a lot, but sometimes you have to back it down some.
That said, there are some things you can do. If the credentials need to be that secure, consider storing them, if possible, in a remote database. You can store them encrypted on a remote server so that anyone having access to your machine won't necessarilly have access to the DB Server.
If you really want to turn the paranoia up, and make security the user's responsibility at the same time, have them provide a "secure location" for a file that contains the data. You can then recommend that the location be something like a thumb-drive which would be removed physically from the computer when your program is not in use.
In any case, with security, you want to think in terms of layers. No one thing you do will be sufficient for really good security, but by layering several measures you can increase security to the point it should be sufficient for your needs.

The problem is not new. Operation system starting with Windows XP hat credential API which can be used in different scenarios. For example CredRead (see also http://www.pinvoke.net/default.aspx/advapi32/CredRead.html) and CredWrite can be used to save in encrypted form any general credential information. In the corresponding fields of CREDENTIAL structure you can define for exaple the level of persistence the saved credentials (logon session, all subsequent logon sessions on this same computer or to other logon sessions of this same user on this same computer and to logon sessions for this user on other computers).
If you want that your application only read the credential information you can use CredWrite in a separate configuration utility used by administrators or use the API as a part of setup of your application.

Related

How to encrypt and decrypt sensitive information in C# without a user-entered password

Forgive me if this is a stupid and obvious question, but I'm having trouble googling for the correct resources. I'm not a security expert and I'm struggling to understand how to properly go about this.
Here's the scenario. I have an internal application on an internal server: not something that will ever go out to a client site. This application has a database of username and password pairs that are used to talk to secure web services. I have no need to keep these passwords secret from colleagues, but I want to protect them in case the server is attacked and the data stolen.
Traditionally one would salt and hash them. This is a process I understand in principle but it depends on the user entering a password which can then be validated against the stored hash. That's not the case for me.
So: searching around there are various solutions that use a fixed "pass phrase" to secure a string. Here's a one example, https://stackoverflow.com/a/10177020/271907 and here is another https://stackoverflow.com/a/10366194/188474.
However, as I understand it neither of these offers a useful solution in my case. That "pass phrase" is going to have to be stored somewhere for my application to do its work. If I hard-code it into the application it can be reverse engineered. If I encrypt it and put it in a separate file it can be stolen and worked out using a rainbow table.
I looked into using reg_iis to encrypt a key as per Encrypting Web Config using ASPNET_REGIIS but, to be honest, that just left me even more confused. I'm not even sure whether or not these encrypted config files can be ported between machines or whether I'd have to re-encrypt between dev and test and live. I don't know how secure they are either: AFAIK there has to be a key somewhere and if there's a key it can be broken.
To further muddy the waters I found this answer which doesn't use a key: https://stackoverflow.com/a/10176980/271907. However the author admits it's out of date and I have no idea how secure the result is.
Is there any kind of sensible approach to solving this problem that doesn't leave a hole in the security somewhere?
Any solution where you decrypt the password to check it is going to fundamentally be insecure because your application must always know how to do that decryption.
You can make it harder by not storing the decryption key in the code, but wherever you put it a hacker that can compromise your code can probably access anything it can access too.
Even if your application security is rock solid; your passwords are still plain text in your DB and if that gets compromised then lots of your users are exposed.
That said - this is an internal-only, low risk system. Your best course of action may be to let your bosses know the relative risk vs the cost of proper security and let them make an explicit business call (and carry any future blame).
The only way of doing this without leaving a hole in the security is by hashing and salting the passwords with a one-way algorithm. The fact that current passwords are plain text shouldn't be a problem - there are lots of ways to push users to encrypt them, but easiest is just to do it for them: next time they log in, if they have a plain text password encrypt it. Then after a suitable wait (depending how often your users log in) remove the old password and check against the new hash.
The golden rule is: if you store passwords you must hash them in a way you can't reverse
The only other option is for you to not authenticate at all - use NTLM or AD or OAuth to get some other service to authenticate the user and just trust that source instead.
If instead you're looking to secure the credentials the application uses itself then you have a similar problem, but the focus shifts. You still can't do much to avoid exposure if the host machine is compromised, but most attacks will only target files.
This can be a problem if all your connection details are held in a web.config or appsettings.json as compromising those files can expose your SQL server or other service passwords.
This is where you can use ASPNET_REGIIS - it lets you add secret configuration that IIS can access, but that isn't held in plain text with the web files.
In .NET core there's new Microsoft.Extensions.SecretManager.Tools that do the same thing.
Both of these add a layer of protection for any application credentials that would otherwise be stored in plain text on disk. Attackers must compromise the machine to get at them, rather than just the files.
In both cases these configuration details are no longer portable - you'll have to set them up again (and re-encrypt) on each server.
However, you only really need the additional protection in live - in development or testing sandboxes you can just use the plain text config, and then override the details with the encrypted settings on the live server.

How to save SQL server password

We have an application running multiple services and executables. Some one them need to access the SQL database, so I need to store the SQL server password somewhere. To avoid direct access to the password, the password is stored encrypted. To decrypt the string, a crypto DLL can be called, returning the plaintext password. Whats bothering me is, how to avoid that anyone can decrypt the password. The following options had been discussed and discarded, because they do not solve the problem of more or less direct access to the plaintext password:
The crypto dll contains all required information to decrypt the password: any malicous user may call the DLL to decrypt the password with his own component
Using DPAPI, I need to set the scope to LocalMachine, meaning any user logging on to the local system may decrypt the password.
2a. Using DPAPI and a service component running with special account would solve the "any local user can use the Unprotect method of DPAPI to decrypt the password" problem, however, the malicous user still can call the crypto service with his own component.
The crypto DLL requests a password, and encrypts/decrypts using a RijndaelManaged instance. Every calling DLL must know the password, meaning I just moved the problem to another component.
Integrated Security is not an option, customer's security policies deny to use IS
Any pointer how to solve this?
If it's a publicly available application, then you would be best to avoid storing any SQL connection string details in the winform app itself.
Instead, host a web service that the winform will communicate via.
This will ensure a malicious user cannot get your SQL connection details (at least, not from the winform app or associated dlls) and allows you to hide your SQL server away from the net.
There are many ways to secure a web service so that it can only be accessed by "approved" clients. (User authentication tokens, etc )
This will depend how far you think a user in the system will go to get at the connection string.
Do they need domain access to use your application?
Can you restrict IP addresses into your SQL server?
Do users have admin rights on their machines?
e.t.c.
Things like the above will narrow down the potential users that can gain access.
Some other things that seem to stand out are:
Move the KEY and IV outside the DLL as that seems to be the single point of failure if its stolen
Obfuscate the key and iv in your application code or store in certificates, possibly with DPAPI
Lock down access to your program files, make the application run under a restricted user.
Some other tips are here:
handling key and iv values
storing key in certicates
restrict SQL access by IP address
you could set the crypto dll's current public interface to internal only.
Then, using the InternalsVisibleTo attribute, you can specify one or more specific assemblies that can actually see those internal interface methods.
This will allow you to restrict access to your crypto library.
reference here: InternalsVisibleToAttribute Class
EDIT 1
The only downside to this would be if the malicious user was to decompile your crypto dll.
Whilst you can make this difficult to achieve, you can't avoid it altogether in .Net.
Also, you don't make mention of what level of risk (internal/corporate app, publicly available app, etc), which makes providing the best answer quite difficult.
(I say best answer, as there's no guarantee to any cryptography :))

What is the potential security risk of including the db password in the web.config

The Entity data Model wizard says :
This connection string appears to contain sensitive data (for example, a password) that is required to
connect to the database. Storing sensitive data in the connection string can be a security risk. Do you want
to include this sensitive data in the connection string?
I have included the db password in many live projects, How risky is it?
It is all about minimizing your risk. Lets say a attacker found a way of getting a copy of the code from the server but not a way to execute code on the server:
If you stored the username and password in the code the attacker now has direct access to your database with the same privileges as your code.
If you used integrated authentication the attacker still does not have any way to get data from your database as he can not impersonate the user to perform integrated authentication.
If you use proper IIS encrption you must be able to execute code on the server itself (the encryption key is tied to the server not the code) to be able to get the username and password. So the attacker still would not have access to the database.
Risk is something only you can evaluate. Is it a test server in your bedroom that is not connected to the internet? Not much risk. Is it an internal company server for a small company without any real sensitive information? Maybe not much risk.
Is it connected to the internet? It's risky. It's always risky if you're connected to the internet. Why? Because the internet is not a safe place. It doesn't matter how big or small you are, you're a target. There are automated bots that roam the net looking for vulnerable systems and automatically taking them over. Then, they infect the systems with Malware to spread to your users. Or they sell your credentials to other hackers so they can use your servers for command and control centers for spam networks. Or any number of other situations.
If you're on the internet, you are at risk. Period. So always take security seriously.
It comes down to how secure is your domain and IIS on your web server? IIS and web.config is at the root of your web application. If you have problems with domain security and people being able to access your inetpub or wwwroot directories and their children, then your website is always at risk. If you are using a third party provider such as go daddy or 1 and 1, they are relatively secure.
If you are hosting it yourself, you want to limit access, especially directory listing privileges. You want to mitigate permissions as much as possible. Also with your SQL Account you use for your web applications, limit database privileges and mitigate access as much as possible. Also do not use generic accounts for access, and have each web app with their own account. In a domain, you want to make sure you take the necessary precautions in your DMZ to help secure that web server if it sits on the edge of your network.
Internal threats are more prevalent than external threats. Those already on your domain with elevated privileges may already have access to your root of your web application without you even knowing it! Keep an eye on your delegate accounts, too that IIS uses for web apps and web services.
You should encrypt the connection string using aspnet_regiis Take a look at this link too (How To Encrypt web.config), for some useful information.
With regards to other aspects of the web application, you need to make sure you are setting the least privileges possible, making sure you research all web application vulnerabilities and how to protect against these.
Replace user name and password with Integrated Security in the Connection string.
Ensure that the process using the connection executes with a user that has been registered on the SQL server with (just enough) privilegies to perform its tasks. This should minimize the risk of your system being compromised.

Hiding MySQL credentials in a C# app

I am extending an open-source VoIP softphone application (written in C#/.NET) to my needs but don't know how to best approach this issue. I want the application to connect to database when a user enters his email address to log in, and perform a SQL query to fetch his account number using that email and authenticate with account number. But, I think including my MySQL connection credentials (host, username, database) is insecure? How should I do it?
It is indeed insecure.
You need software running on the server, that can accept said email and password as input and connect to your database (so the connection string is sitting on a machine in your control), check it and return either ACCEPTED or DENIED to the client. In your case, ACCEPTED could be just the account number you mention.
Bonus points if the email and password are transmitted from client to server app over an encrypted link (public key).
You should put the connection strings into a configuration file and then encrypt that portion of the file. There's a tutorial on how to do that here: Protecting Connection Strings and Other Configuration Information. Although the tutorial is for ASP.NET, the same principle will apply to pretty much any .NET config file.
There's also a similar question here: Encrypting passwords in WinForms app.config, .NET.
Our rule of thumb when designing database applications is to always use delegation and isolation.
What isolation means is that we isolate database interaction from the end user application through the use of services (i.e. web services, wcf, .net remoting, etc). In this way, the database is never directly exposed to the user.
What delegation means is that the database access is always performed on behalf of the end user by a well-known, limited-access database user (generally the user that the service is running as). If at all possible, the database access should be performed by a user authenticated by the network rather than by storing user names and passwords in connection strings or other semi-secure locations.
Finally, one important note: you should always encrypt your end-user's login and password information before sending it over the wire. This is a little extra work, but well worth it from a security perspective.
Can MySQL do Windows based authentication (i.e. on a domain)? If so, you could use that. Otherwise you might want to have credentials to a service, or use encryption, but you would need to include the encryption key so anyone dedicated to discovering it would.
You could code your connection strings so that they end up in your assembly and use a code obfuscator to protect it from disassemblers
There are many ways to do it, including obfuscation and other ways making it difficult to use outside of the application, but not impossible to retrieve/use.
How should you do it? The best way (as far as I know) is to give the account the minimum credentials necessary so that if someone does have the username and password he/she cannot do anything malicious with it. Permissions can be set up in many ways for user-specific data, such as views so a user can only access the correct rows. Basically, if security is a top concern, assign permissions conservatively and if necessary give different users different credentials.
You should host a (php/jsp/asp) script at your server with which your application will talk. you should not store your credentials inside the app at any cost.
Tthere are so many ways to just take out the information. Especially .NET applications. it doesn't takes more that 30 mins :p

Implementing a local password within an application

CONTEXT:
I have a c# .net application made for a customer. The application has no network communication. In fact, the computer it runs on wont likely have any internet or network access.
In comes our customer with a very specific and non-negotiable request:
Request a administrative password before opening up certain screens and grant certain rights. This password must be within the application. The default password (i'll probably set it to 'password') must be changeable, so it can't be hard coded. And there ought to be some way to return to the default in case they forget the password.
It seems kind of superfluous to me just to stick a encrypted password in a file, in the application folder. Anybody who deletes the file would erase the password.
Is there some widely known strategy for this?
Again the password is local and not authenticated on any network.
Maybe hide it in the registry? If the registry key isn't there, then just remake it and set it to the default password. Hardcode the default password, maybe encrypted or something so someone who scans the .exe can't finde it. Also ask your client for what the default password should be, not simply make one.
The problem is, as long as you store something locally, everyone who really wants to know it, will find a way to get it. :/
If it is on windows (is it?)
Key Storage and Retrieval
MSDN Security Briefs Article (part 1)
MSDN Security Briefs Article (part 2)

Categories

Resources