Scenario
Data is encrypted inside DB using key that is never stored in the app server or DB server
Key is entered upon login and is stored via $_COOKIE['key'] variable for persistence (so user doesn't have to enter it every page load)
Data is decrypted via $_COOKIE['key']
$_COOKIE['key'] is destroyed upon browser exit
Threat
Rouge server admin snoops on PHP files, finds out key is stored at $_COOKIE['key']. He injects malicious code like email_me($_COOKIE['key']);. He erase malicious code after gaining the key.
Question
Is there a way to protect yourself from this kind of scenario?
You can make it harder for a server admin to get the key, but they always can.
Let's think about moving the encryption and decryption to the client side. Now, the server won't get the key, so the server admin should not be able to decrypt the data. That's not quite true, because the server admin can manipulate the page JavaScript so that either the key is sent to the server or nothing is encrypted at all.
The only way a client can be certain that a server admin cannot steal their data, is by using a client software that is open source and cannot be changed on-the-fly by an admin. So, web pages and automatically updating apps are out of the question.
If the key itself is a concern, you can use cryptography oracles like Keyvault in Azure that never release the keys contained within but perform cryptography themselves on data sent to them.
Of course an admin would be able to access the data as long as they have access to the cryptography oracle, but not afterwards, and they would never have the key. This helps in some scenarios, that's the whole point of services like Azure Keyvault. Also you don't need to give actual access to the encryption service to all admins.
Another mitigation (a detective control, as opposed to a preventive one) is audit logging both on the IT and application level. When done right, not even admins can hide the fact that they accessed the data, which again can help mitigate some risks and at least may provide non-repudiation.
Yet another thing you could do is proper change management, controlling who has access (especially write access) to your source code. This can get difficult with script languages like PHP, where you can't really sign code, but you can still have good processes for reviewing and releasing code to production.
So in the end, it's probably less of a technical question, there's a great deal you can do in terms of processes.
Related
I'm creating a server(PHP) to store data from android app. With POST query store name, password and email. These data as mentioned are stored on the server (database on hosting).
But I have a lot of questions how to do it correctly:
First is the backend, how to protect data and how to encrypt them?
I know that you can transfer token of android application on the web (server). And there it checked for accuracy, but android application is easy to decompile. How to be in this case?
Also heard of RSA but examples show how the mechanism works. And when used in RSA, I have the private key stored on the server and the public in android application? But what if I we obtain encrypted data from the server on android? I need to decrypt them using the private key. But the key on the server and store the private key on Android ill (paragraph 2, decompiling).
Other...
Please leave comments. Also describe every paragraph of my question, and it is desirable for each paragraph post a link with useful information. Also, I would appreciate any HELPFUL links related to this topic, well, especially your opinion and how best to do it.
I assume that you are trying to create a basic register/login-to-use-this-app mechanism.
Read the PHP FAQ article on password saving on why and how for secure data saving server-side. Basically, to hash (to irreversibly encrypt) sensitive data before directly saving them.
Regarding your second question,
Generally, it is not a big concern on directly transmitting sensitive data between client and server, because there can be these security measures:
Use HTTPS. This will encrypt the stream of data transmission, and it is less vulnerable to the connection being eavesdropped.
You may want to directly send the hash of the password instead of the password itself in the post request, or in other words, use the hash of the user password as the password.
Client frontend
In terms of internal storage, it is not possible to prevent other installed malicious apps from reading and using data you store, unless you (I am not familiar with this) store them in a storage that is only accessible by your own app.
Server backend
There are some servers that distribute OAuth tokens to clients, such as GitHub. However, if you only expect the server login API to be used by your own apps, OAuth isn't necessary in this case, since it is mainly used as a flexible permission bearer which you don't need to concern for your own app.
Instead, the more important thing is how you handle things server-side. For the web API that I once coded for my own server, although I don't expect others to use it, I made the API designed as if it is for the public to use, and pay attention to unexpected client input. This is because clients can be fake anytime, so never trust the integrity of what clients input. (Forgive my obsession, but I even considered backend of my JavaScript on webpages as "clients" to be safe)
I have never used nor have any comprehensive knowledge on other PHP frameworks, but when I work on my website, I would create a safety layer within my own backend code. I separate my backend into two levels, namely the database level and the interface level. The database level should try not let the interface level even get the data that are not supposed to be known by (the current authentication state of) the client, so as to minimize the chance of security vulnerability.
Client-server communication
So this only leaves the problem of data transmission, which is the main point of this question.
As mentioned above, HTTPS would be good enough to encrypt data transmission.
I do not know if this concept is practical, but after initial registration, it might be, if you are obsessive enough, possible to encrypt the data with a timestamp, etc. I am not quite sure about this, but disconnected tokens inspired me on this.
But how much protection you need still depends on what kind of data you are sending. For example, if you are simply tracking user usage, you don't really need a lot of protection for it. Just make sure that the user's original password cannot be leaked by hashing it.
I am trying some stuff out with phonegap and I had a question concerning the security that I cant figure out.
So lets say I want to add something in a db. I let phonegap do an ajax post to a php file on a server with the vars and this php file will insert it in the db.
But anyone who would know where this php file is located and knows the data it wants can do an ajax post and insert data right?
I was reading about giving the php api a token. But I also was reading it is very easy to decompile a phonegap apk so it wouldnt be hard to get this token right?
So how can I make sure the php file on the server only accepts posts made from my phonegap app?
You can't. There is no way to guarantee they only come from your application. You can however ensure any calls come from a specific known user of your application.
You have an untrusted client with which it is impossible to embed a secret within without compromising the secret. You can make it harder, such as encrypting your JS and packaging it encrypted, then relying on Apple's DRM to secure your key, but for someone vaguely determined that will not stop them. Your AJAX end point exists and as the insecure client needs to communicate with it somehow there will always be a way to discover the client's secret.
However, typically this isn't an issue. What you can do, is exchange a secret with the client that is tied to a single user so that any calls to your API are on behalf of that user, and that user only (presuming that secret is kept secure - they don't lose their device etc). You can then use this secret to either encrypt or sign your outgoing AJAX call. This ensures someone can only affect their own account (e.g. only update their own account, only upload content tied to their account etc), and can't make arbitrary calls on behalf of other users.
This is enough for many types of application - though you haven't provided any detail about what your AJAX call does. No one is going to deliberately leak their own "personal" secret (though if theft is a concern, or you have higher security requirements then you could implement 2FA or more).
Personally, if this was anything non trivial, I wouldn't advise rolling your own system anyway. Security is difficult to get right, and there are many existing authentication systems out there (e.g. OAuth2) which have been tried and robustly tested in the wild.
Imagine a pretty standard website, with user authenticating with email/password pair. For passwords, it already ha shashing with random salt, but the rest of data is kept unencrypted.
We do another step forward and encrypt the sensitive data with a password key, the key, obviously, shall be known to the application to be able to decript the data for its operation.
we don't want to have it in the source code, so it's kept in a file and read by the app when it needs it.
we've secured the file so that only user which executes the app can read it
(this point has appeared after some discussions below) We have already considered buying hardware HSM and found that not possible (for instance we are running the server on a virtual machine)
this way we are relatively protected from complete DB stealing, right? However, the key might become known if someone gets access to the OS user with read rights.
the question is: what are the best practices for keeping such key secure?
Buy a hardware security module and keep the key in it. The key will not be able to be read.
Yubi makes a reasonably priced hsm. $500 if I recall correctly.
While we're here, your db server should be on a different box in a different network zone as your web server.
Say I have a PHP application and want the users data to be encrypted before it it gets to the server (to prove to users that their data will not be data mined or resold for advertising).
Similar question was asked here ( Secure Javascript encryption library? ) and implies that this is not going to work, but with the increase in privacy interest amonsgt users this requirement is only going to get greater over time.
Example, using the Stanford library (http://crypto.stanford.edu/sjcl/) a web form has an additional ‘long’ password field which the user pastes in (probably from email for example)
sjcl.encrypt(txtPassword, txtFormFieldToBeEncrypted)
The encrypted data is sent to the PHP page, and the process is reversed when the page is loaded.
Would this work if the users used Chrome or another browser that remembers form values - obviously this is not a secure result, but would this be effective enough to keep the users information private from the host server?
EDIT: Just to be clear, I am only interested in making the information invisible to the host server, and understand that this solution wont protect from 3rd party attacks
Protection on the page is useless, for the simple fact that the encryption key / mechanism will also be in the scope of the page and can thus be tampered with by a malicious party (or by the user itself when inspecting the page).
To avoid data going over the line unencrypted there is also no reason to "roll your own"(tm), because for that there is SSL.
If you want to make sure that the data that you receive on the server was actually originating from a page that you control, you can rely on CSRF protection.
First of all use SSL it is for an only way for secure communication. If you make encryption in JavaScript it is trivial to decrypt your message (because all your code with keys is public).
If you worry about CFRS attack use anti-forgery token (more here: http://bkcore.com/blog/code/nocsrf-php-class.html)
It's perfectly possible to do this, Lastpass for instance built their business model on it. All their server does is store an encrypted blob which they cannot do anything with, all encryption and decryption happens on the client; including a Javascript implementation in the browser. The entire blob of encrypted data is downloaded into the client, where the user's password decrypts it; and in reverse on the way back up to the server.
So if your question is whether it's possible: absolutely. It's also a lot of work, since you will need to be providing the same en-/decryption code for as many platforms as you want to support. You'll also need to secure every context where that code will run, to prevent third parties from injecting code which would allow them to access the client side decrypted data. So, everything needs to go over SSL with no 3rd party content being allowed to be injected.
Here are a bunch of reasons why javascript encryption in the browser is almost always a bad idea.
You need to think deeply about your trust model. Do the users trust the server? If not, there is no hope for trustworthy javascript crypto since the crypto software itself comes from the server. If the users do trust the server, why does the data need to be encrypted client-side? Just use SSL to secure the connection, then have the server encrypt the data before storing it.
I read all posts on HTTP over SSL. So far, I know how to get the data securely in a Web form. But I miss the part of recover and keep the data in the same way.
I need in my Website a form to collect sensible data from customers (may be also credit cards numbers for booking, but no credit card authorization process is required) and later keep and read that data in a secure way.
Then, for a basic secure Web application I need:
a) Web site with SSL Domain Validated (DV) Certificate (I don't have fixed IP address. I use basic shared or "virtual" hosting service).
b) Develop a simple PHP & MySQL application that collect sensible data of customers, putting all the app PHP files on the SSL secure folder.
c) All the collected data is gonna be stored in the server MySQL database.
This is the questions part of my message:
1) If I enter later using phpmyadmin to take look at the database over regular hoster services (HTTP), isn't this insecure??
2) What about the hosting administrators? They could also read all sensible data if I use plain text in the database. But encryption methods for data on the server (not only in transmission over SSL) could be enough? Isn't true that the encryption encoding/decoding method could be intercepted by the hosting administrators?? (consider this: the method is inside the application in the same server).
I can't pay the convenience and security of an own server.
3) Considering those things, and assuming that they are true... really matter if I go for a database encryption?
May be I missed something or I misinterpreting some issue.
Thanks a lot for your help and patience.
These shared hosting plans are not really up to the job of collecting credit card numbers - you are betting using a payment gateway and not storing them yourself.
See some regulations on this: PCI
Yes. HTTP is insecure.
Yes, plain text in the database is insecure. Encrypted is slightly more "secure" - it'll deter someone who casually looks through - but anyone with access to the server also has access to the script doing the encrypting / decrypting.
I'd say yes. Encryption in your case won't do a thing against a dedicated attacker, but it'll prevent some sysadmin idly browsing through from immediately having the data without having to make the deliberate step to break in.
I hope you're not storing credit card or other sensitive data, particularly if covered by privacy laws in your jurisdiction. Storing that sort of stuff on a shared server will probably get you sued. If nothing else, storage of credit card data in this manner will be a violation of your merchant account - if they get wind of it, Visa and MasterCard will become unavailable to you.
1) Seeing the data with phpmyadmin over HTTP is insecure, of course.
Regarding 2), if you don't have physical security, then you can't have any security (perhaps with the exception of storing encrypted data which you encrypt and decrypt outside the hosting site).
As your hosting company has access to the computer, they can read all your data.
Having said that, in my experience hosting providers will not do that and try to keep your data safe (because that is their business), pretty much in the same way banks' business is to try to keep your money for you and safeguard it and not taking it.
3) Go for database encryption only if you keep backups. For running the live version it provides little more security (if at all) and makes things more cumbersome.
It is.
They can.
Not really but it could still be a good idea. Someone could get hold of your database and not the PHP source code. Then encryption in the database would be a good thing.
You are correct. The only way to be sure is to run your own server. Also you should know about the Payment Card Industry Data Security Standard.
I think that bobince is totally correct. Public key crypto can help you but keep in mind that you loose comfort of using PHPMyAdmin to view the data - you will see garbage that will need to be decrypted somewhere on the side. See http://www.php.net/openssl to learn more about PHP and public key crypto.
Having an encryption/decryption process entirely on the server is, as you suspect, mere obfuscation and not secure in itself. It can help in cases of a partial compromise, where an attacker gains read access to the database (typically through an SQL injection hole) but no ability to read the site scripts or run arbitrary code.
If you only need to write out sensitive data (canonically credit card numbers) that the server doesn't need to be able to read back in, you can do that with public key cryptography. Encrypt the data with your public key, then read it only on a known-secure machine that has the corresponding private key. This protects past data in the case of a greater compromise where the scripts are readable, and in the case where an attacker gains write-access to the scripts, they at least only get new incoming data leaked, and not the old stuff. Hopefully that would give you time to detect the intrusion and rebuild.
Isn't true that the encryption encoding/decoding method could be intercepted by the hosting administrators?
Yes. But then the hosts have physical access to the machine, so could bang a rootkit on it that intercepted everything the webapp was doing on the fly from day one, if they really wanted. There's no way around trusting your host, so pick a reputable one and don't run sensitive systems on shared servers.