Just to make sure everyone is on the same page these are the credentials I'm talking about...
$user = 'user';// not actual user, not root either
$pass = 'pass';// not actual password
$server = 'localhost';
$database = mysqli_connect($server,$user,$pass,true|false);
So I'm talking about the passwords used to connect to the database, not the passwords in the database (which for clarification I have hashed with salt and pepper).
I have not read anything that I think remotely suggests you can have 100% foolproof security since obviously the server needs to connect to the database and get the content for visitors 24/7; if I am mistaken I would love to hear how this would be possible.
So let's presume a hacker has root access (or if that does not imply access to the PHP code let's just say then have access to all the PHP source code) and they (in this circumstance) desire to access/modify/etc databases. If we can not prevent them should they have access to the PHP source then we want to slow them down as much as possible. I can keep each site/database connection password in separate files (can as in I'm a few weeks from finishing multi-domain support) for each site and not inside of public_html (obviously). I use serialize and unserialize to store certain variables to ensure certain level of fault tolerance for when the database becomes unavailable on shared hosting (preventing site A from looking and acting like site B and vice-versa) as the database can sometimes become unavailable numerous times a day (my database error logs are written to when the SQL service becomes available again and catches these "away" errors). One thought that has crossed my mind is determining a way to store the passwords in one hash and un-hashing them to be used to connect to the database by PHP though I'd like some opinions about this as well please.
If someone has a suggestion from the database perspective (e.g. having the ability to restrict users to SELECT, INSERT, DELETE, UPDATE, etc and not allowing DROP and TRUNCATE as examples) my primary concern is making sure I am SQL neutral as I plan to eventually migrate from MySQL to PostgreSQL (this may or may not be relevant though if it is better to mention it). I currently use phpMyAdmin and cPanel and phpMyAdmin shows the connected user is not the same as the site's database user names so in that regard I can still use certain commands (DROP and TRUNCATE as examples again) with that user and restrict the SITE user permissions unless I am mistaken for some reason?
Is there a way to configure the context of where the connection credentials are accepted? For clarification a hacker with access to the source code would not be accessing the site the same way legitimate users would.
Another idea that crossed my mind is system based encryption, is there a near-universal (as in on every or almost every LAMP web host setup) web-hosting technique where the system can read/write the file through Apache that would introduce a new layer that a hacker would have to determine a way to circumvent?
I am using different passwords for each user of course.
I currently am on shared hosting though hopefully my setup will scale upwards to dedicated hosting eventually.
So what are the thoughts on my security concepts and what other concepts could I try out to make my database connection credentials more secure?
Clarification: I am looking for ideas that I can pursue. If there is disagreement with any of the suggestions please ask for clarification and explain your concern in place of debating a given approach as I may or may not have even considered let alone begun to pursue a given concept. Thanks!
There is little to be gained from trying to slow down an intruder that already has root access to your system. Even if you manage to hide the credentials well enough to discourage them, they already have access to your system and can wreak havoc in a million ways including modifying the code to do whatever they wish.
Your best bet is to focus on preventing the baddies from ever penetrating your outer defenses, worry about the rest only after you've made sure you did everything you can to keep them at the gates.
Having said that, restricting database user accounts to only a certain subset of privileges is definitely not a bad thing to do if your architecture allows it.
As code_burgar says, once your box gives root, it's too late. That being said, I have had to implement additional security mesures on a project I was involved with a while back. The solution to store config files in an encrypted partition so that people with direct access to the machine can't pull the passwords off by connecting the drive to another PC. Of course this was in addition to file system permissions so people can't read the file from inside the OS itself.
Another detail worth bringing up, if you are really paranoid on security:
$user = 'user';// not actual user, not root either
$pass = 'pass';// not actual password
$server = 'localhost';
$database = mysql_connect($server,$user,$pass,true|false);
unset($user, $pass, $server); // Flush from memory.
You can unset the critical variables after use, ensuring they cannot be var_dumped or retrieved from memory.
Good-luck, hope that helps.
You want to approach security in layers. Yes, if an attacker has root access, you're in a very bad place - but that doesn't mean you shouldn't protect yourself against lower levels of penetration. Most of these recommendations may be hard to do on shared hosting...
Assuming you're using a decent hosting provider, and recent versions of LAMP, the effort required to gain root access is substantial - unless you're a very lucrative target, it's not your biggest worry.
I'll assume you harden your server and infrastructure appropriately, and check they're configured correctly. You also need to switch off services you don't need - e.g. if you have an FTP server running, an attacker who can brute force a password doesn't need root to get in.
The first thing you should probably do is make sure that the application code has no vulnerabilities, and that you have a strong password policy. Most "hacks" are not the result of evil geniuses worrying away at your server for months until they have "root" - they are the result of silly mistakes (e.g. SQL injection), or weak password ("admin/admin" anyone?).
Next, you want to make sure that if your webserver is compromised - but not at "root" level - you can prevent the attacker from executing arbitrary SQL scripts. This means restricting the permissions of your web server to "read and execute" if at all possible so they can't upload new PHP files. It also means removing things like CPanel and phpMyAdmin - an attacker who can compromise your production server could compromise those apps, and steal passwords from you (run them on a different server if you need them).
It's definitely worth looking at the way your database permissions are set up - though this can be hard, and may not yield much additional security. At the very least, create a "web user" for each client, and grant that user only "insert, update and delete" on their own database.
I have found a solution for PHP(Linux) On the root create a directory say db and create a class and define all the database connection variables and access methods in a class say DBConnection.php now your website is example.com you are storing your files in public_html directory create a php file under this directory to connect and do all database operations and include DBConnection.php file using following statement
require('../db/DBConnection.php');
this file cannot be accessed using 'www.example.com/db/DBConnection.php'
you can try this on your web site.
Related
The application produces data by user. Each user has a unique user id and associated unique file permissions. User files are stored in individual directories with associated user permissions on each directory.
The requirements are to provide secure individual user access to only user's files via a portal, assume PHP. A design being considered is to mimic the directory structure and permissions in the portal environment. If it were possible to run PHP as a user then the system permission access security could be used. (this would limit the scope of security implementation to the login process and not to the application.)
Question: Is it possible to run PHP as a user and assume user file permissions?
Research has identified some similar questions, but not the direct question of running PHP as an individual user.
There are a handful of solutions, from best to worst:
Use something like FPM to configure separate process pools configured to run as each user.
Only best if you have a small, fixed number of users, becomes a config/admin nightmare otherwise.
Basically shared hosting.
Stop relying on OS-level users and permissions enforcement altogether and build it into your app.
Create your own permissions enforcement abstraction layer in PHP.
Basically #2, but without the first part, which actually makes it more complicated.
Use posix_seteuid() and posix_setegid() to change the effective UID and GID of the running process.
"But wait!" I hear you say, "That last option seems like exactly what I need! Why is it the worst?"
Because in order to change the UID or GID of a process that process must first be running as a user that is permitted to do such a thing. That user is root.
Running PHP as root, even briefly in order to drop to a different UID/GID, is a massive security hole. Even the most minor bug or flaw is now game over, and this is exponentially more true if you're writing a file manager.
"That's fine," you retort, "this is only for internal use with trusted users, so I'm not worried about security."
NO. BAD. [bops you with a rolled-up newspaper]
Never. Trust. Users.
At best they will never intentionally break or compromise your app, but:
This view is naieve at best.
The universe is constantly manufacturing new and innovative forms of idiot.
Smart, well-meaning idiots like to find "workarounds" so that they don't have to bother you.
Compromised client machines are a threat.
Assuming that your internal network is not compromised nor ever will be is a mistake. [see #4]
Security auditors will crucify you.
and the list goes on.
TL;DR: Unless you're setting up per-user vhosts/sites/apps. Store the files outside of the docroot and use Option #2 to gate access via PHP. If anyone catches you running PHP as root you're going to have a bad time.
Some specific questions beyond this:
1) What are your most critical security considerations? I feel like I've secured the data in transit with encryption/https, data at rest by encrypting sensitive data that I don't need access to, set up a firewall to access phpmyadmin, changed root passwords, etc., but I'm not confident that I've 'checked all the boxes' so to speak. Is there a robust guide to securing mysql/php applications out there somewhere? Perhaps a pen test is the only way to get confidence to some degree?
2) What are your backup considerations? I've got a master/slave relationship set up for the mysql database in two different datacenters, and weekly backups of the production server itself. The code is all in source control, but I have some uploaded documents that I'd lose if the whole thing crashed on Day 6 after backups. Any ideas on that one? Considering moving the document storage to a different server and backing it up nightly, or asynchronously just saving the document on initial upload to two separate servers. They are not large docs, and volume isn't high yet, but, is that scalable?
I feel like I've secured the data in transit with encryption/https
It's not really clear from this how far you have gone, so forgive me if you have already addressed the following.
Obviously https secures the transmission of data between the client to your webserver but it should not be confused with an encrypted connection between your application and the database. Admittedly the risk factor of data being intercepted here is much lower, but it depends how sensitive the data is. Information on setting up encrytped database connections can be found here. As you are replicating between data centres you should consider setting up replication to use encrypted connections also.
Replication and backing up are not the same thing, once you have replicated the data from the master to the slave you still need to back up the slave. You can use mysqldump but the caveat is mysqldump creates a logical backup not a physical one so restore functions are slow and it's not good for scaleability. There's a good post here with solutions for making a physical backup instead.
Apart from that there are the usual kind of security measures you should implement with any system:
Create and assign separate user accounts for each process with the
minimum level of access permissions needed to perform their function.
Create an admin account with a non generic admin type username.
Remove root account and any others that are likely to get you pwned
like admin etc
Only encrypt data if you need to be able to decrypt it again. Salt
and hash sensitive data which is only needed for validation
(passwords etc) and save the resulting value in the database. Validate user inputs against the hash.
Depending upon your use case you may also consider:
In /etc/mysql/my.cnf within the mysqld section you can disallow
connections from anywhere except the local machine by adding
bind-address = 127.0.0.1
Disable loading files into MySQL from the local filesystem for
users without file level privileges by adding local-infile=0
Implementing stored procedures for common database tasks. These
have several benefits (as well as some drawbacks) but are good from a
security point of view as you can grant user accounts permissions on
stored procedures without granting any permissions on the tables
which they utilise.
Using database views to restrict access to some columns within
tables while still allowing access to other columns within the same
table. As with stored procedures there are pros and cons for views.
There are probably a million other things which someone who understands MySQL much better than I do could reel off to you without even thinking about it, but that's all I've got.
So, I'm writing a php script which will be tied to a cron job that will backup my site's db on a regular basis. The db will get saved to a new sql file daily just incase anything unfortunate should happen to the live version. I am aware of how bad it would be for someone to be able to get a hold of one of these files, exposing both the db structure and user email addresses (passwords are encrypted).
I am not extraordinarily security savvy, and this is one of those things you HAVE to get right the first time around. I'm not to prideful to admit when it's best to ask for help so I figured I'd inquire with the trusted Stack Overflow community. (I realize it's likely there is a question similar to this somewhere, but I have been unable to find it).
What steps do I need to take to make sure these files can't be accessed? Note, it is an Apache server. Is it enough to store them in a directory outside of the root which is limited to group read/write (no public read)? Or is it necessary to password protect the directory or even encrypt the actual files? I'd really rather not if I don't have to (encrypt the files), it would just make it more of a pain to use them, but if it's needed...
Also relevant, access to these files is NOT being built into an application interface. I don't need or want to have them accessible by an http request. FTP only. So my question isn't regarding any password protection of a UI.
Thank you all so much for your time!
Storing on the server
If you must, store them outside of the web root and download them with something like rsync over ssh.
Best option (assuming you're running MySQL)
Don't store them on the server, but rather run a cron on your local machine and use ssh and MySQL to do the dump to your local system. That way there is no ominous file someone can have that contains all of your data (unless of course your local network is compromised).
Another option (again another example with MySQL)
You might also look into doing database replication with your local machine by setting up a local MySQL server.
First time reader, first time poster (woo!)
So I've been implementing my login scripts for an informal website. Not likely to be compromised, but just to be safe, I'd like to ask if there's a security risk in having my MySQL database login stored in plaintext in the php code.
As far as I know, the code itself is parsed by Apache, so the end-user doesn't see it (just the output), which would mean it should be safe to keep... but I'd like a second opinion.
Summary:
Accessing database through mysql_connect, mysql_select_db, mysql_query. Login info stored in local variables defined at each iteration of the script, and (I think) dumped once script terminates.
Security vulnerability?
You could also consider moving the username/password combination to a seperate configuration file that lives outside the webroot. Make sure that place is not directly accessible from the webserver side.
That way, if for some reason the webserver decides not to execute PHP files anymore you don't lose the account information to the database server.
As an added bonus, if you use anything that makes a copy of the .php file (editors, SVN or whatever) in the webroot, you don't risk anyone getting around the .php execution.
That's very standard procedure for web applications that talk to a database.
I recommend taking read permissions away from the file for users other than the web server and yourself - if you have other users on your box that can spy on the file, they'll be able to access your mysql server.
Also, you should adjust the executable permission on the top directory as it'll prevent unauthorized users from even entering it.
Harden your mysql user's allowed host, so that only the boxes you need can connect to it.
Of course if your box is compromised and an attacker gains root access, there's little that will protect you.
You can add some additional layer of security by putting all your php files (except index.php of course) in a separate directory and protect them with a .htaccess file. This covers cases in which the php parser is not invoked and apache returns the files in clear text. One more thing that might be usefull: <?php defined('some_id_here') or die(); ?>. You can put this at the top of every php file except index.php (where you define some_id_here) so there is no direct access to your database-files.
Not having the bulk of the code within the webroot, where it is possible, however unlikely, is just the first line of defence that can be taken.
Your database should also be secure even if the database user and password was published - by the simple expedient of only allowing a small number of source machines to connect to the database anyway.
Defence In Depth
<?php // simplest /index.php, as the only .PHP file in the public-accessible webroot
require '../bootstrap.php';
I dont know how you connect to your MySQL database, but if you use PDO there is the possibility that the PDO constructor throws an exception.
If you dont catch this exception the Zend Engine will show a backtrace by default and reveal your connection details!
It is just normal to store the connection creds inside a php file/variable or, in that case you use PDO, in the DSN (Data Source Name). I would even suggest you to put it inside a php file, because it will gets parsed and not send plain into the web...
One step to more safety is to put the login details outside the www-root or protect it with an .htaccess file (this would make it impossible to access the file via the webserver).
However on my server it is impossible to connect not from localhost. So i dont care if someone reads my login details (it is not the case of course.).
Anybody who can login with root privileges on that web server (or possibly somewhat lower ones too) will be able to see your password -- but then, it's essentially impossible to defend against the super-user (wherever else you might keep your password, they could hack around and find it). Apart from this risk, you should be safe.
Edit: backups of the server could also be used (if unencrypted, or by somebody who can decrypt them) to recover your password if it's in-clear in your .php script. This possible attack might perhaps be mitigated (to great inconvenience/cost) by keeping the password on a different, secure location, and only sending it (securely) under highly restrictive circumstances. Is this the kind of attack you fear?
I wrote a PHP web-application using SQLite and sessions stored on filesystem.
This is functionally fine and attractively low maintenance. But, now it needs to run on a shared host.
All web-applications on the shared host run as the same user, so my users' session data is vulnerable, as is the database, code, etc.
Many recommend storing sessions in DBMS such as MySQL in this situation. So at first I thought I will just do that, and move the SQLite data into MySQL too. But then I realized the MySQL credentials need to be readable by the web application user, so I'm back to square one.
I think the best solution is to use PHP as a CGI so it runs as different user for each web-application. This sounds great, but my host does not do this it uses mod_php. Are there any drawbacks from an admin's point-of-view for enabling this? (performance, backward compatibility, etc)? If not then I will ask them to enable this.
Otherwise, is there anything I can do to secure my database and session data in this situation?
As long as your code is running as the shared web user, anything stored on the server is going to be vulnerable. Any other user could write a PHP script to examine any readable file on the server, including your data and PHP code.
If your hosting provider will allow it, running as PHP as a CGI under a different user will help, but I expect there will be a significant performance hit, as each request will require a new process to be created. (You could look at FCGI as a better-performing alternative.)
The other approach would be to set a cookie based on something the user provides, and use that to encrypt session data. For instance, when the user logs in, take a hash of their username, password (as just supplied by them) and the current time, encrypt the session data with the hash, set a cookie containing the hash. On the next request, you'll get the cookie back, which you can then use to decrypt the session data. Note however that this will only protect the current session data; your user table, other data, and code will still be vulnerable.
In this situation, you need to decide whether the tradeoff of the low cost of shared hosting is acceptable considering the reduced security it provides. This will depend on your application, and it may be that rather than trying to come up with a complex (and possibly not even very effective) way to add security, you're better off just accepting the risk.
I don't view security as all or nothing. There are steps you can take. Give the web db user only the permissions it needs. Store passwords as hashes. Use openid login so users provide their credentials over SSL.
PHP on cgi can be slower and some hosts may simply not want to support more than one environment.
You may need to stick with your host for some reason, but generally there are so many available that it is a good reminder for people to compare functionality and security as well as cost. I have noticed many companies starting to offer virtual machine hosting -- nearly dedicated server level security in terms of isolating your code from other users -- at what is to me reasonable cost.
A shared host is no way to run a web site if you are conscious about privacy and security of your data from the sites that you share the server with. Anything accessible to your web application is fair game for the others; it'll only be a matter of time before they can access it (assuming they do have incentive to do that to you).
"you can place your DB connection variables in a file below the web root. this will at least protect it from web access. if you're going to use file based sessions as well, you can set the session path in your user's directory and again outside the web root."
I don't have an account so I can't downvote that.. but seriously it is not even relevant to the question.
Duh you store stuff outside the webroot. That goes for any hosting scenario and is not specific to shared hosting. We're not talking about protecting from outsiders here. We're talking about protecting from other applications on the same machine.
To the OP I think PHP as CGI is the most secure solution, as you already suggested yourself. But as someone else said there is a performance hit with this.
Something you might look at is moving your sessions and db to MySQL and using safe_mode and/or open_basedir.
I would solve the problem with a infrasturcture change instead of a code one.
Consider upgrading to a VPS server. Nowdays you can get them very inexpensive. I've seen VPS's starting # 10$/mo.