I have a Silverlight 3 app which connects to a server to perform various actions. My users log in using Forms Authentication but the actions they request are run on the server using the AppPool account so when they go in the audit logs they're recorded against the AppPool account. PCI DSS regulations now require that the user's own ID is in the audit logs which means the action must be taken using the user's creds. Now, I can save the user's creds when they log on and submit them with each request and the actions being taken by the server can use those creds. But the PCI regs say that if creds are saved they must be encrypted (to avoid someone taking a memory dump of the PC and getting the password).
The only way I can see of doing this is to get a public key from the server and encrypt the password with it, then submit the encrypted password and decrypt it on the server using the private key. But Silverlight doesn't have asymmetric cryptography.
I guess I'm too close to the problem and there must be another solution but I can't see what it is. Can anyone help?
CLARIFICATIONS
It's an internal application. Up until now, I've been using IIS Forms AuthN over SSL to Active Directory - I'm not worried about protecting the password in transit, just whilst it's held in memory on the client. As I understand it, because I'm using Forms Authentication, impersonation is not possible on the server unless I use LogonUser, which means I need the password on the server, so I need to transmit it each time, so I need to hold it in the client, in memory, until the app closes.
Are you saying you need to store the password for re-use in the silverlight app? If you are concerned about the password appearing in memory un-encrypted then Silverlight then I think you're in trouble.
The .NET framework does have a SecureString class for exact purpose you outline.
Unfortunately the Silverlight version of the framework does not have this class. Hence even if you were to keep the logical storage of the password encrypted at some point your code would need to decrypt it before using it. At the point there is memory allocated containing the string in unencrypted form.
I don't know much about Forms authentication but if you can map the User principle to a domain user (which you seem to indicate you need) then you will want to use impersonation when running your code on the server.
Alternatively stop using Forms authentication and use Windows integrated authentication where you definitely can use impersonation server-side.
Encryption should never be used for passwords. When you encrypt something then it follows there should be a way to decrypt it. One way hashes should always be used for passwords. md5 and sha1 have been proven to be far too weak for any secuirty system.
Sha256 should be used, and in silverlight this library will take care of it:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256%28VS.95%29.aspx
In fact storing passwords using "encryption" is recognized by the vulnerability family CWE-257. The use of a message digest is the ONLY way to safely store passwords. I didn't just make this up, this is coming from NIST. There are many other vulnerabilities that come up when storing passwords. Here is THE LIST that NIST has put together:
Related
I've read several Stack Overflow threads, I still can't decide what is the best option for my case. And the most secure one.
Here is the story. My webapp is to help users automatically get an overview of some of their data available in some third-party website. I need to store for each user some third-party credentials. Each night or so, my server will connect to the third-party services on the users' behalf and retrieve the required data.
Most of those third-party sites do not implement any API or OAuth mechanism, so I was thinking to do some web scraping.
I've read in many places that storing the credentials in the DB is not a good idea - especially because my app needs access to the password (so it has to be encrypted in such a way I can easily reuse it).
So, I have two options left:
Whenever I access (via webscraping) the third-party service, I store on the server the cookies issued by that service, for future reuse. I encrypt them and keep them encrypted in a DB, and decrypt them only when I need them. The problem is that the cookie can be denied or expired after a while, and so the automatic process wouldn't work any more.
I store the credentials in the environment variables. I will be on Node.js and Heroku. That's an idea I found in another SO thread. But I'm wondering about the security of this idea. Is it really safe? No one can access them but me? And what about if I reach many users. Like 1000 users, with 10 services. That's 10000 credentials to store in the env variables. That doesn't seem like a good idea.
I found two interesting questions on Stack Overflow but they don't fit 100% with my use case.
Security model: log in to third-party site with user's credentials (that gave me the idea in point 1)
Rails storing third party credentials.. Anyone know best practice? (gave me the idea in point 2).
I add another answer because maybe this one will do the trick for you.
You said the main goal of your website is to have an overview of third party applications. But what if instead of updating this overview every night, you update it when the user logs in ? It changes everything, because you could use the user's password (of your website) as master password to encrypt (using AES) all the others.
If you do that, the communications between your server and the clients have to be encrypted with SSL pinning, because an attacker could perform a MITM, get the master password and all the others stored in the DB... (Even if in practice it's very hard because you need to hack the client AND the server)
Storing a lot of data that changes and grows in environment variables will never be practical, no matter if it's secure or not so this is pretty much out of the question, unless if you have a small fixed number of users.
Not storing credentials in the database is a very good advice, but the cookies are credentials and even if you store them encrypted, your app needs to be able to encrypt it to use it. (This is unlike the situation with verifying passwords of your users when you don't need to ever encrypt them, you only need to see if the provided passwords hash to the same values that you have stored).
This is a hard problem because to make it work you need to have some form of credentials (whether those are passwords or cookies) stored and ready to be used unencrypted (even if they are stored encrypted, you need to store the keys to encrypt it as well).
Also, what you are trying to do can be illegal. Mayke sure that you follow the TOC of every service that you're using or otherwise you may face legal trouble.
Plan for the attacker gaining admin access to the server. Your site will be very attractive to attackers, kind of a one-stop-shop for user credentials so you will need very good security of the login credentials.
There are more than two options for storing the credentials:
Use an HSM for the storage or individual credential encryption keys.
Keep the credentials on another dedicated server with no Internet access, 2-factor authentication and limit admin personal. Rate limit the access to this server and add rate alarms. Access this server on a per user credential basis over a non-Internet connection. The credentials will only be available to the Internet connected server in memory as used, not at-rest in a file.
Storing users credentials in a reversible way looks like a terrible idea anyway. But if you really want to store them, I suggest you to use the environment variables solution. But you can improve it. To limit the amount of data you store and don't have 1000000 variables as you said, you can just store an AES encryption key, store all credentials in a DB encrypted with this key, and you just have to get this key (which is in memory) and decrypt the DB. But there is another problem with this solution. As I said, this is stored in RAM memory, so it's not persistent, imagine your server has to reboot for X or Y reason... You will lose the AES key and also the credentials of your users... Moreover, if the attacker performs a memory dump, he will have access to the AES key...
I think the better idea is to store the cookies (in an encrypted way) and when this one expires, you alert the user (by mail, phone, notifications, ...) and ask him to fill his credentials again. But it's not a perfect solution ! Indeed the cookies are a type of credentials and shouldn't be stored either...
Currently I'm developing a Node.js webserver-app that I then want to make available for download and use. This app should feature accounts, so that you can log in with your account on the website created by the server.
Since that would require a password, I also have to think about security obviously. But now, I don't really know how I should protect the password while sending and receiving it.
For storage, I was about to simply create a hash of the password and store that hash somewhere, but what about the transfer?
I was thinking about SSL/https, but this would require a SSL certificate, and even if I got it for free somewhere, I couldn't share it in an open-source app(?).
I could also somehow hash the password in the website, and then just send the hash to the server, but I think this wouldn't be the highest standard of security as well, would it? Considering that no SSL would cause more disadvantages than just worse/none encryption.
Any ideas?
I was thinking about SSL/https, but this would require a SSL certificate, and even if I got it for free somewhere, I couldn't share it in an open-source app(?).
Use SSL/TLS. Even if it's an open source app, it doesn't mean that you need to share your private key too. This would undermine the whole concept.
Open source means that you share the code with some license. What the licensor does with it is not your consern as long as they conform to the license. If they want to use their own instance of your software under their own domain, they will have to create their own certificate (under their domain).
I could also somehow hash the password in the website, and then just send the hash to the server, but I think this wouldn't be the highest standard of security as well, would it? Considering that no SSL would cause more disadvantages than just worse/none encryption.
This is no solution, because you now changed the thing you want to protect to something else. The model doesn't change just because you hash it on the client. Now you need to protect the hash on the transport channel which is actually the same problem as you would have had before with sending a password.
Currently I'm developing a Node.js webserver-app that I then want to make available for download and use. This app should feature accounts, so that you can log in with your account on the website created by the server.
Federated accounts
If you want federated accounts across multiple instances of your app which are hosted by different parties.
You could look into OpenID as an identity provider for all instances of your app. You would then either require that users use a known OpenID provider or you setup your own default provider. You could release the code for your provider as open source, but it wouldn't be necessary for the app to function.
If the OpenID interface is not enough, there is always a way to establish a pairing between instances of your app. You would have to build an interface where different instances may share data.
Unconnected instances
If this is only about securing the communication without SSL/TLS, then I must say, this is impossible in the general sense.
You could however let every student register in person and use that password on client and server to derive a shared secret key (i.e. for AES). Then you could use CryptoJS to encrypt everything with AES and send it using AJAX. The problems are of course that (1) there must be a person that handles the registration and (2) this is vulnerable to man-in-the-middle attacks, because JavaScript crypto is bad.
Good thing is that Let’s Encrypt will be online soon. It will enable a semi-automated way to request free certificates for your domain. It will be so easy that you can do this as part of the normal NPM install workflow.
http://letsencrypt.org works great for this and is now available (I understand I am a little late to this one.)
You can check out https://github.com/DylanPiercey/auto-sni for automated Letsencrypt certificates.
In the book Programming Grails, Burt Beckwith gives some really good insights about how to develop Grails applications which follows OWASP Top 10 recommendations in chapter 9.
Punctually,I'm trying to implement the recommendation for Insecure Cryptographic Store. That reads as follows
Do not store passwords in config files, or even in files on the filesystem. Instead, create
a web page that you use to initialize the system where people trusted with passwords
enter the passwords (using SSL!) when the application starts up. Ideally, you shouldn’t
trust any one person with all of the information to start the system. For example, to use
JCE encryption, you will need to load a java.security.KeyStore , and this requires a
password, and you use this to create a javax.crypto.SecretKey , which also requires a
password. Use different passwords. If two people know the key store password and two
other people know the key password (it’s a good idea to have backup users in case
someone isn’t available), then no one person can decrypt the data or be coerced into
giving someone else access.
I want to secure the Amazon AWS[1] Access Credentials that will be used by the application in order to use the KMS[2] API call to secure encrypt and decrypt information.
I would like and example about how this can be achieved. My initial idea is to use a Service in the Singleton scope which holds the credentials and those credentials are setted by a Controller which is responsible of loading the KeyStore and the SecretKey used to decrypt a previusly encrypted and store AWS Access Credentials.
[1]http://en.wikipedia.org/wiki/Amazon_Web_Services
[2]http://aws.amazon.com/en/kms/
Suppose you have a server-client application.
Server keeps sensitive information that belongs to a Client.
Server will search some parameters in side the clients's sensitive information.
Thus server should decode the sensitive information with client control temporarily.
But server should not reveal the keys, by hacking it self.
I mean a developer should not try to change server sidde code and should not extract the client keys.
Is there really a way to do that?
Somewhat client permits server to decode sensitive information, but the keys instantly disappear and developer have no tricks to reveal this password?
The answer if exist, is valid also for an ideal secure cloud application. Developer or cloud hosting company should not access to decrypted information.
I am not optimistic, but worth to try asking.
So in a word no. This does not grant any security whatsoever, as you cannot trust the client. You even call out that the server will be controlled by the client temporarily, this is generally not a wise approach. Also, do not underestimate a bored developer, it is completely feasible to write some code and rip the keys. The key here is remembering that if someone has access to the box it is no longer your box.
In general, any client access to sensitive info on the server must require authentication of the client, so that you can verify that the client is exactly who he claims he his. The authentication typically involves sending a password, or some kind of authentication token (e.g., an encrypted shared secret) that was given to the client by the server through a secure channel.
As has been said many times, many ways, allowing client access to server data without proper and sufficient authentication means that you give up control of the server.
My company is going to be storing sensitive data for our customers, and will be encrypting data using one of the managed .NET encryption algorithm classes. Most of the work is done, but we haven't figured out how/where to store the key. I've done some light searching and reading, and it seems like a hardware solution might be the most secure. Does anyone have any recommendations on a key storage solution or method?
Thanks for your replies, everyone.
spoulson, the issue is actually both the "scopes" that you mentioned. I suppose I should have been clearer.
The data itself, as well as the logic that encrypts it and decrypts it is abstracted away into an ASP.NET profile provider. This profile provider allows both encrypted profile properties as well as plain text ones. The encrypted property values are stored in exactly the same way the plain text ones are - with the obvious exception that they've been encrypted.
That said, the key will need to be able to be summoned for one of three reasons:
The authorized web application, running on an authorized server, needs to encrypt data.
Same as #1, but for decrypting the data.
Authorized members of our business team need to view the encrypted data.
The way I'm imagining it is that nobody would ever actually know the key - there would be a piece of software controlling the actual encrypting and decrypting of data. That said, the key still needs to come from somewhere.
Full disclosure - if you couldn't already tell, I've never done anything like this before, so if I'm completely off base in my perception of how this should work, by all means, let me know.
There only two real solutions for (the technical aspect of) this problem.
Assuming it's only the application itself that needs access the key...
Hardware Security Module (HSM) - usually pretty expensive, and not simple to implement. Can be dedicated appliance (e.g. nCipher) or specific token (e.g. Alladin eToken). And then you still have to define how to handle that hardware...
DPAPI (Windows Data Protection API). There are classes for this in System.Security.Cryptography (ProtectedMemory, ProtectedStorage, etc). This hands off key management to the OS - and it handles it well. Used in "USER_MODE", DPAPI will lock decryption of the key to the single user that encrypted it.
(Without getting too detailed, the user's password is part of the encryption/decryption scheme - and no, changing the password does not foul it up.)
ADDED: Best to use DPAPI for protecting your master key, and not encrypting your application's data directly. And don't forget to set strong ACLs on your encrypted key...
In response to #3 of this answer from the OP
One way for authorized members to be able to view the encrypted data, but without them actually knowing the key would be to use key escrow (rsa labs) (wikipedia)
In summary the key is broken up into seperate parts and given to 'trustees'. Due to the nature of private keys each segment is useless to by its self. Yet if data is needed to be decrypted then the 'trustees' can assemble thier segments into the whole key.
We have the same problem, and have been through the same process.
We need to have a process start up on one computer (client) which then logs in to a second computer (database server).
We currently believe that the best practice would be:
Operator manually starts the process on client PC.
Client PC prompts operator for his personal login credentials.
Operator enters his credentials.
Client PC uses these to login to the database server.
Client PC requests its own login credentials from database server.
Database server checks that operator's login credentials are authorised to get the client process' credentials and returns them to the client PC.
Client PC logs out of datbase server.
Client PC logs back into database server using its own credentials.
Effectively, the operator's login password is the key, but it isn't stored anywhere.
Microsoft Rights Management Server (RMS) has a similar problem. It just solves it by encrypting its configuration with a master password. ...A password on a password, if you will.
Your best bet is to physically secure the hardware the key is on. Also, don't ever write it to disk - find some way to prevent that section of memory from being paged to disk. When encrypting/decrypting the key needs to be loaded into memory, and with unsecure hardware there's always this venue of attack.
There are, like you said, hardware encryption devices but they don't scale - all encryption/decryption passes through the chip.
I think I misunderstood your question. What you're asking for is not in scope of how the application handles its key storage, but rather how your company will store it.
In that case, you have two obvious choices:
Physical: Write to USB drive, burn to CD, etc. Store in physically secure location. But you run into the recursive problem: where do you store the key to the vault? Typically, you delegate 2 or more people (or a team) to hold the keys.
Software: Cyber-Ark Private Ark is what my company uses to store its secret digital information. We store all our admin passwords, license keys, private keys, etc. It works by running a Windows "vault" server that is not joined to a domain, firewalls all ports except its own, and stores all its data encrypted on disk. Users access through a web interface that first authenticates the user, then securely communicates with the vault server via explorer-like interface. All changes and versions are logged. But, this also has the same recursive problem... a master admin access CD. This is stored in our physical vault with limited access.
Use a hard-coded key to encrypt the generated key before writing it out. Then you can write it anywhere.
Yes you can find the hard-coded key, but so long as you're assuming it's OK to store a symmetric key anywhere, it's not less secure.
Depending on your application you could use the Diffie-Hellman method for two parties to securely agree on a symmetric key.
After an initial, secure exchange, the key is agreed upon and the rest of the session (or a new session) can use this new symmetric key.
You can encrypt the symmetric key using another symmetric key that is derived from a password using something like PBKDF2.
Have the user present a password, generate a new key used to encrypt the data, generate another key using the password, then encrypt and store the data encryption key.
It isn't as secure as using a hardware token, but it might still be good enough and is pretty easy to use.