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.
Related
I have php with nginx. I want to make PHP save it's sessions on RAM for security reasons. Is there any way doing it?
If it's impossible, is there is any advice to make php sessions unrecoverable from hard disk after the server is shutdown?
After a lot of searching I've found the Shared memory module of php, which can be used like persistent memory cache over sessions. is it shared with other applications too?, and how secure is it?
I would use memcached to store session data in RAM. If you are already using a database you might simply use a memory storage engine. However, I don't get what security reasons you have in mind. If you have concerns that somebody is able to access your session data then make sure that he is not able to do so. Regardless where they are stored as otherwise the security is completely broken.
Update
You told that the client and the server are running on the same physical machine. I can imagine of a kiosk application.
As a general advice the client needs to run as a different user. This is possible in Windows too. Then make sure that the client has a limited system access and is not able to access the secret data. that's it.
You might also consider to separate server and client using virtual machines.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I had finally managed to get a very successful business running, however I have been constantly attacked. The attacker was getting shell access to parts of the site and managed to create/edit my PHP files to send update queries to my database.
I had help from sitelock to secure the site and I even paid them extra to carefully go through code and make sure there are no vulnerabilities. The attacker managed to succeed again, and brought me entire business down.
Now here is what I need: The users need to be able to view the database, and I also have a cron job to update the users "balances" every 20 minutes. Sometimes I need to administrate the site, which means adding new information to the database.
Then I had a great idea (I thought), but sitelock didn't think it was smart:
The main database would be set to VIEWING only. There would be no password available anywhere on the main site that would allow UPDATE or INSERT queries to be sent.
Meanwhile, I would have a secret site on another server from which I do the updates from. I would run my PHP script (with my cron job) to remotely access the MAIN database with a more priviledged database user.
Sitelock claims that accessing the database remotely could cause even more risks, but I don't see how it would. Assuming that my secret site doesn't get hacked as well, I don't see why this would be so dangerous. Can someone explain why it would be?
Due to lacking of vital information, it is quite hard to provide an answer. Nevertheless, I'll give it a try.
Being unter attack is normal.
Let me note, that most websites are unter attack all the time. Since you can't disable attacks, you need to protect your system ad your WebApp. It's important
to keep the operating system and its configuration current
write code, that doesn't expose attackable points
probably install protective system components.
But let me explain, what you might wish to do:
First of all, disable your site and collect evidence related data!
Disable your site, in a fundamental way:
Cut the internet connection.
At least disable each and any script [less good].
Don't just disable the index.php script! Intruder does know other vulnerable points of your WebApp! Use .htaccess to disable each script in each folder!
Then, backup the server's state to your local machine. Vital technical artifacts are in these classes of files:
Your PHP scripts.
The databases / table of your database server.
The server's log files.
The server's configuration files [notably /etc].
In case enough bandwidth is available, backup the whole server to your local machine!
For sure, run the backup through ssh only!
Next, figure out, how intruder managed to access
your site. Intruder might have obtained access at the operating system level [e.g. telnet] or at the web application level.
Your intruder may have changed not only your web-application, but as well other parts of your server's software or system configuration.
While you focus on the front-end, the actual problem might be at another location.
Check your system for root kits.
A root kit scanner like RootKit Hunter might be helpful. The article 'How to scan Linux for rootkits with rkhunter' might provide some help.
Note, in case you set up a new system, a permanent installation of a root kit hunting tool would be useful anyway.
General rule of thumb: Security by obscurity is worthless.
If you use a secret site to perform certain task, intruder may identify the remote too - and probably break into that site - in case the remote site or it's access part to the main site, might have the previous vulnerability too.
Enhance the security level of your site.
Disable each and any service, that isn't permanently required.
Add and enable Apache's mod_security module to automatically reject certain potentially dangerous request.
Enable PHP's safe_mode in case you run PHP prior of release 5.3.0. This PHP option disables certain dangerous features.
Follow the guidelines described in OWASP's PHP security Cheat Sheet
Access your operating system's shell using ssh. No other way is secure!
Protect your site against man in the middle attacks using https.
Protect user sessions using https.
If your site uses http [not https], an attacker might grab the session ID of a legal user of the site. If attacker own the ID, attacker has all those right, that the legal user has.
Don't forget, that grabbing session IDs is simple, if legal user uses
an insecure [public] WiFi network
a non-switched Ethernet
a compromised PC
A virus/trojaner infiltrated system might grab each and any information that legal user exchanges. Thus, most technical measures might fail.
Don't believe, that automated security checks do find each and any security problem.
While SiteLock might find certain classes of problems of web-applications, certain others are far beyond the scope of any automated security check. Automated security checks are incomplete by nature.
Your need specialists for each technical domain.
To protect your site, you need an operating system / admin specialist and a PHP specialist.
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.
For a simple web application, I'd like to be able to take advantage of several UNIX features that are stable, have a long history, and are well proven in production, rather than having to write my own code. Take users, for example. Rather than having an entire user, group, permission infrastructure in my webapp, I'd like to be able to simply piggyback on top of the equivalent features of UNIX.
Is there a PHP library that will allow me to register users, log them in, manage permissions, etc. ?
It's really not a good idea to fumble around with the user and permission settings of the actual system that is hosting your site. If you want to protect individual directories of your site, you're better off using .htaccess files. If OTOH you're working with virtual URLs, you'll have a hard time mapping the UNIX directory permissions to them anyway.
Based on your comment to deceze's answer, are you looking for something like PHP's filesystem functions?
Then, there is system and its related functions, which gives access to Unix commands, but I'd recommend other ways of doing things if possible.
Edit: In response to the comments about needing user and group functionality:
Firstly, in case your plan is to let web users have access to the whole file system (or even just their regular log in directories), I just want to advise against that - lots of security concerns (eg. if someone else gets into a user's account, they could delete everything to which they have access).
The little experience I have with handling users in PHP was in some beginner level training. In that class, we had our users in an SQL database and used sessions. We didn't use SSL, but I'd advise some sort of crypto when passing passwords around.
If you're using Apache, it can handle the authentication for you. Other server software can probably do the same, but Apache is all I've ever worked with. I can't address whether Apache can handle sessions itself and don't have the time to research it right now.
If php or your webserver is running with root rights it should be no problem to use this functions.
For security reasons I would strongly recommend to reimplement these things or using any existing php library instead!!
It seems there are standard functions for interfacing with Kerberos or Radius in php.
These both have a long history and are well proven in production, while being separate from the system users.
In ASPNET, I grew to love the Application and Cache stores. They're awesome. For the uninitiated, you can just throw your data-logic objects into them, and hey-presto, you only need query the database once for a bit of data.
By far one of the best ASPNET features, IMO.
I've since ditched Windows for Linux, and therefore PHP, Python and Ruby for webdev. I use PHP most because I dev several open source projects, all using PHP.
Needless to say, I've explored what PHP has to offer in terms of caching data-objects. So far I've played with:
Serializing to file (a pretty slow/expensive process)
Writing the data to file as JSON/XML/plaintext/etc (even slower for read ops)
Writing the data to file as pure PHP (the fastest read, but quite a convoluted write op)
I should stress now that I'm looking for a solution that doesn't rely on a third party app (eg memcached) as the apps are installed in all sorts of scenarios, most of which don't have install rights (eg: a cheap shared hosting account).
So back to what I'm doing now, is persisting to file secure? Rule 1 in production server security has always been disable file-writing, but I really don't see any way PHP could cache if it couldn't write. Are there any tips and/or tricks to boost the security?
Is there another persist-to-file method that I'm forgetting?
Are there any better methods of caching in "limited" environments?
Serializing is quite safe and commonly used. There is an alternative however, and that is to cache to memory. Check out memcached and APC, they're both free and highly performant. This article on different caching techniques in PHP might also be of interest.
Re: Is there another persist-to-file method that I'm forgetting?
It's of limited utility but if you have a particularly beefy database query you could write the serialized object back out to an indexed database table. You'd still have the overhead of a database query, but it would be a simple select as opposed to the beefy query.
Re: Is persisting to file secure? and cheap shared hosting account)
The sad fact is cheap shared hosting isn't secure. How much do you trust the 100,500, or 1000 other people who have access to your server? For historic and (ironically) security reasons, shared hosting environments have PHP/Apache running as a unprivileged user (with PHP running as an Apache module). The security rational here is if the world facing apache process gets compromised, the exploiters only have access to an unprivileged account that can't screw with important system files.
The bad part is, that means whenever you write to a file using PHP, the owner of that file is the same unprivileged Apache user. This is true for every user on the system, which means anyone has read and write access to the files. The theoretical hackers in the above scenario would also have access to the files.
There's also a persistent bad practice in PHP of giving a directory permissions of 777 to directories and files to enable the unprivileged apache user to write files out, and then leaving the directory or file in that state. That gives anyone on the system read/write access.
Finally, you may think obscurity saves you. "There's no way they can know where my secret cache files are", but you'd be wrong. Shared hosting sets up users in the same group, and most default file masks will give your group users read permission on files you create. SSH into your shared hosting account sometime, navigate up a directory, and you can usually start browsing through other users files on the system. This can be used to sniff out writable files.
The solutions aren't pretty. Some hosts will offer a CGI Wrapper that lets you run PHP as a CGI. The benefit here is PHP will run as the owner of the script, which means it will run as you instead of the unprivileged user. Problem averted! New Problem! Traditional CGI is slow as molasses in February.
There is FastCGI, but FastCGI is finicky and requires constant tuning. Not many shared hosts offer it. If you find one that does, chances are they'll have APC enabled, and may even be able to provide a mechanism for memcached.
I had a similar problem, and thus wrote a solution, a memory cache written in PHP. It only requires the PHP build to support sockets. Other then that, it is a pure php solution and should run just fine on Shared hosting.
http://code.google.com/p/php-object-cache/
What I always do if I have to be able to write is to ensure I'm not writing anywhere I have PHP code. Typically my directory structure looks something like this (it's varied between projects, but this is the general idea):
project/
app/
html/
index.php
data/
cache/
app is not writable by the web server (neither is index.php, preferably). cache is writable and used for caching things such as parsed templates and objects. data is possibly writable, depending on need. That is, if the users upload data, it goes into data.
The web server gets pointed to project/html and whatever method is convenient is used to set up index.php as the script to run for every page in the project. You can use mod_rewrite in Apache, or content negotiation (my preference but often not possible), or whatever other method you like.
All your real code lives in app, which is not directly accessible by the web server, but should be added to the PHP path.
This has worked quite well for me for several projects. I've even been able to get, for instance, Wikimedia to work with a modified version of this structure.
Oh... and I'd use serialize()/unserialize() to do the caching, although generating PHP code has a certain appeal. All the templating engines I know of generate PHP code to execute, making post-parse very fast.
If you have access to the Database Query Cache (ie. MySQL) you could go with serializing your objects and storing them in the DB. The database will take care of holding the query results in memory so that should be pretty fast.
You don't spell out -why- you're trying to cache objects. Are you trying to speed up a slow database query, work around expensive object instantiation, avoid repeated generation of complex page, maintain application state or are you just compulsively storing away objects in case of a long winter?
The best solution, given the atrocious limitations of most low-cost shared hosting, is going to depend on what you're trying to accomplish. Going for bottom of the barrel shared-hosting means you have to accept that you won't be working with the best tools. The numbers are hard to quantify, but there's a trade off between hosting costs, site performance & developer time (ie - fast, cheap or easy).
It's in theory possible to store objects in sessions. That might get you past the file writing disabled problem. Additionally you could store the session in a mysql memory backed table to speed up the query.
Some hosting places may have APC compiled in.. That would allow you to store the objects in memory.