Unfortunately this question may be a little broad, because I can't work out the proper terms to help me bring all this together. I'm very new to php/SQL, and I'm attempting to set up a minimal site with very simple login/register functionality.
Should I be creating a new database user whenever I register a new web user?
Are CRUD privileges safe to give to all users of the website?
Should I actually make a DB user for registering, one which can only insert into the user table and nothing else until they login (requiring no password for mysqli_connect())?
Once logged in, they would make a connection to a different type of DB user, one with more privileges to use the website.
How many different types of DB users should there be?
I assume a small group of users for the DB workers (including one for root access), another group for each type of web user (ie. employers have more privileges than employees), and another restricted user just for registering.
All in all, would >10 DB users in a small website be unusual?
Is there a performance/space cost associated with having many types of users?
I appreciate any responses and links, and apologize if these are very basic questions.
I struggled with this all those years ago, so here is the answer I wish I had:
Generally, this is overcomplicating things, and the headline answer for a basic application is: the permissions of users will be managed by the PHP code in the API calls you make, and one DB user is fine. All users should avoid interacting directly with the DB for app dev generally, to prevent violating the sanctity of the data.
It's good to think about security and restrictions, but simplicity is king - the more complex you make it, the harder it is to maintain, and therefore the easier it is to miss corner cases.
Should I be creating a new database user whenever I register a new web user?
No, database users are distinguished by their privileges. As a result, all users conform to a set of groups with varying privilege levels. The database accounts are separate from the web accounts - connecting to the database is done behind the scenes and has no link to the web account being used.
A good approach would be to create a DB account for each service connecting directly to the DB. For the vast majority, this will be one service, your web server. If the application grows and isolated services such as audits, microservices, security, IOT spring up, they should probably have their own accounts.
Are CRUD privileges safe to give to all users of the website?
The question is misguided - you give the CRUD to the DB account, which will need it. For the CRUD permissions managed inside the PHP, it really depends on your app and specific endpoints. For example, you probably don't want all your users to be able to delete User records, so your PHP code should prevent that from happening.
How many different types of DB users should there be?
The number depends on your database. Generally, there are 4 groups
Database Administrators
Database Designers
Casual End Users
Native End Users
However, if you want to grant table level privileges then you might need to branch out a little more. This would suggest 10 DB accounts is quite a small amount, several hundred is more likely.
The more privileges, the more space is required, but it's a fairly minute consideration, and shouldn't play a big role in performance. Complexity is the next issue - think carefully how many groups and permutations you actually want to test. In the case of the question above, I was a single hobbyist developer - one account as a DBA is probably fine. If there were multiple users directly accessing the DB (already probably a bad idea for app dev), then maybe split out them with varying permissions.
Talking about table level permissions for a simple app is just way overkill!
Related
I have an application in which we want to provide the functionality using which user can add/update/delete the columns of different tables. My approach is to create a different database for each client so that their changes specific to tables will remain in their database.
Since each client will have their own database, I wonder how can I manage authentication and authorization? Do I need to create a different database for that as well? Will it affect the performance of the application?
Edit: The approach that I am planning to use for authentication and authorization is to create an additional field called "Account" on the login page. This account name will guide the program to connect it to correct database. And each database will have it's own users to authenticate.
The answer to your question is of course (and unfortunately) Yes and No. :)
This is known as multi-tenant data architecture.
Having separate databases can definitely be a great design option however so can using one database shared with all of your clients/customers and you will need to consider many factors before choosing.
Each design has pluses and minuses.
Here are your 3 essential choices
1) Each customer shares the same database and database tables.
2) Each customer shares the same database but they get their own schema inside the database so they each get their own set of tables.
3)Each customer gets their own database.
One major benefit (that I really like) to the separate database approach is data security. What I mean by this is that every customer gets their own database and because of this they will edit/update/delete just their database. Because of this, there is no risk in end users overriding other users data either due to programmatic error on your part or due to a security breach in your application.
When all users are in the same database you could accidentally pull and expose another customers data. Or, worse, you could expose a primary key to a record on screen and forget to secure it appropriately and a power user could override this key very easily to a key that belongs to another customer thus exposing another clients data.
However, lets say that all of your customers are actually subsidieries of 1 large company and you need to roll up financials every day/week/month/year etc.
If this is the case, then having a database for every client could be a reporting nightmare and having everyone in a single database sharing tables would just make life so much easier. When it comes time to report on your daily sales for instance, its easier to just sum up a column then go to 10,000 databases and sum them up. :)
So the answer definitely depends on your applicaton and what it will be doing.
I work on a large enterprise system where we have tens of thousands of clients in the same database and in order to support this we took very great care to secure all of our data very carefully.
I also work on a side project in my spare time which supports a database per customer multi-tenant architecture.
So, consider what your application will do, how you will backup your data, do you need to roll up data etc and this will help you decide.
Heres a grea article on MSDN for this:
https://msdn.microsoft.com/en-us/library/aa479086.aspx
Regarding your question about authentication.
Yes, having a separate database for authentication is a great design. When a customer authenticates, you will authenticate them off of your authentication database and they will receive the connectionstring to their database as part of this authentication. Then all data from that point comes from that clients database.
Hope this was helpful.
Good luck!
Our client would like the user table to be separated from all other tables for "security reasons". Is this a good practice given that our application is built using RoR and MySQL and running on Unicorn and Nginx ?
I can think of two possible ways:
Create two different login accounts, one for the user table and one for the other tables.
OR
Have a separate database for the user data.
I think that both the solutions might create some problems with the migrations and other tasks and I don't know if this is an effective method of protecting user data. I am a junior developer and I am not familiar with some database and security concepts. Any suggestion?
A very common pattern is to have the users table literally just contain details of the user account and NO details of the actual person behind that account. ie, it would have username, email, password, or encrypted password & salt or whatever, but nothing else - not even name. So, all the "glue" that makes the system work stays in the users table in your regular database.
Then, the details of the real person behind the account (name, telephone number, address, card details etc etc) are stored in a different table, or tables, with a foreign key in either table pointing into the other one. You could store them in a different database but i don't know if this makes it more secure. A better way might be to encrypt just the table with the user's personal data, or perhaps encrypt the entire database. see
http://thinkdiff.net/mysql/encrypt-mysql-data-using-aes-techniques/
I get the feeling that your client doesn't know a lot about internet security and just needs to be reassured that some hacker isn't going to put all the customers' credit card details online, as has happened in several high profile cases recently. To satisfy them i would recommend that you research this well and implement at least two different security strategies, each of which on their own would be considered adequate.
Reassuring the client didn't work as this was an acceptance criteria for launch. In the end, I created two separate database with separate login credentials and user permissions. In order to manage multiple database migrations, I initially used multi-database-migrations gem and then customised it into my own gem.
I was new to SO when I posted this question (still am) and I now understand that the topic is too wide to be asked in a single SO question. Thanks for the suggestions anyway and I hope that the answer can help other people.
What I am trying to ask is ...
Users will only ever access the database via my application. The application itself allows an admin user to create/modify/delete users and give them certain privileges. So, I have a table which contains each users log-in name & password.
I am still developing the app, so it currently logs in as root with no password. Obviously, I will change that, but what's the best practise? Should I have a single database user & password which the application uses, or should I create a separate user for the databaase each time a user for the application is created (or modified)? The latter seems like more work.
Your APPLICATION should certainly have separate user ids and passwords for each user. Given that, there's no reason for the application to have multiple user ids when it talks to the database. As long as the application's security is implemented correctly, there's no gain from having multiple DB user ids.
Giving each user his own DB user id would surely be a gigantic pain because it would likely involve all sorts of special cases and exceptions. For example, to log in to your application, the application would have to validate the user's id and password. How will it do that if the user doesn't have access to the password table? But if anything needs to be protected from unauthorized access, it's the password table. So you'd have to use one userid to do the login, then take that away and give a different userid. It's likely that there are other tables that a given user might be allowed to access in one context but not in another. The accounting department likely needs to see total amounts paid in salaries for the year, but maybe they can't see individual employee's salaries. Employees may be able to access data about their own benefit, but not that of other employees. Etc.
The only exception I can think of to this would be if you allowed some sort of generic access to the database. To take the most extreme case, if you had a screen where the user can type in an arbitrary SQL query which you would then execute. In that case, you could theoretically have the application analyze the query and attempt to apply security rules, but that would require your application to embed an awful lot of knowledge about SQL. In that case you'd be better to give each user his own DB user id and putting the security rules into the database engine.
Short Answer: Before the internet, yes. After the internet: nobody does it, but it is still perfectly acceptable.
Common practice in the internet age is to consider your application to be the user, and to give that application a login. The only actual benefit is some performance boost from connection pooling. The perceived but illusory benefit is security.
Understanding the security angle requires the realization that all security in the end resolves down to who can read and write from what tables, rows and columns. To see how this works, consider a user who is authorized to manipulate a highly secure table, and another user who cannot even see that table. The less privileged user successfully manages a SQL injection attack attempting to wipe out the secure table, it fails because the Database prevents access by that user to that table.
The takeaway is that there is no technical reason to use a single login except if connection pooling is important. Databases are very poorly understood by many internet age programmers so explaining how to use their built-in security is an uphill battle against many pre-conceived and incorrect ideas.
There's no reason to create a database login for each user. It's really your app that's interacting with the database, not the user. Creating extra logins just makes your database that much less secure.
im struggling to find the best practice to this so any links or research reading materials or any Google search terms will be much appreciated.
Im a volunteer for a local charity organization, a childcare setting.
We have a mysql database that contains various tables containing children & Parent information, invoices, staff rotas etc.
What we would like to attempt to do is have secure online access for parents to view there own contact details and invoices.
My question is, is it safe to allow the website to have access to the main database. it would be a second set of userPermisions with only read access to select tables and not the entire database.
I don't want the website to open up a hole to allow users to obtain all our data or destroy or corrupt the main database.
Or
should i create a second database that the website will have access to and have the main database sync with the second? I can see future issues if we decide to allow parents to edit there own contact details, pay invoices online.
Web specific details will be kept in a second database such as user name password, forum etc
Its not any thing iv ever attempted to do before and don't know where to start in terms of research.
Kind regards
Matt
You certainly couldn't hurt anything by having a second, slave/read-only database accessible to your user interface. If done properly, MySQL grants can restrict users to read-only operations, so it's not necessary from a functional standpoint to have a second database. Perhaps, given the nature of your business, there may be a legal reason why you must have a second database though. Be sure to investigate the requirements for protecting PII (e.g. HIPPA)
Security is an ongoing process - part of it is ensuring proper identification and authorization as well as defense in depth - ensuring that the account used to access the database has least privileges and that the surface area exposed to that account is minimal. Also if the database is on the same machine as the web server, then ensuring that a compromise of the web server doesn't also compromise the database.
You also have to contend with the standard social elements - ensuring users have a way to get their first password/setup an account, maintain their own passwords. You should not store their passwords (even encrypted), but instead store only a salted hash. When they forget their password, the reset it themselves, since the web site cannot and should not send them a permanent password via email.
And you should be aware of XSS (cross-site scripting attacks), SQL injection - you should be able to find references to that in most discussions of web application development.
For a web application, when creating the user which will connect to the MySQL database, you have the choice of privileges. Assuming that the only actions intended to be done by that user are SELECT/INSERT/UPDATE/DELETE, it seems to make sense to only provide those privileges, however I've never seen that recommended anywhere - what are the reasons for and against this method?
I disagree with Bill here and Atomix's line of thinking is more suitable. Unless it can be demonstrated otherwise, Bill's answer highly increases the risk of the database being compromised.
Perhaps for very experienced developers there is other security in place, but for other developers giving a script full, unfettered access to do ~anything~ to a database is asking for trouble, when there is no need to.
The principle of least privilege should be in use here. For MySQL, have a super user with all privileges which is used for creating tables, drop database, and so on. Ideally this username and password is never seen in any PHP file or any file on the web server. (I'm using PHP as an example but it applies to other web applications). You would only use this username and password with something like PHPMyAdmin or MySQL Workbench.
Then, for PHP scripts, have one with the minimum required, such as just INSERT, SELECT, UPDATE, maybe not even DELETE, depending on your PHP script. This would be in the PHP files, that is, actually only ONE file OUTSIDE of the document root, as is recommended by most.
The reason is thus: yes, you do not need a MySQL user for every web application user. But principle of least privilege ( http://en.wikipedia.org/wiki/Principle_of_least_privilege ) should apply. If somehow your MySQL super user is compromised because you accidentally named your MySQL connect script as .txt instead of .php, or someone gained access to the web server files, at least the "worst" they can do is SELECT, UPDATE and INSERT... Which while can cause big problems anyway, is not as bad as giving them DROP DATABASE, DROP TABLES and much worse things.
Additionally, in my current project due to agile development practices (I do not work for but recommend http://www.agilealliance.org/), one or two "non-tech" team members are directly using PHPMyAdmin to make direct changes to the MySQL database. This is because creating a CMS for simple direct data entry is not required. In this case, a third MySQL user with reasonable but again, "just enough" privileges is suitable for them. We don't want to cripple the team member with too little privileges, but of course they shouldn't be able to accidentally delete or change things.
Since MySQL doesn't have ROLES (as of the time the original question was asked, and as per Bill) then allowing any web script to just access MySQL with only one Super User is very risky.
There are other privileges that a user might need during an ordinary application, for example:
CREATE TEMPORARY TABLE
EXECUTE (stored procedures)
FILE (for SELECT INTO and LOAD DATA)
LOCK TABLES
There's also the possibility that minimal privileges could mean only SELECT on certain tables, and only SELECT and UPDATE on other tables, etc. This is subject to change any time the application's functionality is enhanced. And there are weird cases, like the need to have SELECT privilege on a table you never query, because it's referenced by the foreign keys in a table you UPDATE. So tracking minimal privileges is a royal pain.
What are you trying to restrict by using SQL privileges? You're the one who wrote all the code, so managing SQL privileges at a fine granularity shouldn't be necessary. Frankly, if your users are able to upload and run SQL statements that you haven't vetted, you have bigger problems:
SELECT * FROM mytable, mytable, mytable, mytable, mytable ORDER BY 1;
The real tasks you want to govern aren't at the database level, they're at the application business level. For example, a CMS has operations like create a page, edit a page, administer comments, etc. These tasks are higher-level than SQL privileges. You could mimic them with SQL roles (which are groups of privileges), but SQL roles aren't widely supported.
I don't know anyone who maps their application users to distinct MySQL users. They're users you authenticate in your application, after the app has connected to the database (the users are just rows of data in the database).
So you're probably better off having your web app use a single MySQL user with full privileges.
A web app usually uses just one user to access the DB, rather than a user per actual user account. Applying minimal privileges is good practice. The username and password is going to be coded into your script (does anyone obfuscate this?) so there's room for compromise if your scripts aren't managed properly.
In my experience, I very, very rarely have the app delete rows - much better to flag a row as deleted as you then have an audit of what is there rather than not knowing what was there! This approach also helps keep tables and indexes optimised.
Therefore, I would suggest allowing only INSERT, UPDATE and SELECT - it will quickly become apparent if parts of your app need to be relaxed a bit!
Allowing more privileges can only broaden the possibility for DoS attacks by issuing resource intensive commands, or allowing malicious data attacks.