I know that the "how do I securely store a password?" questions have been asked many times here; and I know the answer is always "Never do this! Store hashes, never store passwords! Use bcrypt!"
But what about times when you cannot use a hash for authentication? For example: automated processes. Say I wrote an automation application that needs to log into an SFTP site or some sort of external service that requires a username/password. I can't use a hash to authenticate with an external service, so what am I supposed to do?
I tagged this question with C# and ASP.NET as these are the two areas that this question applies to specifically for my situation.
Edit: Due to discussion raised in the comments, let me clarify the threat I'm trying to address: I want to prevent an attacker from being able to read the plain-text password used to access the external service. Meaning that if they somehow gained non-admin access to our network or database, even with the database dump they would not be able to read the passwords in plain text.
There are different options, both using encryption for password using a key, and protecting the key storage using HSM module.
option (1): Using Database with HSM module
You can store passwords encrypted in database and benefit from a feature in SQL 2016 "Always Encrypted (Database Engine)".
Always Encrypted allows clients to encrypt sensitive data inside client applications and never reveal the encryption keys to the Database Engine (SQL Database or SQL Server).
You can use Hardware Security Modules (HSM) with Always Encrypted.
The hardware security module (HSM) is a physical device that safeguards digital keys and performs cryptographic operations. These modules traditionally come in the form of a plug-in card or an external device that attaches directly to a computer or to the network.
When you get an HSM, you also get a software libraries implementing common APIs, such as Microsoft Crypto API and Cryptography API. These API are called Cryptographic Service Provider (CSP) and Cryptography API: Next Generation CNG providers.
Your applications can communicate with an HSM using those APIs.
For more securing the HSM module, you can:
- Tie the HSM to your Database Server.
- Tie the HSM to your admin login to Operating System Server.
for more details:
Always Encrypted (Database Engine)
Using Hardware Security Modules with Always Encrypted
Also, Oracle database and other engine can provide encryption with HSM
Securing Stored Data Using Transparent Data Encryption
Option (2): Store password in files in Protected storage using HSM module:
Encrypting files that contain passwords. This may be done by the operating system, an application, or a specialized utility such as password management software that is specifically designed to protect the confidentiality of passwords.
Using OS access control features to restrict access to files that contain passwords. For example, a host could be configured to permit only administrators and certain processes running with administrator-level privileges to access a password file, thus preventing users and user-level processes from accessing passwords.
As you are not using hashing, I exclude this option, but it's a mechanism for storing one-way cryptographic hashes for passwords instead of storing the passwords themselves.
AES encryption and store the key in an external encryption key storage module, if you happen to have access to one of those.
Otherwise, you could try scattering parts of the encryption key on different servers or something but it shouldn't be the first choice.
In my opinion, this shouldn't be solved with a HSM, as that also needs a password that you would need to save. Better is to always type in the password only when restarting the system (a server seldom restarts, so that's ok). The RAM is more or less safe (see here). See for discussion of small projects that have a maybe physical server that have a crontab here.
Related
If I have a stored key file used to decrypt the encrypted input coming into my application, and I store that key file as an embedded resource so that it is embedded in the assembly when deploying, how difficult would it be for someone to reverse engineer the application and retrieve the key file?
Also, the application is deployed through ClickOnce "Online only" mode which I imagine would also make it more difficult to reverse engineer? (I'm not exactly sure of the workings of ClickOnce but I wasn't able to find the dll's/assemblies on my local machine after running the application in online only mode...).
Update:
As Ralf essentially answered the main question below in his comment (answer: it's not really safe at all), here's some more information so that you knowledgeable people can possibly suggest a better security model.
The encryption will be used to encrypt the login password for my application, to be used in a SSO setup (the user will first sign on to a different system and then by clicking a link will be able to directly open my application without having to enter in their login details).
The encrypted data will be sent as a base-64 string URL parameter in the link that will launch the my click-once application.
I will also be developing the application that will create the encrypted data for the URL parameter (clarification: not the first application the user will sign in to for the SSO, I will only be creating a small tool to convert the plain text password into an encrypted base64 string).
It's only an internal application so bullet proof security isn't essential and ease of deployment is more important, but it'd be nice to know what the best practices and different options that are available.
Whether in clear text or encrypted, you don't want to store the password. When you get a password, all you should do is pass it to your server app where you compare it against the salted hash of the password you have in the DB. Even if you don't think security is that important, you need to take care with the password because people frequently reuse passwords across different systems. I know they shouldn't but they do.
If you want to implement a single sign on (SSO), create a sign on token on the server side and pass it back to the client, either encrypted or signed (HMAC is a good choice for signing). This is an unforgeable token because you need to know the encryption key or shared secret for the HMAC and that data is only known on your servers. So you have your SSO and all data involving the SSO is managed on servers so there's no data leakage or chance of spoofing.
As long as the aplication can be launched, the files have to be somewhere on the computer. You just have to know where to look. The reverse-engineering may be ugly but it is always possible. The computer has to be able to understand what he is supposed to do so you only have to extraxt the information one is looking for. Therefore the security of your application should never depend on the difficulty of reverse-engineering! I believe that a secure application should be open-source anyways.
You propably need a diffent security model. The important thing here is that you know against what you want to protect the data. If you simply want that you know the data is sent by the server and not somebody else (man in the middle attack) you could use digital signatures instead.
If you do not want anybody to read any data sent between server and client you should use some sort of ssl implementation to create an encrypted channel. Then you only need to watch out that the public key of the server is not altered on the client. This may be done by an certificate of an official CA but unfortunately those are usualy not for free.
I am currently writing a c# mvc web application in which password are being taken from a user and stored in a database - sql server. I need a way of hashing the passwords.
It has been recommended to be to use the Data Protection API (DPAPI). I am not familliar with it and from research on the internet, very little information exists on it.
Can anyone point in the direction for further information on it? OR give me an overview of how to set it up and work with it etc.
The Data Protection API is primarily used for protecting cryptographic keys and secrets under a users credentials. If you want to store hashed passwords in a database, the DAPI isn't really what you want.
The ASP.NET Membership Provider is used for managing users, including hashing passwords with a salt. Unfortunately there doesn't seem to be a method to just return a hashed password, so if you don't need the extra functionality, it might be worth extracting the relevant code from something like CodeFirst Membership Provider (See Crypto.cs in the Source Code). The advantage here is this Membership Provider uses PBKDF2 to derive the hash, which is more resistant to brute force attacks given the number of rounds. It's also the method StackOverflow itself uses.
.Net has a wrapper class for the DPAPI called ProtectedData. It it very easy to use, and contains just two static methods: Protect and Unprotect. A How-to article can be found here. The DPAPI does not require a key because it uses either the logged-in users's credentials or the machine's credentials to do the encryption, depending on what scope you choose when calling Protect. Note that if you intend to store the encrypted data in a database, you must be sure to always use the same windows user account or machine (again, depending on the encryption scope), or else you will not be able to decrypt the data. Thus, depending on your application, this API may not be optimal. It is primarily intended for doing local encryption on a single machine rather than for distributed applications.
I am using C# and SMO to successfully detach and attach an SQL server database.
I was wondering if it is possible to password protect the detached database? Preferably via C# other suggestions also welcome. I am not too familiar with SQL Users and permissions.
(Background: We use a transfer database to transfer information to offsite units without internet connections via contractors. These databases have sensitive information. We would like that the information not be accessed by a savvy contractor)
What you describe does not have anything to do with SQL Server / SMO or whatever - just encrypt the files you want to transfer with some password and a good algorithm (like AES256) and keep the password secret between you and the offsite unit. Use a new cryptographically strong password for every transfer (never use a password twice!).
IF you want to verify that the file has not been tampered with create a digital signature for every encrypted file you transfer (use an asymmetric algorithm for that like RSA). you keep the private key a secret from everyone... for verification of the signature(s) the public key is sufficient - the public key can be known to the whole world without compromising your security.
I have an asp.net application, accessed by people over the internet using web browsers. It runs on a web server and it talks to a backend database.
Some of the users would like to use the application to store some private data. The requirements of this are:
1) Only the user who stored the data should be able to see it.
2) The developers/dbas should not be able to see the data.
3) If the web server and database server were compromised a hacker must not be able to decrypt the data.
So, it's obvious I'm going to have to encrypt this data. If I encrypt it there will be a key somewhere and probably a salt/IV. The question is where do I store the data which is used to perform the decryption? If I store it in the database or the web server then a developer, dba or hacker can access it and decrypt the data.
I think my ideal solution to this would be for the private key to be on the clients machine, that way they are entirely responsible for it. But I'm not sure of how to go about this with an asp.net web application.
I believe I can create a certificate which also stores a private key (PFX). The client companies could use group policy to deploy the certificate to their domain. But it is possible that the ASP.Net application can request the web browser to send the private key to it so that it can perform the decryption? Decrypting on the client would be best but other than creating something in javascript I don't see how this is possible.
Any advice welcome.
Store the key in the mind of the user. Use any password/passphrase based key derivation algorithm you like. The standard is PBKDF2. The optimum choice of algorithm will depend on precisely what your security requirements and threat mode is. Ideally, that decision and the implementation should at least be reviewed by a security expert.
Is it possible that you deploy a ClickOnce application as a part of your solution? The ClickOnce could easily access the cert store on a local machine thus allowing you to perform client-side encryption.
I would like to use TDE, but I cannot use it, so I have chosen to use the EncryptByCert and DecryptByCert functions. However, I was also considering encrypting/decrypting data in c# as shown here.
My question is are EncryptByCert and DecryptByCert unsecure because the certificate is also stored in the database? How do people get around this problem?
Is using the c# built-in encryption a better idea?
Thanks in advance for any help. :)
There is an Encryption Hierarchy one has to deploy:
(source: microsoft.com)
The root key used can be the service master key (actually the root is the service password, but this is transparent to the service start), in which case the applications can access the data just by simply connecting to the database and decrypting it. This protects the data if the database file is lost accidentally, but does not protect the data against compromised access to the server: since the decryption key is held by the server itself (the service master key) then anyone that has access to the data can see the data, because anyone can decrypt it. The data is protected through normal access rights and permissions, but the cryptography does not add any protection against authorized users.
The other option is to rely on a password at the root o encryption hierarchy, in which case the application must ask the user for the password to access data. For instance, if is a web site , the user would have to fill in a data decryption password in order to access a specific page. This truly protects the data cryptographically against users that gain access to the data through ordinary data access permissions and don't know the password(s).
SQL Server 2008 also offers the possibility to leverage a hardware TPM to store the decryption key (ie. an employee badge) but this is Enterprise Edition functionality only.
Ultimately, asking if the SQL Cryptographic API is secure or insecure is a non-question. The API itself of course is secure. Encrypting with the data with a symmetric key and then encrypting the symmetric key with a certificate and storing the private key of the certificate along with the data in the database is secure, as long as the private key is properly protected. The security or insecurity of a cryptographic deployment it always ultimately driven by the key management (bare some faulty implementation, but lets assume the implementation is perfect) and key management is 1% application design and 99% human process.
Ultimately, you need to do a serious threat modeling (sorry, but "The threat is that the data is private information and should not be seen plain text." is not threat modeling). Follow a methodology like STRIDE, or other similar methodologies. This is a very hard domain, and is deceptively simple to read about cryptographic APIs and believe that you know how to protect data:
The world is full of bad security
systems designed by people who read
Applied Cryptography