So I'm finally posting again. I've been constantly think about this post, just didn't do it. So I finally got my web server switched over to FreeBSD, there are still some things I would like to improve, but it's running over there now. I went with apache, just because that's what I know better, and there were already so many complications to work on. Maybe I will try another web server or two some time in the future.
So regardless of what web server you are using, you most likely will be running some non-static pages or applications. These can be anything such as webmail, wikis, administrative tools, etc. And to be honest it doesn't much matter what you run, most of the same concerns with setup and security apply to you. Since the most common language at this current time seems to be PHP for many of these things, I'm going to cover that.
I was always a Perl guy myself. I've built whole ticket systems, email handling scripts, even a password decoder for proxy software in it before. It's OK don't worry, I worked for the ISP and we had to have a way to go into the registry (Windows) and pull out the encoded password and remove the software, so people wouldn't sue us because they forgot their passwords. And by now you are most likely saying what does this have to do with anything we are talking about. Well that's simple, back when PHP stood for Personal Home Page and not PHP: Hypertext Preprocessor. It had a lot of things from Perl in it. They just tried to make it easier to use. And overall it was easier to embed in the web pages instead of calling external scripts like CGI scripts that would generate html code. I think that the simplicity of PHP made it so wide spread. I also think that because of this you end up with a lot of issues too.
Let me write again I'm not a security expert. Every environment is different and has different requirements and concerns. So please take everything here as a starting point and not an ending point. A lot of the items will be at a high level as well. If you want to know details about them you should research the settings and see how they will directly impact your web setup. In fact part of my hesitation was thinking about the HOWTO junkies that copy and paste things and think they are good. This seems to be a bigger issue with the Linux community than the BSD one, however a lot of Linux guys (like myself) have been moving to BSD and this is mostly not operating specific.
So lets start with apache. Since this is our base. I ended up using apache 2.4 from packages. My old Debian web server was a 2.2, and there are some notable changes. The main ones that caused me some issues were the granting and denying users and groups access to locations and directories. So things like:
Order deny,allow Deny from all
Order allow,deny Allow from all
Require all denied
Require all granted
On the whole it seemed a lot easier and shorter to handle. I also liked being able to group things together into the RequireAll and being able to put the keyword not in there, so you could block an ip range for instance. In either case this is the extent of which I will cover this topic, because access control to directories and locations is very specific to the web site itself. You may want IP Address restriction, or even hooking up to some database for user authentication. That is great and fun to do, but not what I'm aiming for here.
So the first thing I want to show you is the default http.conf entry for the root directory on your server:
<Directory /> AllowOverride none Require all denied </Directory>
So basically, it doesn't allow any overrides by default, so the .htaccess file or similar means will not override permissions or options. And it blocks everyone from everywhere. Seems reasonable. And of course if you are in a jail then the root directory is the root of the jail anyways so it might not be exposing too much. I add a few things.
The first thing is, we aren't allowing overrides, but we really aren't defining any base options. So for example, I may turn off a few things, by adding:
Options -Indexes -Includes -MultiViews
You can do more, like -ExecCGI for instance. Take your time and go over the options and your needs.
Another thing that I like to do with the root directory section is define what methods I accept. So for example:
<LimitExcept GET POST HEAD> Require all denied </LimitExcept<
So in this example we allow GET, POST and HEAD. These may vary depending on your application and your needs. There are a ton of other methods like OPTIONS for example. You may need them, you may not. But I would disable everything you don't need, as you never know how something may react when called with a method you were not prepared to handle in your code. And of course if you are like most people you are running things you didn't write and have very little control over.
Of course there is configuring SSL (even though I say SSL, I mean TLS, as of right now no variant of SSL is safe). Usually you do this by enabling the ssl module and then setting up some ssl settings. In the FreeBSD configuration you can uncomment:
LoadModule ssl_module libexec/apache24/mod_ssl.so
To start. Then at the very least you need 3 other settings:
SSLEngine on SSLCertificateFile /usr/local/etc/ssl/certs/web.pem SSLCertificateKeyFile /usr/local/etc/ssl/keys/web.pem
Those values are totally made up, as is obvious by the generic names, but you get the point. Then you can make some redirects from http over to https. Again this depends on your needs. A lot of things don't need to be https.
Then there are some security through obscurity settings. These include ServerTokens and ServerSignature. These allow you to make your server less verbose about the software and versions running on it. Most people if they are so inclined will find the information they need, so this will only create a minor slow down at best. But adding:
ServerTokens Prod ServerSignature Off
Can't hurt right? You can always leave them on for your test and development environment. In production they just add more noise and output.
Another setting is the FileETag. This can have adverse affects as well though. Caching can use this information to validate files and help speed up browsing. It makes these systems look for things like Cache-Control and Expires headers instead. From a security standpoint however these tags have been comprised of information about the actual files. This could expose inode information, modified times and sizes, etc. So you have a few choices. You can disable them completely:
Or you can specify the items you want to use:
FileETag MTime Size
Notice I removed INode as an option there. So depending on your needs adjust this as you like. Also note worthy is that some functions such as WebDAV require ETag and specific settings. As always, read and use caution with any options.
The next thing will make your server non-compliant according to apache themselves, "Despite claims to the contrary, TRACE is not a security vulnerability, and there is no viable reason for it to be disabled.". That said, it's mostly used for debugging, and we may have already disabled it when we blocked our methods above. I say if you want it put it in your test and development environment. But again it will depend on you and your environment. So to disable it, we can add:
Another setting some people tweak is the TimeOut value. This defaults to 60 seconds in current versions of apach 2.4. That of course could change from update to update or version to version. It may be a good idea to define it anyways. But some times people lower it to avoid DOS or DDOS issues. Obviously the longer it takes for your server to handle I/O the easier it would be to cause a denial of service. This will of course depend on how long it takes your applications to run. If it's just small static pages, you should be able to go smaller. If you have large applications you may need to increase it.
There are some very specific types of attacks, one of which is cross site scripting. The current recommended method of helping with this as of this date for version 2.4 of apache is to add:
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure Header set X-XSS-Protection "1; mode=block"
The first item helps to prevent stealing or modifying a web applications session and cookie. The second forces cross site protection which can usually be bypassed in most browsers. As always consult documentations and your needs. And remember everything is a snap shot in time. Settings change, attacks change.
Another very specific attach is clickjacking. To describe this in the most basic way, this is an attach that makes users think they are clicking on something different than what they think they are clicking on. The current apache line for this is:
Header always append X-Frame-Options SAMEORIGIN
Frames in this context applies to frames, iframes and objects. And you can also set this to DENY to block being displayed in a frame at all, or ALLOW-FROM and a specific address/page.
Is that it? Well that's all I'm talking about, but certainly not. As I mentioned above, this is a starting point. And it doesn't cover other OS level security, like running in a jail or chroot, changing file permissions, running as the proper user, or even additional logging. Use some common sense, research things, etc. And I didn't cover mod_security, I think that topic would be massive in and of itself.
And we have made it this far and not even mentioned PHP. So the first thing I will mention about PHP actually applies to your apache configuration. Well let me clarify that, you can put it in your PHP configuration, but I always find it better to do on a site by site basis. There is a parameter called open_basedir, which is sort of like your DocumentRoot for PHP to access other files. For example if you have the following:
In your configuration, it may be a good idea to add:
php_admin_value open_basedir /example/mainweb
Or even a sub directory where PHP needs access to and not the whole DocumentRoot. This you will definitely need to play with. Some times PHP accesses files in multiple locations, a good example would be a wiki server where the web document and script portion is in one directory and the data is in another. The variable accesses colon separated paths under FreeBSD (I think most Unix-like OS) and I believe semi-colon on Windows (but I could care less because I don't run important things on Windows). So for example:
php_admin_value open_basedir /example/wiki/:/usr/local/www/wiki/
This setting blocks PHP from opening files from outside of this scope with open functions. Of course this will break a lot of applications if you don't know what they need to access.
One of my other favorites is the disable_functions in the php.ini This can disable any function that PHP has. Lets take the simplest example. Lets say I have user pages on in apache, and someone uploads the a php script with the phpinfo command in it, but I don't want them to see it. I would simply add that function name to the disable_functions (which are coma separated) and then the script would not run. So for a very basic example:
disable_functions = ini_set,php_uname,getmyuid,getmypid,shell_exec,exec,system,chgrp,chmod,chown,lchgrp,lchown
And that is just a small fraction of the functions. So you will need to research both what you want to block and what your applications need. Since php is plain text, most of the time you can grep your applications for a particular function.
Another common security through obscurity is to hide the PHP version and headers. This can be done with:
expose_php = Off
As with apache above, there are things in PHP that can cause a DOS or a DDOS. One of which is how long can a script take to parse input. In the case of web scripts this is GET and POST data mostly. To adjust this:
max_input_time = 30
The time is in seconds. Of course if you want someone to upload big pictures to a webmail or wiki application this would need to be bigger. As with everything it varies depending on what you are doing, I'm just trying to give you some rough ideas and starting points.
Similarly, I may want to limit the amount of memory a process can use. I can do this as follows:
memory_limit = 64M
But that will depend on what you are doing too. I've seen this value set as low as 8M in production, and also much higher.
Also you can limit uploaded file sizes as follows:
upload_max_filesize = 1M
Is that right for your server or use, I don't know. But it could stop someone from filling up a temporary upload space with one giant file. You can of course set the value to whatever you need. Don't be a copy and paste monkey ;)
Here's an interesting one. PHP has the file open function fopen. You may think that it just accesses local files, and you'd be wrong. It is url aware, and can access things like web pages or ftp servers. So to disable those functions you add:
allow_url_fopen = Off
If you don't need remote content this is a good option.
Sessions can be a big deal when it comes to security. You want users to be able to have custom settings when they are in an application. This all gets stored in the session. We talked a little about it with apache above. Here are a few settings:
session.use_strict_mode = 1 session.name = SOMETHINGUNIQUE session.cookie_httponly = 1 session.hash_function = 7
Is that it? Not even close. Do you know how many settings you can change in PHP? Even just for the session and cookie settings I barely scratched the surface. And of course as stated above many times this is a starting point. You can enable more detailed logging, via files or syslog, etc. You can adjust OS permissions. Another thing I didn't cover is Suhosin, as with mod_security for apache this could be very detailed. I will say that it is a package in FreeBSD and adds even more settings for you to adjust in PHP. I do recommend you install it and take some time to go over those settings.
I think that's all I can physically write in one post. I hope the information has been some what useful to anyone who actually looks at my stuff. I realize that security is many things to different people, and I generally try to avoid talking about it in such a direct way. I hope that you can all realize the intent of this post. And if anyone blindly copy and pasted anything into their configuration don't blame me. Especially if you do it any time other than when this was made, as options and features change all the time.