Apologies if this has been asked before, but I did some searching and wasn't able to find an answer to my question.
I have my website content stored in a MySQL database (let's call it content) and I need to write a simple login system for my website. So, I need to create some sort of users table that holds usernames, passwords, permissions, etc., and what I'm wondering is whether I should just make this a new table in my content database, or if it would be more secure to have it stored in a new database? The downside to having it in a second database is that I will have to use two database connections instead of one.
Maybe this is a silly question, but I appreciate your input!
You don't need to use a differnt db. That's more reserved for when you've got data that has completely DIFFERENT purposes, e.g. company A has a db and company B has a db.
Note that simply having two different databases does NOT require two different database connections to access. As long as the user ID you're logging into the DB with has proper access rights, you can do:
SELECT onedatabase.table.field, someotherdatabase.table.field
...
Moving sensitive information to another database is a great Defense In Depth strategy because it is limiting the impact of SQL Injection. This works off the principle of isolation and planning on failure. This is a common practice for protecting sensitive Medical or Finical information. Often these separate databases will go a step further and store the information in an encrypted state.
SQL Injection under MySQL is very limited, you cannot stack queries (e.g: '; drop table ...) and without MySQL's file privileges you cannot get a shell. The only thing left that is useful is obtaining credentials using a union select or sub-select to access other tables or databases. As long as you have separate user accounts, and separate permissions an attacker will have to find SQL Injection in a query that is accessing the sensitive database, which reduces your attack surface. Not be able to access sensitive information with SQL Injection makes this attack much less useful.
Also, you should be using parametrized queries.
It's a good idea. For security reason, it might be better not having users logging in at all. An idea is having a central admin account that you control, and then have the users send their content to you by mail. That way, you can be sure no one else will have access.
As you say, you’d need to maintain more than one database connection if you were to do this. Although sand-boxing the databases is a nice thought, 99% of database-powered websites with user registrations will store the users with the content.
Related
I have an app in php and Mysql. For security purposes is better to save user´s data in differents tables? or if I save all in the same table has no problem? The first approach, makes that the user info in some object is not complete in memory. Is that in php safer?
Yes, this could be done as a defense in depth approach to security.
You could have one table that stores username, and bcrypt password hashes, and the database account that authentication uses is limited to this table only.
Another approach is to have another database that the page that authenticates has access to, then use another database for the rest of your site that the post-authentication connection uses.
This would limit any data extraction from your system if a vulnerability such as SQL injection exists. Of course it is better to concentrate on protecting your system against existing vulnerabilities initially, then design in separate databases as a part of a system hardening exercise. Separation of databases will help you if there are any future mysql vulnerabilities that may allow injection of queries. You never know if such vulnerabilities exist until they are discovered.
It's ok to use one table. Don't store password in the db, only it's hash to compare in the future.
Separate your back end from the UI well. Escape all user inputs. The question is not about storing the data in one table. It is about how strong the protection of the entire DB is.
I wanted to know why isn't easier and more secure to have one database service, dedicated only to user authentication (withholding usernames and passwords) which would be well secured (inputs well sanitized etc.)
And another database service for all the other data in the website which would be possibly less secured and available for serving web content.
Wouldn't it be a good way to prevent a lot of the SQL injections happening these days?
No. There is a difference between sanitizing inputs and protecting passwords. SQL injection can happen in any query, and allows someone not only to steal, but also to destroy data. This should be prevented at all times.
Regarding usernames and passwords, there are additional measures to take. For one, don't store passwords at all, but always store hashed versions, hashed with a salt. Furthermore, you might put the authentication in a different database or even some authentication service if you like, but like I said, that's extra.
Of course, if you got a big bunch of data that is read-only from a website perspective, you might store that in a different database, or at least make the website connect using a database user that doesn't have any rights to modify the data. That way, the data is better protected against destruction, because errors on the website, SQL injection and even leaking of the username and password will not lead to destruction of the data. But this also goes for both the user credentials as the 'less important' data.
You seem to miss two points :
the rest of your data also should be secure (or else there's no point in securing the application)
you don't store passwords. Never. You only store a hash built from the password, the username (optionally) and a record specific salt. So it's not so important to secure that base, it only is done to prevent impersonation
As there's no reason to secure in a greater manner that part of the DB, just ensure the whole is correctly secured, it's so much easier to manage one DB than two TB. Trying to keep different types of data in different RDBMS and to maintain their coherency is a nightmare.
Lastly, note that this shouldn't change anything regarding to mysql injections. Just don't allow those injections by using prepared statements.
This is a tough quesiton. Indeed you can have two databases one for sensible data, the other for "furnishing".
Let's put it this way: even if you use a database only for "furnishing", what happens if that database get hacked ? Will your users have to see "THIS SITE WAS HACKED" in the section or...? :)
EDIT: What is protection? Protection is when you buy a coffee and you don't want your friend or someone to drink it. Then what if you buy a coffee and a muffin. Would you protect only one ? Would you protect both ? Which one is more important for you ? If you're like me and most people you would say both. What you made me understand by commening is that muffin (users) is more important than something else (furnishing).
Why would you need protection, if you don't care about the coffee ? Probably because you don't really value coffee enough to protect it. Then let me say this: the money you used to buy your coffee were worth when they were still money, but now they're coffee, what's changed apart from their shape ? Nothing.
Now let's get back to our case: if you have a simple database which contains only "furnishing" texts like "TITLE", "DESCRIPTION" etc. Having them lost isn't bad ? Won't you have to go there and fix them ? Won't you have to WORK to get everything pretty ?
Not to speak that most vulnerabilities related to a database might get pretty worse than just losing only ONE database. Having a sql injection issue might get all database destroyed, that's the danger you're trying to avoid. So, it's almost pointless to try to secure a database more than another. Try to secure everything instead, you'll be sure that everywhere you go, nothing could happen.
So you fear a special inmate, and you secure him A LOT, and trascurate that old cell. You look away, the inmate in the old cell is now out of his cell! And worse, he freed the special inmate (and everyone else). That's the kind of security hole a sql injection imply.
I think you need to look deeper into your RDBMS protection layers to get a better picture why they are better in the same instance.
Let's take for example your MySQL database:
an instance is made out of 3 + databases (mysql, information_schema, and all others you create).
so you already have a separate database repo that is handling the auth + user + pass - and that is your MySQL database.
There are ways to develop applications that are hacker free - when working with MySQL most of the coders use open SQL code (inline SQL) - and this is the problem - hackers will take advantage of this! To fix this use stored procedures (encapsulated).
Inside database privileges are a problem as well - lazy developers or stupid DBA will give extra rights for application users. Your idea is redundant from many points of view. More instances will cost you more money, more resources, etc.
More of a risk assessment question than technical.
So i have been reading a lot about protecting against SQL Injection. Lets assume i have a large web application that is mostly unprotected and i need to make some improvements to protect against this problem. Read large as lots of SQL interaction using dynamic queries but on few (less than 100 registered users).
My question is... If i have already secured the main login script (the only publicly available user input) using parameterized queries, is it really that necessary to do the same work for the rest of the site? I mean if a potential attacker can't log in, how much other damage can he do?
Assuming of course none of my registered users have malicious intent.
Assuming of course none of my registered users have malicious intent.
Never assume that :) If your users have different rights, one with almost no right could find the way to get admin access... And so on.
Also, protecting against SQL injection does not make your login bulletproof and someone could bruteforce through it or simply have sniffed packets from your trusted users. Make sure you protect your whole application, do not assume that the entry point you planned (login script) is the only one available...
And please use SSL if your website contains or requires any sensitive data from your users.
What makes you sure that none of the legitimate users won't attempt to attack your system?
I'm glad my bank don't think that. Some-one would have emptied my account by now, just by using sql injection attacks.
And even then you should be careful about accidents. If you use parameterised queries, someone using a ' in a value won't cause problems.
It allows type safety in your parameters.
It engenders better programming habits.
It allows execution plan caching. (Without it, every query with a different parameter will look like a completely different query. Not only preventing caching of plans for those queries, but over-filling the cache so plans that really can be re-used get discarded.)
Not only is it more secure, it's more reliable. Other than experimentation and throw-away code, I can think of no project where I would have condoned not using parameterised queries.
Never trust your users!
Even if you do (and nobody can sign up either), there's always the potential of CSRF for instance; an attacker would lead users of that system to a seemingly harmless page with an image. That image would have the following code:
<img src="http://yourserver.com/profile?user_id='; DROP TABLE users" />
My hacking skills are practically zilch, but you can imagine what would happen :)
I'm running a basic website with some user accounts (no cookies, php session system.).
I'd like to store some data generated by the user only visible for themselves.
For the moment I store the data from all users in one table, with an extra column for identifying (this is an input from php session user-id). (We are talking about max. 50-100 keys per user).
On data request I have an extra parameter (AND "user-id"=x) in the mysql query.
Is this a safe (there is no sensitive data on the site, but the accounts have to be private anyway) way of storing data?
Are there better ways to handle this? (I read about separate databases etc.) and if so, how?
thx,
M.
Is this a safe (there is no sensitive data on the site, but the
accounts have to be private anyway) way of storing data?
There is nothing wrong in having the user-id=x in your mysql query to get the data from the table. But make sure you are not directly reading this value from your query string and appending to the mysql query without doing proper sanitization and cleaning. Otherwise you will be a vicitm of SQL injection.
Are there better ways to handle this? (I read about separate databases
etc.) and if so, how?
I don't see any reasons to have seperate database to handle this. You can use your current database. If needed, you may create additional tables for this. I am not sure what is your db schema and entity relations. So i am not in a position to tell you how to do that. Look into your tables and make sure it is normalized.
If you want the data stored to be seen only by that particular user, You probably want to check in whether the current logged in user id ( get from the session variable ?) is same as of the userId of the db record. May be you can compare with the "CreatedById" field value if you have one.
I believe this link is a must read if "SQL injection" is a new term for you.
http://www.unixwiz.net/techtips/sql-injection.html
Just use the PHP $SESSION.
By using session_set_save_handler you can define your own session storage method, which could be a MySQL database for instance.
The values in a session can not be altered by the user directly (as you can with cookies). So this approach is perfectly safe, so long as you don't expose the PHPSESSID cookie value anywhere.
No way is 100% safe. Your method sounds very insecure but I cannot see your code. If your are cleaning the input correctly to avoid mysql injection and also there is no way for a user to specify a key of another user then you may be ok.
I'm programming a sensitive application (health data) that requires a good security schema. Of course, bugs exists and hackers or user may found it. So my concern is to protect data as much as I can. Reading something about security I have found a mechanism that could be useful, but I would like to listen the opinion of someone more experienced in this stuff. The scheme is:
Create a database, call it 'app' for example
Create some common tables (or not)
For each user, create a set of tables with a prefix based on the user name and a hash to avoid a user to known other user prefix (sjiXoi4sa_table)
All database queries for a user will put his own prefix except those refered to the global scope
Is this a good security scheme? Could it be improved? (for instance, it will be great if each user may encrypt their own tables). Any suggestion welcome.
As you describe it, the schema does nothing to improve security - OTOH, the additional overhead in working with more tables means more code means more defects injected. You are also compromising performance with this approach.
However if you were to set up the permissions so that a user only had read/write access to their own tables, then yes, it would be more secure - however you've still caused yourself a lot of problems elsewhere. You can get the same level of security AND reduce the complexity / amount of code AND solve the performance / scalability problems by normalising the data properly, and denying all access by users to the tables - but grant access via stored procedures (where you can effectively apply permissions on a row-by-row basis).
This is security by obscurity, and doesn't add any protection. If the site is hacked, the hacker will just dump the mysql database, not just the user table
This will do nothing to address the security issues in your application and will have the added disadvantage of impacting on performance (creation of tables, indices etc). Consider encrypting data instead and locking down access to user specific data based on which user is logged into your system.
In addition to everyone else's answer to why your schema is a bad idea, here's another piece of advice: Your dealing with health data, so there are probably regulations that you must follow to ensure security. For example, NIST standards or whatever your national equivalent is. Find them, read them, follow them. In many jurisdictions around the world such standards are mandatory, and you could be liable for damages if something happens and you didn't follow the standards.
So, find out what (if any) standards apply to processing and storing private health data in your country, and use them.
Any scheme that requires the creation of a new set of tables for every new record in another table is too horrible to use except in obfuscation contests, no matter how much security it adds. And as already pointed out, it doesn't add much security either.