Related
I'd like to use Windows.Security.Credentials.PasswordVault in my desktop app (WPF-based) to securely store a user's password. I managed to access this Windows 10 API using this MSDN article.
I did some experiments and it appears that any data written to PasswordVault from one desktop app (not a native UWP app) can be read from any other desktop app. Even packaging my desktop app with Desktop Bridge technology and thus having a Package Identity does not fix this vulnerability.
Any ideas how to fix that and be able storing the app's data secure from other apps?
UPDATE: It appeared that PasswordVault adds no extra security over DPAPI. The case is closed with a negative result.
(this is from what I can understand of your post)
There is no real way of preventing data access between desktop apps when using these kind of API's http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx tells more about it. You'd probably just want to decrypt your information.
memory access restriction is difficult, code executed by the user is always retrievable by the user so it would be difficult to restrict this.
have you considered using the Windows Data Protection API :
https://msdn.microsoft.com/en-us/library/ms995355.aspx
grabbed straight from the source
DPAPI is an easy-to-use service that will benefit developers who must provide protection for sensitive application data, such as passwords and private keys
WDPAPI uses keys generated by the operating system and Triple DES to encrypt/decrypt your data. Which means your application doesn't have to generate these keys, which is always nice.
You could also use the Rfc2898DeriveBytes class, this uses a pseudo-random number generator to decrypt your password. It's safer than most decrypters since there is no practical way to go back from the result back to the password. This is only really useful for verifying the input password and not retrieving it back again. I have never actually used this myself so I would not be able to help you.
https://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes(v=vs.110).aspx
see also this post which gives a way better explanation than I can.
How to securely save username/password (local)?
If I misunderstood the question in some way, tell me, I will try to update the answer.
NOTE that modern/metro apps do not have this problem, although they still are accessible in other ways.
The hard truth is that storing a password in a desktop application, 100% securely is simply not possible. However, you can get close to 100%.
Regarding your original approach, PasswordVault uses the Credential Locker service which is built into windows to securely store data. Credential Locker is bound to the user's profile. Therefore, storing your data via PasswordVault is essentially equivalent to the master password approach to protecting data, which I talk about in detail further down. Only difference is that the master password in that case is the user's credentials. This allows applications running during the user's session to access the data.
Note: To be clear, I'm strictly talking about storing it in a way that allows you access to the plain text. That is to say, storing it in an encrypted database of any sort, or encrypting it yourself and storing the ciphertext somewhere. This kind of functionality is necessary in programs like password managers, but not in programs that just require some sort of authentication. If this is not a necessity then I strongly recommend hashing the password, ideally per the instructions laid out in this answer by zaph. (Some more information in this excellent post by Thomas Pornin).
If it is a necessity, things get a bit more complicated: If you want to prevent other programs (or users I suppose) from being able to view the plaintext password, then your only real option is to encrypt it. Storing the ciphertext within PasswordVault is optional since, if you use good encryption, your only weak point is someone discovering your key. Therefore the ciphertext itself can be stored anywhere. That brings us to the key itself.
Depending on how many passwords you're actually trying to store for each program instance, you might not have to worry about generating and securely storing a key at all. If you want to store multiple passwords, then you can simply ask the user to input one master password, perform some salting and hashing on that, and use the result as the encryption key for all other passwords. When it is time for decryption, then ask the user to input it again. If you are storing multiple passwords then I strongly urge you to go with this approach. It is the most secure approach possible. For the rest of my post however, I will roll with the assumption that this is not a viable option.
First off I urge you not to have the same key for every installation. Create a new one for every instance of your program, based on securely generated random data. Resist the temptation to "avoid having to store the key" by having it be generated on the fly every time it is needed, based on information about the system. That is just as secure as hardcoding string superSecretKey = "12345"; into your program. It won't take attackers long to figure out the process.
Now, storing it is the real tricky part. A general rule of infosec is the following:
Nothing is secure once you have physical access
So, ideally, nobody would. Storing the encryption keys on a properly secured remote server minimizes the chances of it being recovered by attackers. Entire books have been written regarding server-side security, so I will not discuss this here.
Another good option is to use an HSM (Hardware Security Module). These nifty little devices are built for the job. Accessing the keys stored in an HSM is pretty much impossible. However, this option is only viable if you know for sure that every user's computer has one of these, such as in an enterprise environment.
.Net provides a solution of sorts, via the configuration system. You can store your key in an encrypted section of your app.config. This is often used for protecting connection strings. There are plenty of resources out there on how to do this. I recommend this fantastic blog post, which will tell you most of what you need to know.
The reason I said earlier not to go with simply generating the key on the fly is because, like storing it as a variable in your code, you rely exclusively on obfuscation to keep it secure. The thing about this approach is that it usually doesn't. However, sometimes you have no other option. Enter White Box cryptography.
White box cryptography is essentially obfuscation taken to the extreme. It is meant to be effective even in a white-box scenario, where the attacker both has access to and can modify the bytecode. It is the epitome of security through obscurity. As opposed to mere constant hiding (infosec speak for the string superSecretKey approach) or generating the key when it is needed, white box cryptography essentially relies on generating the cipher itself on the fly.
Entire papers have been written on it, It is difficult to pull off writing a proper implementation, and your mileage may vary. You should only consider this if you really really really want to do this as securely as possible.
Obfuscation however is still obfuscation. All it can really do is slow the attackers down. The final solution I have to offer might seem backwards, but it works: Do not hide the encryption key digitally. Hide it physically. Have the user insert a usb drive when it is time for encryption, (securely) generate a random key, then write it to the usb drive. Then, whenever it is time for decryption, the user only has to put the drive back in, and your program reads the key off that.
This is a bit similar to the master password approach, in that it leaves it up to the user to keep the key safe. However, it has some notable advantages. For instance, this approach allows for a massive encryption key. A key that can fit in a mere 1 megabyte file can take literally billions of years to break via a brute force attack. Plus, if the key ever gets discovered, the user has only themselves to blame.
In summary, see if you can avoid having to store an encryption key. If you can't, avoid storing it locally at all costs. Otherwise, your only option is to make it as hard for hackers to figure it out as possible. No matter how you choose to do that, make sure that every key is different, so even if attackers do find one, the other users' keys are safe.
Only alternative is to encrypt password with your own private key stored somewhere in your code. (Someone can easily disassemble your code and get the key) and then store encrypted password inside PasswordVault, however the only security you have is any app will not have access to password.
This is dual security, in case of compromised machines, attacker can get access to PasswordVault but not your password as they will need one more private key to decrypt the password and that will be hidden somewhere in your code.
To make it more secure, if you leave your private key on your server and expose an API to encrypt and decrypt password before storing in Vault, will make it most secure. I think this is the reason people have moved on to OAuth (storing OAuth token in PasswordVault) etc rather then storing password in vault.
Ideally, I would recommend not storing password, instead get some token from server and save it and use that token for authentication. And store that token in PasswordVault.
It is always possible to push the security, with miscellaneous encryption and storage strategies. Making something harder is only making the data retrieval longer, never impossible. Hence you need to consider the most appropriate level of protection considering execution cost x time (human and machine) and development cost x time aspects.
If I consider strictly your request, I would simply add a layer (class, interface) to cipher your passwords. Best with asymmetrical encryption (and not RSA). Supposing the other softs are not accessing your program data (program, files OR process), this is sufficient. You can use SSH.NET (https://github.com/sshnet/SSH.NET) to achieve this quickly.
If you would like to push the security and give a certain level of protection against binary reverse-engineering (including the private key retrieval), I recommend a small (process limited) encrypted VM (like Docker, https://blogs.msdn.microsoft.com/mvpawardprogram/2015/12/15/getting-started-with-net-and-docker/) based solution such as Denuvo (https://www.denuvo.com/). The encryption is unique per customer and machine based. You'll have to encapsulated you c# program into a c/c++ program (which acts like a container) that will do all the in-memory ciphering-deciphering.
You can implement your own strategy, depending on the kind of investment and warranty you require.
In case your program is a backend program, you can pick the best strategy (the only I really recommend) of all which is to store the private key at the client side, public key at backend side and have local deciphering, all transmitted password would be hence encrypted. I would like to remark that password and keys are actually different strategies to achieve the same goal: checking if the program talks to the right person without knowing the person's identity; I mean this: instead of storing passwords, better store directly public keys.
Revisiting this rather helpful issue and adding a bit of additional information which might be helpful.
My task was to extend a Win32 application that uses passwords to authenticate with an online service with a "save password" functionality. The idea was to protect the password using Windows Hello (UserConsentVerifier). I was under the impression that Windows surely has something comparable to the macOS keychain.
If you use the Windows Credential Manager APIs (CredReadA, CredWriteA), another application can simply enumerate the credentials and if it knows what to look for (the target name), it will be able to read the credential.
I also explored using DPAPI where you are in charge of storing the encrypted blob yourself, typically in a file. Again, there seems to be no way (except obfuscation) to prevent another application from finding and reading that file. Supplying additional entropy to CryptProtectData and CryptUnprotectData again poses the question of where to store the entropy (typically I assume it would be hard-coded and perhaps obfuscated in the application: this is security by obscurity).
As it turns out, neither DPAPI (CryptProtectData, CryptUnprotectData) nor Windows Credential Manager APIs (CredRead, CredWrite) can prevent another application running under the same user from reading a secret.
What I was actually looking for was something like the macOS keychain, which allows applications to store secrets, define ACLs on those secrets, enforce biometric authentication on accessing the secret, and critically, prevents other applications from reading the secrets.
As it turns out, Windows has a PasswordVault which claims to isolate apps from each other, but its only available to UWP apps:
Represents a Credential Locker of credentials. The contents of the locker are specific to the app or service. Apps and services don't have access to credentials associated with other apps or services.
Is there a way for a Win32 Desktop application to access this functionality? I realize that if a user can be brought to install and run a random app, that app could probably mimic the original application and just prompt the user to enter the secret, but still, it's a little disappointing that there is no app-level separation by default.
I would like to know which method to use to store passwords in database. I have implemented it using MD5 but according to some posts SHA1 is more secure. Is there any other method which is more secure?
Please help me finding out a best method to secure passwords.
Sure SHA1 is more secure that MD5, but for most purposes it is not secure enough.
You will probably find useful the video How NOT to Store Passwords by Computerphile - 9 minutes and 24 seconds long.
You must realize that there is much to cover when it comes to authentication and access control, so having a good hashing scheme is not enough.
On storing passwords.
As you already know, you don't store the password. In fact, when it comes to storing passwords, in general terms you want to store salted hashes of the passwords, using a modern algorithm optimized for this purpose. For the salt it is considered ok to store it alongside to the hash, for the salt value use a random value as long as possible.
Note: When generating random value for security purposes, use a cryptographic secure generator (such as a subclass of RandomNumberGenerator for .NET - example). This random number generator are designed to be hard to predict. While standard random number generator are meant to be repeatable (That is with System.Random all you need is the seed to generate all the values, and to guess the seed all you need is enough consecutive values generated with the same seed).
Also note: Most hashes are optimized to be fast to calculate, in that category falls both MD5 and SHA1. You should choose one that is not that fast, so that the attack will take a reasonable amount of time to compute the hashes when trying to crack your passwords.
One such algorithm is BCrypt - others include Scrypt and PBKDF2 - on using BCrypt from C# you will find the article Use BCrypt to Hash Your Passwords: Example for C# and SQL Server useful. If you can't resource to BCrypt or similar algorithm, you should atleast use a variant of SHA2 (SHA256, SHA512 and so on).
Addendum: You can use the class HMACSHA256 which is available in the BLC as a key derivation function, pass your salt as key. This is preferible to appending or prepending the salt (which could fall to Length extension attacks). That is, if you use HMAC, and your hash algorithm is vulerable to Length extension attacks (known or to be discovered), your system is till secure. MD5, SHA1 and SHA2 as suceptible to this kind of attack. SHA3 is not. Sadly SHA3 is not included in the BLC (no, it is not SHA384), you can get it from Multiformats.Hash or HashLib. I have to mention that SHA3 is also designed to be fast when implemented in hardware. And remember, for passwords an slow hash is better.
Addendum: Argon2
As it was pointed a year ago this answer should be updated to mention of Argon2. I did write the original answer before that existed.
At the time, I had not found an implementation for C# that I was willing to recommend. Since this answer was brought to my attention, I had another look, and that is no longer the case.
You can use Isopoh.Cryptography.Argon2 which has fully managed code (it is not a C# binding for a C++ implementation, but full C# code), works on all major platforms and there are Nugets available.
Notes:
Use Argon2Version.Nineteen. This is Argon2 v.1.3 (Nineteen = 0x13) which fixes known vulnerabilities.
Use Argon2Type.DataDependentAddressin (Argon2d), or use Argon2Type.DataIndependentAddressing (Argon2i) with TimeCost >= 10. Argon2d is in theory vulnerable to side channel attacks, as such it is not recommended for code that runs on client machines. Isopoh.Cryptography.Argon2 mitigates this by using OS calls to prevent sensitive memory to be moved to virtual memory/pagefile/swap and zero it as soon as possible. On the other hand Argon2i has a Time-memory tradeoff vulnerability, which allows to compute the hashes faster by using more memory. The paper Towards Practical Attacks on Argon2i and Balloon Hashing shows that you need 10 iterations/passes to make the exploit inefficient, even in Argon2 v.1.3.
Here are some recommended reading:
Speed Hashing
You're Probably Storing Passwords Incorrectly
Everything you ever wanted to know about building a secure password reset feature
The definitive guide to form based website authentication
OWASP's Password Storage Cheat Sheet
OWASP's Forgot Password Cheat Sheet
Also the video: Crypto is Back! - Google Tech Talk - August 5, 2009 - 54 minutes and 32 seconds long.
On recovering a password.
First off: don't. The point of the password recovery option is not to recover the password, but to recover access to the application. So... how do you recover access to the application?
I'm glad you ask. What you need is an alternative way to verify the identity of the user. This could be a second factor authentication (anything from security question to using a hardware key generator). Yet, what is often done is to resource on third party, such as mail.
So, you want to know if the user is the owner of the email (or cellphone, or whatever) the user has previouly claim to own. In order to do so you send a code (often refered as token or cookie) to that email (or whatever). This must be a random generated code with a cryptographic secure generator so that nobody else - except the owner of that email (or whatever) - will be able to know what that code is.
Now, if the user presents to your application that code, you are almost sure it is the right user.
Almost because: emails (or whatever) could has been stored in an unsecure location. To mitigate that, you want to put a time limit on your code (cookie or token). Also, if a code has been used, it should NOT work again. And for extra security you could resource to a CAPTCHA, to ensure this code doesn't come from a bot that just got lucky.
For more on this topic (this links are also presented above):
Everything you ever wanted to know about building a secure password reset feature
OWASP's Forgot Password Cheat Sheet
SHA1 has less vulnerabilities than MD5. It's a newer algorithm that utilizes more bits and requires more processing to "crack." You can view most of the mainstream hash algorithms and their known vulnerabilities here: http://en.wikipedia.org/wiki/Cryptographic_hash_function
As someone already commented, definitely make sure you add "salt" to your password hash to further obscure any possible pattern.
I've got a question regarding C#.
I am currently working on a medical software product, and one of the important things is to make sure that the patient's data is encrypted. I got two questions regarding this:
1.) How secure is the Microsoft .NET implementation of AES (Rijndael) from System.Security.Cryptography? Does it have any known security flaws, or am I fine just using the MS implementation? (note, I know the basic background of how these algorithms work, but I am not really that deep into it to get an idea of how it works).
2.) Since the data is stored on the same PC as the application, how hard is it to get information from a C# application? Assuming I have somewhere in the code
string encrypPassword = "ThisIsMyPassword";
string encryptedString = EncryptString(ClearString, encrypPassword);
// save encryptedString to harddrive
I know that an attacker could just go down to the assemble code, and at that point there is nothing at all I can do against this (the system has to be able to encrypt / decrypt the data), but is there like a shortcut for C# to get the encrypPassword, since it is managed, or does something like this still require you to go down to the assemble code?
If you have a fixed password compiled into your app, then you don't need to care about the security of AES and known security faults because your data is simply not secure. A sufficiently knowledgable person with access to the PC will be able to decrypt all the data.
And locating a fixed password usually doesn't require any programming knowledge. A good hex editor will do in most case. You don't even need to know what programming language was used.
If your data is used by a single user, then you can tie the password for the patient data to his or her Windows password (or account). Windows provides some specific functions for that. See http://msdn.microsoft.com/en-us/library/aa302402.aspx for how to access it from .NET.
In answer to the first part of your original question - the native Windows implementation of AES is NIST certified to be FIPS 140-2 compliant. Access to the certified implementation is limited to:
Using the Windows Crypto API
Using the CAPICOM com wrapper to the Windows Crypto API
Using the .Net AesCryptoServiceProvider class in the System.Security.Cryptography namespace (this class did not become available until .Net Framework 3.5)
That being said, the implementation in the RijndaelManaged class is the same, it just has not been thru the NIST certification process (this process is very long and very expensive).
The Aes algorithm is very secure (military grade encryption - especially the 256 bit key variant).
The biggest concern (agreeing with the posters above) is keeping your encryption password embedded in the application in plain text.
To store your password data you could use SecureString class from System.Security namespace.
Most decent obfuscators will encrypt the strings from your code before storing them in the assembly's strings section, and inject a method to decrypt them before use. These techniques have also long since been reverse engineered by disassemblers.
Realistically, there is almost no way to really safely store a string in any programming language. Someone can pretty much always either find the string, or reverse engineer your logic used to build it. The best thing you can do is stow down the attacker long enough to make it not worth their time and effort.
In your case, I would probably store the password encrypted in the app (as in, encrypt it yourself manually outside your app, and copy/paste it in). Possibly split it into parts so it isn't stored as a single string. Then put it back together and unencrypt it at runtime, then at runtime store it in a SecureString. Also invest in a good obfuscator, as it will help mask your unencryption logic (which will become the weak link in the security).
What is the most standard encryption technique used in sql server for asp.net c# enterprise level application? . i am talking with respect to standards like md5 or sh1 etc, hashing
What you describe is called hashing, not encryption.
I think you can use some form of SHA-2, possibly after concatenating with a 'salt' string. Most common platforms provide built-in functions for such hashing algorithms. Details: http://en.wikipedia.org/wiki/SHA-2
Enterprise applications don't store passwords. They use NTLM/Kerberos integrated security and rely on impersonation and constrained delegation to secure access end-to-end.
Hashing and/or encryption as a means to protect against accidental media loss is much better served with Transparent Data Encryption, which encrypts an entire database transparently.
Password hashing against a compromised host disclosure of passwords which opens the potential of password reuse on unrelated sites can use built-in hashing functions like HashBytes. As long as the hash is properly used (correctly salted). But with a compromised host the battle is already lost.
I've generally found Md5 (with salt) to be quite common.
However
I've seen time and time again, where the login page(s) are done via standard http!
This is a bigger concern then someone hacking into web-server/ SQL box and getting hold of the passwords.
Read about the Cookiemonster Attack for more information regarding 'Man in the Middle' type security issues.
I'm working on an application and I need to store the users password, so I'm thinking I'll store it in the current-user class of the registry, but I also want to hash it for the obvious reason, and I've seen news items that state that SHA1 has been cracked, is there a better (uncracked) hashing algorithm available in the "standard" system or .net?
SHA1 is not encryption, it's a cryptographic hash function. And yes it has been broken, which means it's possible to generate collisions faster than a brute force method. The SHA2 family has not been broken.
But I would advise to use a custom seed per entry so that a rainbow table could not be used for trying out passwords. If you're using the SQL Membership provider the password format "Hashed" already uses a different seed for each user.
More information about seeding your hash can be found in the article What You Need To Know About Secure Password Schemes by Thomas Ptacek.
As you say in your comment, SHA1 is a hash algorithm, not encryption. It is a one-way function that, even if it is broken, does not allow the password to be retrieved.
If you want stronger hash functions that are already in .NET, look at the SHA2 family - SHA256, SHA384, SHA512. (SHA224 also exists, but isn't implemented in the System.Security.Cryptography namespace.)
The collision attacks on SHA1 are not practically exploitable yet, but you are right to be looking ahead. NIST is currently running a selection process for SHA3 in the light of these attacks, but this is a few years from completion and commercial acceptance. SHA2 on the other hand is an existing family of algorithms that are standardised by NIST and are not subject to the attacks that have been successful against MD5 and SHA1.
What you need to do is salt your passwords. Here is some actual sample code in C# that uses SHA1 and salting.
The problem with SHA1 "being cracked" is all basic possible combinations have been pre-calculated, however salting makes your password nonbasic (it is still vulnerable to a brute force if it is weak or easily guessable but it kills rainbow tables)
Hash algorithms have been showing some signs of weakness as of late, which is why NIST has offered up a hashing contest much like they had an encryption contest which crowned Rijndael as the new AES.
I personally like what MD6 has to offer, as it is being spearheaded by Ron Rivest, who has been in the cryptography space for over three decades. MD6 has been withdrawn, so I suggest some of the stronger candidates in Round 2 in my humble opinion are Keccak, Blue Midnight Wish, and Fugue.
From there, definitely use good practices such as salting.
Yes you can use SHA512, just remember how long the actual hash is. You can always add extra security by salting the hash results as well.
SHA512("The quick brown fox jumps over the lazy dog") =
07e547d9 586f6a73 f73fbac0 435ed769 51218fb7 d0c8d788 a309d785 436bbb64
2e93a252 a954f239 12547d1e 8a3b5ed6 e1bfd709 7821233f a0538f3d b854fee6
If you want to look into other Hashing algorythms, here's a short list.
5 days too late but you could try this highly secure encryption function:
uint64_t highly_secure_encrypt(char* password) {
sleep(1);
return 0;
}
No way you're getting the passwords back from that.
Now, onto serious matters. If you don't already know the answer to your question you shouldn't be designing security systems.
If you're storing the password in the current-user section of the registry then the only people who can access it (under normal circumstances) are the user and the administrator. I'd trust (somewhat) the current-user section of the registry and use the standard password hashing mechanisms that the OS provides.
Jeff Atwood's "Rainbow Hash Cracking" describes hashes and password storage at a good beginner detail, and Thomas Ptacek's "Enough With the Rainbow Tables: What You Need to Know About Secure Password Schemes" goes on to tell you why you should not try and do it yourself usually.
Choosing a good hash function is less than 1% of the battle. If an attacker can run you hash function millions of times a second then (s)he can test millions of combinations a second. What you need is a slow, tunable secure hash. That's not something that is easy to come by and SHA*, MD5, etc are designed to be bloody fast since they're meant to be used over files and chunks of files usually, where speed is king.
I'd recommend reading up more, since the answers are out there and very easy to find.