This is an old revision of the document!
Security
Topics related to server security.
This will get divided into sections as it grows.
Command Line (BASH)
Idle Log-out
If you want idle sessions to be logged out automatically, put something like the following into /etc/profile.d/timeout.sh (or another similar name). In modern distributions (Gentoo and RHEL5) placing the file in /etc/profile.d/ should cause it to be automatically executed at each log-in.
[ -n "${TMOUT}" ] && readonly TMOUT [ -z "${TMOUT}" ] && declare -irx TMOUT=7200
This sets a 7200-second (2-hour) time-out and makes the variable read-only so that it cannot be changed by the user.
Apache
Using .htaccess to restrict access
There is a great deal that can be done with .htaccess. Most Apache configuration parameters can be modified by placing an .htaccess file in a directory, authentication can be specified on a per-directory basis, and more. There is a performance penalty for using .htaccess, however, as described on the Apache Foundation's htaccess tutorial page.
Here are some good sites explaining the use of .htaccess:
- And, of course, The Apache Foundation
Restricting access by IP address
One of the things you will constantly see in your server logs are attempts to find weaknesses in your server's configuration. I have observed that most often these attempts come from Asia followed by the Middle East (Turkey etc.). Only rarely do I see attempts from North America, and when I do a single report almost always makes them stop, whereas reports to Asian or Middle East ISPs often get returned because their “abuse” mailbox is invalid or inactive (e.g., full because probably nobody ever checks it).
In order to relieve myself of this time-wasting annoyance, for web sites which have no application in certain regions (do I really want anyone in China looking at my family photo album site since I don't have any relatives there?) I simply block the IP address ranges and large ISP domain names for those countries by placing them in the configuration file or the “.htaccess” file for the web site.
For example, on my family photo albums site I want to exclude people from Asia who constantly create accounts in order to place ads on it, and I don't want search engines to index it either. To cover most of my problem areas without going overboard, I can use these lines:
order deny,allow deny from .com.cn deny from 59.0.0.0/255.128.0.0 deny from 120.28.64.0/255.255.192.0 deny from 120.40.0.0/255.252.0.0 deny from 125.78. deny from .googlebot.com deny from 66.249.64.0/19 deny from .microsoft.com deny from .msnbot.com deny from 65.52.0.0/14
Country IP block lists
A good source for country IP blocks is this web site, although the lists are specific to each country so you may end up with more lines than if you wanted to cover a region with several countries. For example, you see that I use 59.0.0.0/9 in my example above, which is easy to write and covers a large portion of Korea, China, India, etc., however, it includes some Australian ISPs whom I really don't mind, but for my photo albums site it's fine since I don't have family there either.
Blocking entire countries means should probably be done in your main Apache configuration files, within <Directory> or <Files> blocks, to avoid the performance penalty mentioned above. I made this easy for myself by creating a directory called “country-block-lists” and then placing Include directives as desired in various web site definitions. For example:
Order deny,allow Include /etc/apache2/vhosts.d/country-block-lists/China Allow from all
You could also use the country lists on the “countryipblocks” web site with Sendmail on a server to block mail from places you don't have any reason to talk to. Just use sed to convert “deny from ” into “Connect:” and then again to tack-on the REJECT message, like so:
sed -e s/"deny from "/"Connect:"/ -i korea.list sed -e s/$/"\tREJECT"/ -i korea.list
PHP Coding
Storing passwords in code
Passwords, such as for PostgreSQL or MySQL, must be accessible from PHP (therefore readable by the Apache web server and possibly from command-line scripts run by ordinary/unprivileged users) yet protected from being seen in plain text in order to prevent undesired access to the database from outside the application. In rare situations1) it is possible for Apache to deliver unprocessed PHP code to a user's browser, which could reveal passwords if proper care is not taken.
Here are ideas to keep tight security for passwords stored in PHP code.
- Store passwords outside the Apache DocumentRoot so they cannot be directly delivered to a user's browser
- Set permissions to not permit world read-ability. For example, set the ownership to root:apache and set the permissions to 0640 if the scripts will only be run by Apache or root. This will prevent other users from running PHP scripts from the command-line that require reading such a file.
- Encrypt passwords using a method that can be reversed.
- Store the encryption key in a separate file on the server, also outside Apache's DocumentRoot, so that if anyone sees the code they cannot decrypt the password without already having access to the server. This becomes a bit complicated if multiple web servers are involved, but can be handled by placing the encryption keys in a separate source code repository or Cfengine rule that the sysadmins control rather than the developers, so the same key can be deployed and updated to multiple web servers.