Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I am developing a web application where users can play a game. If the user wins, she will get money into her account; in the other hand, if the user loses the game, she will lose money as well. I need to store the data "total money earned" and "total money lost" into a Database.
The problem is that, if some malicious user gets access to the database, that user will be able to change all the "total money earned" and "total money lost", and that is a big problem.
At first glance I thought this problem could be totally avoided by encrypting the "total money earned" and "total money lost", but suddenly I realised that this wouldn't work, as this hypothetical malicious user could always change those value to whatever he wants.
This question is not about ""How to avoid users to access my Database"", but rather about "if a malicious user gets access to it, how can I prevent my data to be changed?""
This is just basic server security. If somebody logs into your MySQL database as a user with write privleges there is nothing you can do. You have to stop them beforehand.
Steps you can take:
1) Have strong server passwords and user account design. Don't have people SSH in as root is a no-brainer example.
2) Give your application only as much access to the database as it needs. Don't have your application be allowed to drop tables for instance if it does not need to. This will at least mitigate possible damage.
3) Be sure you are protected against SQL injection. This is probably the number 1 mistake noobies make.
There is of course tons more to know, but there are more books than you can read in a lifetime on the subject of security. I advise you look into one. I highly recommend Essential PHP security for your PHP code. Its small concise and informative.
Starting point:
You could checkout what Magento does with its sales_order table information.
Each row in the sales_order table represents an individual order issued by a customer. There are protection mechanisms in the admin that do not allow admins to edit these orders. You can only cancel the previous and create a new cloned order (if the initial order really needs to be "changed").
At the table level there is a column called protect_code. This code is (i'm speculating) generated as a cryptographic hash (hash_hmac with any one of the algorithms: md5, sha1, sha2, sha256, etc.) of the entire order information object.
If the order information object is hashed using a secure key that the perpetrator does not have access to (for example the hacker has accessed your database but not your PHP code) then he will not be able to alter the values of the order information object because he will also need to update the hash and without using the same secure key he will not be able to obtain the same hash.
You will be able to recognize any row that has been tampered with by recalculating the hash.
Background info:
Normally keys like this are stored in PHP and the hashes are presented to the user within payment forms, to make sure the user cannot change the payment information before sending the form to the payment gateway (a separate website).
Both your PHP application and the payment gateway application share the cryptographic key, because the payment gateway has to hash the data it receives and check that it hasn't been tampered with (by comparing hashes). Usually you receive your (own dedicated) cryptographic key from the payment gateway.
This implies that the user/hacker does not know your cryptographic key and cannot access your PHP server (meaning he can't read the key either).
Anything you use is accessible:
If the user has access to your application server that means he can have access to any and all 3rd party services (secured or not), such as databases, file storage servers, payment services, mail sending services etc.. The only exemption from this rule is if your application server is just an aggregator for other self hosted self contained services.
If the user has access to the database server but not the application server, your cryptographic key should be safe and your data should be hard to tamper with undetected (but not hard to alter or delete).
If you are using a tiny bit of data anywhere in your application an the user/hacker has access to the application server that means that he (the hacker) has access to that data. You can even store the cryptographic keys on a separate server and obtain each of them by request, if the user/hacker has access he can request them too. If your app is using them, your hacker can be using them too.
The first thing you need to understand is that there is no silver bullet with regards to keeping your data secure. From securing access to your server by ensuring only the necessary ports for communication are open to using strong username and passwords to ensuring that the DB user has only the rights required to perform the tasks necessary. It really is a broad topic. I suggest you search the web for OWASP. If an unauthenticated user is able to gain access to your data your encryption is the least of your worries.
For your situation encrypting is fine but consider using a user specific salt and keeping your encryption method safe.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
I'm currently building a web application(PHP/MySQL) which saves data from persons. Most of this data is not worth protecting with encryption but some of it is financial information like income and so on. It is not a payment application and does not store information that could be turned into money directly like credit card information but still stuff you don't want to have in a possible leak. This platform has to be sold to customers that want "security", but that can mean anything as the customers themselves do not have any knowledge what they really want, since they are business people and not cryptographers(like me neither).
It is a management platform so the people that have their financial data saved there are not the users of the platform. Users of the platform are merely a login with permissions attached to them. The server itself never has to have access the data. Every operation is done by a user(could also be an admin) that is logged in. Multiple users need to have access to the same data given they have enough permissions.
My question is now how I can protect the financial data from these threats:
Somebody finds an SQL-injection and dumps all tables remotely
Somebody steals the hard drive of the server (database + code)
Where I'm certainly not going: Large scale sniffing attack or compromised servers(like sniffing all traffic on the server itself where SSL doesn't matter) or social engineering/phishing.
I would also like to have a quick summary how much more information(keys, data, etc.) I have to store in comparison to the current system, where there is one simple field for income etc. and a standard login system with username and hashed password.
EDIT: Reformulated question almost entirely following the suggestion of comments/answers
Here are two approaches to this:
1) Use symmetric encryption because you have already arranged a secret with the client, which is their password.
Whenever the user requires access to their sensitive information, they need to provide their password. If you require this, then you can use that password as a basis of generating the encryption key.
You can use the openssl functions in PHP to encrypt the sensitive data, and decrypt it when the client needs it. This will allow you to select an appropriately hard to break algorithm which OpenSSL supports. The drawback of this is that you will need explicit user permission and their password to access that data, which is good if you're only storing it on behalf of that user, but bad if you need to pass it on to someone else.
This way you will not need to store additional information in the database. In case someone steals your hard drive, all they will have is encrypted sensitive data and hashed passwords. The drawback is that it's a single point of failure, if they break the encryption they also get the password and vice-versa however the difficulty of breaking the encryption is not as high as reversing a hash. It also relies on strong passwords, which as we know users often don't tend to use, however that's not a new problem and one we're not likely to solve today.
2) Require the user to generate a private-public key pair and send you the public key. You can then store this public key and encrypt data using it. This generally would work well if you had an app/software that communicates with your server, which can do this on the user's behalf, but is harder to implement in a web application. Perhaps there's JavaScript libraries that can do this but since it's not something that is commonly done you need to be 100% sure the library you're using is secure. However this also requires of the user to store the key somewhere and be able to use it whenever they want access to that data (again JavaScript can do this for the user but saving and loading the key is something that requires user interaction due to security concerns).
In short:
Symmetric encryption would only be secure if the encryption key is not stored on the server but is something that the user can provide whenever it is needed.
Asymmetric encryption is even more secure but unrealistic in a web application targeted to an average user.
So I would suggest symmetric encryption using the user's password as a key.
From your question, the following key points stand out.
The server itself never has to have access to the data.
Multiple users need to have access to the same data given they have enough permissions.
Maintain security even if:
Somebody finds an SQL-injection and dumps all tables remotely.
Somebody steals the hard drive of the server (database + code).
This is possible to achieve, but not trivial. The thing that makes this possible is the fact that the server does not require access to the data. This allows us to use user passwords to derive keys.
Each level in your permission structure will have an associated key. This key will be used to encrypt data that can be viewed with those permissions. When the first administrative account is created, generate a key for each level in your permission structure and use the administrative password as an input for a KDF and derive a key. Use this password-derived key to encrypt each permission key and store the resulting ciphertexts alongside the administrative account.
As new users are created and assigned ranks by the administrative account, pull the highest level permission key that the new user will have access to, as well as any keys at a lower permission, decrypt them with the administrative password (which will be required for creating users) and then encrypt them again with the new users password and store alongside the new user in the database.
This system allows you to pass the required encryption keys to each user and makes accessing data above the users permission level cryptographically impossible.
At this point, it is rather straight forward for you to allow users to access data by simply taking their password, decrypting the relevant permission key and then using that key to decrypt the data. Users changing their password is also trivial as it simply means you have to decrypt the permission keys with the old password then re-encrypt with the new password.
At a more technical level, I would recommend the following:
Use AES. AES-256 tends to be the most common but AES-128 is just as secure in the grand scheme of things. Use of an authenticated block mode (GCM) isn't as important here but is still recommended. If not, use a mode like CBC or CTR with an HMAC.
Never use a password directly as a key. Use PBKDF2 to generate keys from passwords. Using AES-256 fits in nicely here because you can use SHA-256 as the primitive to PBKDF2 and get output the same length as the internal hash function.
Generate a new random IV every time you encrypt using a CSPRNG. Prefix the IV to the ciphertext. Don't derive an IV from PBKDF2 like the key.
Asymmetric encryption and hybrid encryption are pointless here unless the users generate and retain ownership of the private keys themselves. I infer from the rest of your question that this isn't the case.
Assuming you want to be able to view this encrypted information without user interaction (e.g. you aren't just storing this information for the user and the information is relevant to your business operations), you have limited storage options.
If your exact threat model is to protect this data in the event of a database leak and nothing else, symmetric encryption is perfect, if properly implemented.
The implication of this is that the symmetric key must be stored on servers that make requests to the database and serve the data to your other (likely front-end) systems. If any of those servers were to become compromised, then the encrypted data will be leaked.
In summary, use symmetric encryption, but understand that it will only protect you directly from a database leak through something like SQL injection or a similar attack. A compromised server is a compromised server and generally means full data access given enough time.
EDIT: If you intend to require user interaction to view the secured data, then apokryfos's comment above accurately details what to do to secure the information. Generate a symmetric key from the users password and use this to encrypt an additional symmetric key. Use this secondary symmetric key to actually encrypt the data. Using two keys makes a user password change easier.
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.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have been reading/googling for the last week on best approach to this issue/application.
I have an app that is bascially a database front end, currently it stores data locally, all works happily (available in the app store).
What i want to do next is store this data on a server.
(Before this i had no experience in server at all so everything from this point on from my own research and asumptions, if something is incorrect please point it out to me).
I decided that a RESTful webservice design would be best for what i wanted.
Basically intention is iPad/Android will be able to talk to web service, web service sits on top of a MySQL database, web service will receive strings, vidoes, photos.
My current situation is i can get the webservice to talk to the MySQL database, i can send simple requests from iPad for data (strings) and to post data (strings), (Still need to figure out best way of handling photos and videos, but thats a different issue).
My Question: What is the best way of making this web service Login/Secure.
The data is sensitive so has to be secure. Currently the user can't access the app without a username & password, but obeviously i need to take precations in the web service also.
I have done loads and loads of googling research and even topics on here i seem to be constantly seeing comments along the lines of "This method is out of date" etc.
It seems to be there are two fundamental approaches,
1) Basically having a GUID which is configered on inital start up <-I think
2) On every request for data also transfering password/username.
Any help guidance would be greatfully recieved.
Thanks
P.S. Sorry about the essay
It is possible to encrypt and sign the data exchanged between the server and the client. For that you can generate your own trusted certificate for free. You'll have to look for the methods based on the technologies you are using. This will protect you against man in the middle attacks as an intruder can't read or alter the data.
Any passwords you use in the code should be encrypted to protect against reverse engineering (at least for amateurs)
Use key based encryption algoritms
Capture all the exceptions, an error should never be transmitted to the client as it's a door to your system.
Protect your wsdl file (if you have any) against public viewing.
Validate your forms, the user shouldn't be able to inject special characters like "<",">","'","=","-"...
This is what I can think of for now.
You can use the following approaches to make your API secure.
oAuth implementation to send and receieve data with authentication headers.
SSL certicificates to make sure the communication between your server and client is encrypted. You can easily buy a private certificate for as low as $15/month.
Hash database fields such as password. (Make sure NOT to use MD5 as it is not secured. Use SHA1 or SHA2 instead).
Don't store user passwords in mobile applications, store some sort of hashed auth key, instead.
I have a php/js site where the information is encoded and put into the database. The encryption key for the information is randomly generated, then given back to the users after they send a post through a form. The encryption key is not stored in my database at all. A seperate, randomly generated, ID is formed and stored in the database, used to lookup the item itself before deciphering it.
My question is, is it possible at all to look through the logs and find information that would reveal the key? I am trying to make it impossible to read any of the SQL data without either being the person who has the code (who can do whatever he wants with it), or by a brute force attack (unavoidable if someone gets my SQL database)?
Just to re-iterate my steps:
User sends information through POST
php file generates random ID and access key. The data is encrypted with the access key then put in the php database with the ID as the PRIMARY KEY.
php file echos just the random ID and the access key.
website uses jQuery to create a link from the key and mysite.com?i=cYFogD3Se8RkLSE1CA [9 digit A-Ba-b09 = ID][9 digit A-Ba-b09 = key]
Is there any possibility if someone had access to my server that can read the information? I want it to be information for me to read the messages myself. The information has to be decodable, it can't be a one way encoding.
I like your system of the URL containing the decryption key, so that not even you, without having data available only on the user's computer, will be able to access.
I still see a few gotchas in this.
URLs are often saved in web server logs. If you're logging to disk, and they get the disk, then they get the keys.
If the attacker has access to your database, he may have enough access to your system to secretly install software that logs the URLs. He could even do something as prosaic as turn logging back on.
The person visiting your site will have the URL bookmarked at least (otherwise it is useless to him) and it will likely appear in his browser history. Normally, bookmarks and history are not considered secure data. Thus, an attacker to a user's computer (either by sitting down directly or if the computer is compromised by malware) can access the data as well. If the payload is desirable enough, someone could create a virus or malware that specifically mines for your static authentication token, and could achieve a reasonable hit rate. The URLs could be available to browser plugins, even, or other applications acting under a seemingly reasonable guise of "import your bookmarks now".
So it seems to me that the best security is then for the client to not just have the bookmark (which, while it is information, it is not kept in anyone's head so can be considered "something he has"), but also for him to have to present "something he knows", too. So encrypt with his password, too, and don't save the password. When he presents the URL, ask for a password, and then decrypt with both (serially or in combination) and the data is secure.
Finally, I know that Google's two-factor authentication can be used by third parties (for example, I use it with Dropbox). This creates another "something you have" by requiring the person accessing the resource to have his cell phone, or nothing. Yes, there is recourse if you lose your cell phone, but it usually involves another phone number, or a special Google-supplied one-time long password that has been printed out and stashed in one's wallet.
Let's start with some basic definitions:
Code Protecting data by translating it to another language, usually a private language. English translated to Spanish is encoded but its not very secure since many people understand Spanish.
Cipher Protecting data by scrambling it up using a key. A letter substitution cipher first documented by Julius Caesar is an example of this. Modern techniques involve mathematical manipulation of binary data using prime numbers. The best techniques use asymmetric keys; the key that is used to encipher the data cannot decipher it, a different key is needed. This allows the public key to be published and is the basis of SSL browser communication.
Encryption Protecting data by encoding and/or enciphering it.
All of these terms are often used interchangeably but they are different and the differences are sometimes important. What you are trying to do is to protect the data by a cipher.
If the data is "in clear" then if it is intercepted it is lost. If it is enciphered, then both the data and the key need to be intercepted. If it is enciphered and encoded, then the data, the key and the code need to be intercepted.
Where is your data vulnerable?
The most vulnerable place for any data is when it is in clear the personal possession of somebody, on a storage device (USB, CD, piece of paper) or inside their head since that person is vulnerable to inducement or coercion. This is the foundation of Wikileaks - people who are trusted with in confidence information are induced to betray that confidence - the ethics of this I leave to your individual consciences.
When it is in transit between the client and the server and vice versa. Except for data of national security importance the SSL method of encryption should be adequate.
When it is in memory in your program. The source code of your program is the best place to store your keys, however, they themselves need to be stored encrypted with a password that you enter each time your program runs (best), that is entered when you compile and publish or that is embedded in your code (worst). Unless you have a very good reason one key should be adequate; not one per user. You should also keep in-memory data encrypted except when you actually need it and you should use any in-memory in-clear data structures immediately and destroy them as soon as you are finished with them. The key has to be stored somewhere or else the data is irrecoverable. But consider, who has access to the source code (including backups and superseded versions) and how can you check for backdoors or trojans?
When it is in transit between your program's machine and the data store. If you only send encrypted data between the program and the data store and DO NOT store the key in the data store this should be OK.
When it is stored in the data store. Ditto.
Do not overlook physical security, quite often the easiest way to steal data is to walk up to the server and copy the hard drive. Many companies (and sadly defence/security forces) spend millions on on-line data security and then put their data in a room with no lock. They also have access protocols that a 10 year old child could circumvent.
You now have lovely encrypted data - how are you going to stop your program from serving it up in the clear to anyone who asks for it?
This brings us to identification, validation and authorisation. More definitions:
Identification A claim made by a person that they are so-and-so. This is usually handled in a computer program by a user name. In physical security applications it is by a person presenting themselves and saying "I am so-and-so"; this can explicitly be by a verbal statement or by presenting an identity document like a passport or implicitly by a guard you know recognising you.
Validation This is the proof that a person is who they say they are. In a computer this is the role of the password; more accurately, this proves that they know the person they say they are's password which is the big, massive, huge and insurmountable problem in the whole thing. In physical security it is by comparing physical metrics (appearance, height etc) as documented in a trusted document (like a passport) against the claim; you need to have protocols in place to ensure that you can trust the document. Incidentally, this is the main cause of problems with face recognition technology to identify bad guys – it uses a validation technique to try and identify someone. “This guy looks like Bad Guy #1”; guess what? So do a lot of people in a population of 7 billion.
Authorisation Once a person has been identified and validated they are then given authorisation to do certain things and go to certain places. They may be given a temporary identification document for this; think of a visitor id badge or a cookie. Depending on where they go they may be required to reidentify and revalidate themselves; think of a bank’s website; you identify and validate yourself to see your bank accounts and you do it again to make transfers or payments.
By and large, this is the weakest part of any computer security system; it is hard for me to steal you data, it is far easier for me to steal your identity and have the data given to me.
In your case, this is probably not your concern, providing that you do the normal thing of allowing the user to set, change and retrieve their password in the normal commercial manner, you have probably done all you can.
Remember, data security is a trade off between security on the one hand and trust and usability on the other. Make things too hard (like high complexity passwords for low value data) and you compromise the whole system (because people are people and they write them down).
Like everything in computers – users are a problem!
Why are you protecting this data, and what are you willing to spend to do so?
This is a classic risk management question. In effect, you need to consider the adverse consequences of losing this data, the risk of this happening with your present level of safeguards and if the reduction in risk that additional safeguards will cost is worth it.
Losing the data can mean any or all of:
Having it made public
Having if fall into the wrong person’s hands
Having it destroyed maliciously or accidently. (Backup, people!)
Having it changed. If you know it has been changed this is equivalent to losing it; if you don’t this can be much, much worse since you may be acting on false data.
This type of thinking is what leads to the classification of data in defence and government into Top Secret, Secret, Restricted and Unrestricted (Australian classifications). The human element intervenes again here; due to the nature of bureaucracy there is no incentive to give a document a low classification and plenty of disincentive; so documents are routinely over-classified. This means that because many documents with a Restricted classification need to be distributed to people who don’t have the appropriate clearance simply to make the damn thing work, this is what happens.
You can think of this as a hierarchy as well; my personal way of thinking about it is:
Defence of the Realm Compromise will have serious adverse consequences for the strategic survival of my country/corporation/family whatever level you are thinking about.
Life and Death Compromise will put someone’s life or health in danger.
Financial Compromise will allow someone to have money/car/boat/space shuttle stolen.
Commercial Compromise will cause loss of future financial gain.
Humiliating Compromise will cause embarrassment. Of course, if you are a politician this is probably No 1.
Personal These are details that you would rather not have released but aren’t particularly earth shaking. I would put my personal medical history in here but, the impact of contravening privacy laws may push it up to Humiliating (if people find out) or Financial (if you get sued or prosecuted).
Private This is stuff that is nobody else’s business but doesn’t actually hurt you if they find out.
Public Print it in the paper for all anyone cares.
Irrespective of the level, you don’t want any of this data lost or changed but if it is, you need to know that this has happened. For the Nazi’s, having their Enigma cipher broken was bad; not knowing it had happened was catastrophic.
In the comments below, I have been asked to describe best practice. This is impossible without knowing the risk of the data (and risk tolerance of the organisation). Spending too much on data security is as bad as spending too little.
First and most importantly, you need a really good, watertight legal disclaimer.
Second, don’t store the user’s data at all.
Instead when the user submits the data (using SSL), generate a hash of the SessionID and your system’s datetime. Store this hash in your table along with the datetime and get the record ID. Encrypt the user’s data with this hash and generate a URL with the record ID and the data within it and send this back to the user (again using SSL). Security of this URL is now the user’s problem and you no longer have any record of what they sent (make sure it is not logged).
Routinely, delete stale (4h,24h?) records from the database.
When a retrieval request comes in (using SSL) lookup the hash, if it’s not there tell the user the URL is stale. If it is, decrypt the data they sent and send it back (using SSL) and delete the record from your database.
Lets have a little think
Use SSL - Data is encrypted
Use username/password for authorisation
IF someboby breaks that - you do have a problem with security
Spend the effort on fixing that. Disaster recover is a waste of effort in this case. Just get the base cases correct.
I am currently building a setup to take credit card information. The following structure was used:
Server 1:
MySQL user set to read only
Holds the login credentials.
I use PBKDF2 hashing, done with a class i built based on this code.
Server 2:
MySQL user set to read and write
holds all of the customers credit card information
My question:
If server 1 stores the paswword in this format: algorithm:iterations:salt:hash
For example: sha256:1000:Pe27BkIKkBHklogp9Io80iRKtF+6koly:nrYUwOlixwJECRcjBRKwQ+MVNMTbnYnm
If server one was compromised, it seems to me that having the password in this format would make it easy for them to crack the passwords for the site and access the users credit card information.
Is this a case where I need to use Mysql (AES_ENCRYPT() and AES_DECRYPT())?
Am I over thinking this?
Is there a better way to protect the information in server 1?
Update Based on Comments
I built my heating and air company system. Any one that pays online can store their cc information with quickbooks if they choose. I have a few larger clients that we bill monthly in office, and process cc's through a desktop terminal. These clients have customer profiles on our servers, which they can access. These are the clients that I want to allow to store there cc information. This way I don't have to have the cc information stored on paper in our office for anyone to find.
To be honest, if I manage to compromise server 1, I'm not going to try to crack those passwords. They should be secure. What I would more likely do is try to get my own code installed on the server to send me the passwords and/or credit card information when the user logs in. For example, let's say you process the authentication in a file named login.php. If I can compromise login.php, then when it is validating the login, I can have it execute a curl command or something to send the login information to my own server where I can collect it.
But I digress... The answer is that your hashing of the user login details should be secure as you've described it. If server 1's database is compromised, it should be about as secure as it can be. You could add a layer of obfuscation within your PHP code to do something like munge in the a hash of the salt or something so that someone with access to the database but not the code would have a much harder time knowing what process you used to hash the passwords, which would avoid hackers from trying to brute force passwords such as password, iloveu, etc. I would also highly suggest that the credit card information on server 2 is stored in an encrypted format using either AES_ENCRYPT() or PHP's mcrypt_encrypt() function.
Make sure you sanitize all input via POST forms, and you should be good to go.