cPanel Security Advisor: Don’t Take it to Heart

Posted by Nessa | Posted in uncategorized | Posted on 19-02-2014

3

cPanel 11.40 introduces a new feature in WHM called “Security Advisor“. I don’t mess with WHM a lot so while I was vaguely aware that such a feature existed in cPanel, only today did I actually mozy over and give it a run.

Well, it’s pretty obvious that this tool was whipped up in response to people repeatedly asking the blanket question: “How do I secure my server?” (Easy: you hire someone that knows how to secure servers). As the leading provider of its type, cPanel is under a lot of pressure to keep up with the demands of their clientèle, including the ones that expect a point and click solution to everything.  And while cPanel’s efforts here are meritorious, Security Advisor appears to do nothing more than make a series of “educated” guesses about what your server is, or should be, doing.  This leaves me wondering how many people are making unnecessary and thoughtless changes to their servers because some script told them to.

Here are a few examples of what it found on one of my test boxes:

Apache vhosts are not segmented or chroot()ed.

Enable “Jail Apache” in the “Tweak Settings” area, and change users to jailshell in the “Manage Shell Access” area. Consider a more robust solution by using “CageFS on CloudLinux”

 

No brute force protection detected

Enable cPHulk Brute Force Protection in the “cPHulk Brute Force Protection” area.

 

ClamAV is not installed.

Install ClamAV within “Manage Plugins”.

 

A newer kernel is installed, however the system has not been rebooted. running: 2.6.32-279.22.1.el6, installed: 2.6.32-431.5.1.el6

Reboot the system in the “Graceful Server Reboot” area.

So, for one: my contempt for CloudLinux is only matched by equal hatred for mod_ruid2 (required for “Jail Apache”).  SA missed the CloakFS setup on this server, which achieves the necessary jailing.

CpHulkd and ClamAV are also not the only software of their kind, so if you use CSF, BFD, and/or your own AV, be prepared to hear Security Advisor roar.

Ksplice has been a thing for a while now.  My reboot-less kernel upgrade is no match for you, Security Advisor.

Now, there were some legitimate things SA found, but nothing that I necessarily care about.  Here’s why:

My intention here, quite to what seems to be the contrary, is not to blast Security Advisor for its efforts in guiding sysadmins through the daunting and never-ending path of system security.  My point is, you need to understand your system and what security ‘violations’ it reports are actually problematic and what is the best way to address these problems in your environment.  The solutions SA is suggesting may actually be invalidated by  other measures in place on your system, or better addressed using a different method.  For example, I don’t condone switching to ruid2 on a shared server just to provide the jailing capabilities that CloakFS and CageFS can just as securely provide.  Or pointlessly rebooting your server because SA doesn’t like the output of uname.  Before you make changes to your server, understand what you’re doing, why you’re doing it, and whether it really needs to be done.

BTW, cPanel, I still love you guys.  I just don’t fancy Security Advisor.

Basics of YAML Parsing in PHP

Posted by Nessa | Posted in uncategorized | Posted on 22-06-2012

0

I know I’ve been on hiatus for a while and have neglected to update my website in over a year. That’s what happens when you get married and pop out a kid three months early. But now that I have more time on my hands I promise to devote a little more time to the website, starting with some of the basic PHP tutorials that my readers have grown to know and love.

First off, YAML is not a markup language, nor does it claim to be (YAML Aint a Markup Language), but it does represent a decent way to statically store arrays of data that are easily parsed by almost any programming language.  I recently had to write a script to parse out domain data from a cPanel “userdata” file, which is a YAML-formatted template that cPanel uses to build an httpd.conf file:

---
addon_domains: {}

cp_php_magic_include_path.conf: 0
main_domain: v-nessa.net
parked_domains:
  - v-nessa.com
sub_domains:
  - mail.v-nessa.net
  - cpanel.v-nessa.net
  - anothersubdomain.v-nessa.net

Essentially with a YAML file you’ll treat the data like a multi-dimensional array – key/value pairs are separated by a colon, and sequences are prefaced by dashes.  PHP makes it easy to parse these files with the YAML PECL module.

First things first, does your PHP installation have YAML support?

root@server [~]# php -m |grep yaml

To install YAML for PHP:

Install libYAML

Then:


wget http://pecl.php.net/get/yaml-1.1.0.tgz
tar -xvzf yaml-1.1.0.tgz
cd yaml-1.1.0
phpize
./configure && make && make install

Then make sure that yaml.so is located in your php.ini

extension=yaml.so

In its simplest form, our YAML file can be parsed as so:

$file="/var/cpanel/userdata/myuser/main";
$parsed = yaml_parse_file($file);
 
print_r($parsed);

This will return the YAML file as a multi-dimensional array:

Array
(
    [addon_domains] => Array
        (
        )

    [cp_php_magic_include_path.conf] => 0
    [main_domain] => v-nessa.net
    [parked_domains] => Array
        (
            [0] => v-nessa.com
        )

    [sub_domains] => Array
        (
            [0] => mail.v-nessa.net
            [1] => cpanel.v-nessa.net
            [2] => anothersubdomain.v-nessa.net
        )

)

Then from here, we can simply parse the array as usual.  For example, this will print out all of the items under the parked_domains key:

foreach($parsed['parked_domains'] as $key=>$value){
    echo "$value\n";
}

Fun With cPanel Mailing List

Posted by Nessa | Posted in uncategorized | Posted on 10-02-2010

2

Last month cPanel hosted a webinar for cPanel 11.25 where there were reportedly over 2000 attendees from all over the world. One thing I guess they didn’t realize is that the list email address for all the attendees, webinar[at]cpanel.net, has a reply-to that posted a reply all to anyone on the list, unmoderated. Oops.  It all started this morning when I checked my email, to find an email from the webinar mailing list to the webinar mailing list, apparently directed as a reply to someone else:

Mario,thank you, appreciate it :)
You aren’t by chance attending webhosting day in Germany, are you ?
I pre-registered, but am not 100% sure to attend yet.

This email was obviously referring to Mario Rodriguez from cPanel/r1Soft . The best things about this is that it seemed like there was an actual conversation going on, as there was a good flow of sequential events. Here was the initial response to the mysterious emails:

Why am I receving this email ??

Well, duh, you’re on a mailing list. Obviously one that is not configured properly to moderate posting. Now we’re starting to realize this:

Looks like this is a mailing list which is circulating replies!

Exact! In fact, it is a mailing list bad configured…that is sending replies to all members !!

This someone set up a bad forwarder =)

It seems cPanel listing is sending reply to all members.

Looks like a group mailing list to me =) Perhaps an oversight on cPanel’s part?

Let’s also keep in mind that most of these people are technical staff from various hosting providers. Naturally, now that we know there’s a problem we’re going to take full advantage:

Hello from Russia! :)

Hello from Brazil :¬)

A bit of spam before it gets fixed then….http://amplicate.com/rocks/cpanel

Personal Spam also? You can follow me on Twitter at www.twitter.com/******** Cpanel and systems administrator for over 10 years ;)

Greetings from Greece too :))))))) Should I spam this list with an incredible offer for .eu domain registrarion for 5EUR/yr exclusively for list members? :)))))))

I took it that they wanted me to come to Germany…boss said no, though =(

Awww, where’s the fun in that?

Anyone in London Fancy meeting up for Lunch this week?

I’m not in london but I wouldn’t mind lunch. a/s/l? just kidding =)

I can’t make it to London but if anybody is in Aruba lunch is on me! (playing the odds here ;)

By now, cPanel acknowledged that there was a problem:

I am working on this right now, my apologies for the inconvenience.

Yes, sorry for the confusion and mass emails. We will have it fixed shortly.

And then you have the people who start to get a little pissed:

Please DO NOT send any more replies.

Seriously, stop sending emails to the list. It’s obvious no one knew about it and it’s obviously not correctly setup since no one opted in and there isn’t an opt out link.

It does look like it is configured to relay email to everybody if you send an email to the list. Just hold off sending emails and in a little bit somebody from cPanel will fix it. I am sure they didn’t mean to set it up so that everybody gets emails from the list. No reason to flood the inboxes of everybody else :)

Man my blackberry is going to go off every minute now with twitter spam and .eu domain spam. Bah Thanks cPanel ;)


And then the emails stopped so cPanel appears to have fixed the problem. Kind of fun while it lasted…

Simple API Writing, Part I

Posted by Nessa | Posted in uncategorized | Posted on 09-02-2009

8

A lot of people don’t realize how easy it is to write an API with PHP. It really is as easy as having a simple PHP script accepting GET variables, and when you add in some security, you can pretty much do anything you want with a single script that accepts variables from any authenticated source.  So a little while ago I posted about the new cPanel XML API and how to integrate that with your own scripts – well now, I’ll use that as an example to show you how to write an API for their API, a.k.a, an API connector.   Though in real applications you wouldn’t need an API, all you’d need is a PHP script that accepts GET or POST input to perform some kind of action. In this example, we’ll have a script that automatically adds DNS zones to a nameserver that runs cPanel as well.

Most APIs do the same thing – you have a script, then that script accepts post/get variables, then does something.

The Interface (addzone.php):

You guy remember the one I posted a while back – well, we’ll use the same one only a tad different.  This is the script that runs statically on the server, which accepts the variables passed through the URL:


<?php
// API for adding a DNS zone to ns cluster
$isinclude = “1″; // specifies $isinclude for xmlapi.php
// GET & POST definitions

$key = “098f6bcd4621d373cade4e832627b4f6″;
$domain = $_GET['domain'];
$ip = $_GET['ip'];

// Validation – make sure that we have the right information

if($_POST['key'] != $key){ echo “Invalid key!!”; die(); }
if(empty($domain)){ echo “Domain value missing!!”; die(); }
if(empty($ip)){ echo “IP Value missing!!”; die(); }

$theServer = “ns1.v-nessa.net”; // the server to connect to
$apiPath = “/xml-api/adddns?domain=$domain&ip=$ip”; // the xml api path

$user = “root”; // use to connect to whm as

// ns1 hash (whm > remote access)

$rhash = “e9917f16b3fda69137192725a06b68e7
230e99fd445473807e33d637878641a5
–edited out for sake of length–
f673567ab443acedc77f9aec62ff953f”;

// Include the API connector
include(“xmlapi.php”);

// Output XML Result
$xmlObject=simplexml_load_string($xmlresult);

echo $xmlObject->result->statusmsg . “\n”;

?>

The file that is called via include() is the basic xml function file which constructs all of the variables from the outser script (shown above).  You can get a copy of of xmlapi.php from here, but for this example you need to comment out the output.

Now all we need to do is pass the variables that the script needs in order to know what information to process, which is $ip and $domain.  Therefore, in order to successfully call this API, you would enter the following in a browser:

http://v-nessa.net/api/addzone.php?domain=test.v-nessa.net&ip=205.134.252.71

This will pass the ‘domain’ and ‘ip’ variables to addzone.php, which uses the XML API to connect to WHM and add a dns zone on the nameserver ns1.v-nessa.net.  This is a problem though – what’s to keep outsiders from finding this and abusing it?  Well, there are several forms of non-interactive authentication you can use, such as:

  • Have an allow list of ips that can access the script (look up environmental variables at php.net)
  • Requiring a key or token

I generally use a key, though there are better ways to do this.  The way I’m about to show you is simple and secure, but slightly limits the way your API can be called.

First, I generated an md5 hash and defined it in the scipt (remember $key = “098f6bcd4621d373cade4e832627b4f6″; ?).  Then all I need to do is make sure that key is used whenever I call the API. Notice that in addzone.php it’s defined as a POST variable?  That is mainly for preference but you can just as easily make it a GET variable and just add it to your URL line.  Here I want it to be posted, so I can call the API through cURL as follows:

curl -k http://v-nessa.net/api/addzone.php?domain=test.v-nessa.net&ip=205.134.252.71 -d key = “098f6bcd4621d373cade4e832627b4f6

And there you have it! A very simple way to write an API using POST and GET.


Where Does cPanel Put It?

Posted by Nessa | Posted in uncategorized | Posted on 17-12-2008

5

I can think of a few things that are wrong with that title but in all seriousness…don’t you ever wonder where cPanel stores the config changes that you make in WHM?  Automation is the key nowadays, and lately that’s required me to get a little down and dirty with cPanel to find its deepest secrets. *This information is not official documentation, nor is it backed up by cPanel or set in stone.  In other words, don’t blame me if you mess up your server.

These are files that store the information read and used by WHM (as of 11.23.6)

  • IP addresses: /etc/ips
  • Reserved IPs: /etc/reservedips
  • Reserved IP reasons: /etc/reservedipreasons
  • IP address pool: /etc/ipaddrpool
  • Access hash (WHM remote access key): /home/user/.accesshash or /root/.accesshash
  • cPanel update preferences: /etc/cpupdate.conf
  • Basic cPanel/WHM setup:  /etc/wwwacct.conf
  • System mail preferences: /etc/localaliases
  • Exim open relay list: /etc/alwaysrelay
  • Server-wide max emails per hour: /var/cpanel/maxemailsperhour
  • Tweak settings: /var/cpanel/cpanel.config
  • Packages: /var/cpanel/packages/
  • Features: /var/cpanel/features/
  • User data: /var/cpanel/users/ and /var/cpanel/userdata
  • Apache templates: /var/cpanel/templates/apache(1,2)
  • Exim config template: /etc/exim.conf.localopts
  • Exim mail IPs: /etc/mailips
  • rDNS for mail ips: /etc/mail_reverse_dns
  • Clustering: /var/cpanel/cluster/root/config
  • Service manager: /etc/chkserv.d
  • Users and their domains: /etc/userdomains
  • Users and their main domains: /etc/trueuserdomains
  • Users and their owners: /etc/trueuserowners
  • Main cPanel IP: /var/cpanel/mainip
  • cPanel version: /usr/local/cpanel/version
  • Resellers: /var/cpanel/resellers
  • Reseller nameservers: /var/cpanel/resellers-nameservers

These are a few scripst that you can use to achieve the same  results of their WHM equivalents:

  • Initialize quotes: /scripts/initquotas
  • Compile Apache: /scripts/easyapache  (you can pass additional options – see EasyApache 2 docs)
  • Update cPanel: /scripts/upcp
  • Enable/disable tweak settings: /scripts/smtpmailgidonly on|off
  • Change PHP API and suExec settings: /usr/local/cpanel/bin/rebuild_phpconf
  • Suspend an account: /scripts/suspendacct <user> <reason>
  • Terminate an account: /scripts/killacct <user>

Obviously there are a ton more, and just about anything done in WHM can be done directly on the server.  The main things to remember:

Scripts are mainly stored in /scripts and /usr/local/cpanel/bin

Data files are in /var/cpanel

Config files are in /etc/ and /usr/local/cpanel

daybreakers

Setting up cPanel Proxies

Posted by Nessa | Posted in uncategorized | Posted on 26-07-2008

2

It’s been about a while since cPanel 11.1 came out and the proxy script from cpanelproxy.net that we all know and love stopped working. Well, the cPanel devs came through for us again and incorporated an Apache-based proxy feature to natively allow users behind firewalls to connect to cPanel over port 80, similar to the way the previous php-based cpanel proxy worked. This was a peace of cake on new server setups, where all you had to do was check on the proxy options in WHM “Tweak Settings” and include mod_proxy in your Apache build. However, I had a very difficult time getting this to work on previous servers that did not already have those features. After bringing this up to Mr. Ken from cPanel (who, by the way, is the most awesomest person in the cpanel bunch), I was finally able to come up with a procedure for getting this to work without having to completely recompile Apache which is a no-no on more mature production servers.

First, if you haven’t already, run a cpanel update to the latest version which at the time of my writing is 11.23. Once the update is complete, log into WHM > Tweak Settings and check off these options (only the first is required):


Add proxy VirtualHost to httpd.conf to automatically redirect unconfigured cpanel, webmail, webdisk and whm subdomains to the correct port

Automatically create cpanel, webmail, webdisk and whm proxy subdomain DNS entries for new accounts.

Allow users to create cpanel, webmail, webdisk and whm subdomains that override automatically generated proxy subdomains

Now, to install mod_proxy (for Apache 1.3 and 2.x)

Download the source for your Apache version. If you’re not sure what that is, you can find out from your phpinfo file or in some cases by typing ‘httpd -v’ from command line.

wget http://apache.mirrors.tds.net/httpd/apache_1.3.41.tar.gz
tar -xvzf apache_1.3.41.tar.gz
cd apache_1.3.41/src/modules/proxy (will just be /modules/proxy for Apache 2 sources)

You need to compile the mod_proxy module with apxs to add it to httpd.conf. For Apache 1.3.x:

/usr/local/apache/bin/apxs -i -a -c mod_proxy.c

For Apache 2.2 (not sure about 2.0 since we don’t run that version on any of our systems) I found that you have to compile mod_proxy with two of its submodules in order for the proxy feature in cpanel to work:

/usr/local/apache/bin/apxs -i -a -c mod_proxy.c proxy_util.c
/usr/local/apache/bin/apxs -i -a -c mod_proxy_http.c

The restart Apache and verify that it is able to start. In my case, when I just compiled the mod_proxy module I got some error about ap_proxy_lb_workers, but when I added proxy_util that fixed the problem. Then I wasn’t able to get the cpanel proxy feature to work without mod_proxy_http. There is one last step with Apache, where you need to add the proxy virtualhost entries in. cPanel has this set up as one virtualhost entry for all the subdomains as well as https, which didn’t quite work in my case because we have shared SSL certificates on the main IP. So I added the following lines between the <VirtualHost> tags for the main hostname and shared ssl hostname:

ServerAlias cpanel.* webmail.*
RewriteEngine On
RewriteCond %{HTTP_HOST} ^cpanel\.
RewriteRule ^/(.*) http://127.0.0.1:2082/$1 [P]
RewriteCond %{HTTP_HOST} ^webmail\.
RewriteRule ^/(.*) http://127.0.0.1:2095/$1 [P]
UseCanonicalName Off

These are just the ones for webmail and cpanel, but webdisk and whm ones can be added as well.

All you need to do now is setup the subdomains so that customers can access them. The best way to do this is to specify the username:

/scripts/proxydomains --user=username add

To do all accounts on the server (which can take a while):

/scripts/proxydomains add

To list all the options for this script simply type /scripts/proxydomains .

How to Add Services to Chkservd

Posted by Nessa | Posted in uncategorized | Posted on 28-06-2008

5

.!.
.!.

Chkservd is the service in cPanel that checks to make sure that services are running, then restarts them if necessary. It’s also responsible for the ‘Service Manager’ section in cPanel, which is an interface where added services can be easily checked on and off.
To add a new service, create a line in /etc/chkserv.d/chkservd.conf in the same format as the others:

service:1

1 means the service should be enabled, 0 means it’s off.
In /etc/chkserv.d each service has its own file. Create a file called as the name of the service you are monitoring. The contents of the file are in the format of:

#SERVICE = PORT, SEND, RESPONSE, RE-START COMMAND

There are two ways that cPanel checks services with chkservd:

  • Connection-based monitoring – By default, cPanel will try to connect to the service’s specified port, issue a command, and if a response is received within 10 seconds it will consider the service to be online. For instance, FTP:
service[ftpd]=21,QUIT,220,/scripts/restartsrv_ftpserver
  • Process-based monitoring – cPanel will check for a specific process to determine whether it is online. For instance, named:
service[named]=x,x,x,/scripts/restartsrvr_bind,named,named|bind

If you have more than one restart command, you can separate them with semicolons in order of preference that they should be run. Output of these commands will be logged to the chkservd.log
After you’ve created the service’s configuration file, restart chkservd:

/etc/init.d/chkservd restart

You should then see the service listed in WebHost Manager in the ‘service manager section’
Chkservd logs are in /var/log/chkservd.log. Checks are done every 8 minutes, and everyone online service gets a +, offline services get a -. If the service is determined to be offline, the restart command(s) specified in that service’s chkservd configuration file is issued and the output is logged.

If you don’t even have chkservd installed, it’s probably missing and you need to install it.

Sexifying WHM with XML API

Posted by Nessa | Posted in uncategorized | Posted on 07-06-2008

6

.!.

I don’t know about you other cPanel system admins out there, but I find WHM to be very useful for the more advanced and time-consuming tasks, such as installing SSL certificates. However, the easy stuff like changing an account’s package and resetting passwords is a royal pain in the ass as far as convenience is concerned when you have to log into WHM, list accounts, and make whatever change.

I recently became favorable towards the WHM XML API functionality which will let me do a majority of the everyday account-related tasks from command line without ever opening my browser, which is a lot easier when managing thousands of users across multiple servers. Below are a couple scripts I’ve put together using the XML API from a base script in the cPanel forums:

Change account password

Change account package

Both are run via command line, and the arguments passed to the PHP script as variables. For example, to change an account’s password:

./chacctpass myuser mypass1234

Customizing these scripts to perform different functions is easy via the following steps:

- change if ($argc != 3) to the number of command line arguments you wish to pass to the script plus one. In the above example there are two arguments and since the script name counts, add one and that makes 3.

- in the section where the arguments are assigned to variables (like $cpuser, etc), name your variables. The first one should have an array value of 0, then 1, 2, etc.

- edit the usage example, which will come up if the required number of arguments is not provided…you can add any text you like

- if you’re using a hash (which is more secure than user/pass authentication), go fetch your remote access key from WHM and put it in the $hash value within quotes, format intact. Otherwise, put in your WHM user’s username and password

- change the $server variable to your server’s hostname

- change $apipath to the WHM path for the function you are using. You can find a whole list of them here, and most will give you the path to use in the examples sections. In the API path, insert your variable names where the values are suppose to be. For instance:

$apiPath = “/xml-api/passwd?user=myuser&pass=mypass1234″;

Would be:

$apiPath = “/xml-api/passwd?user=$cpuser&pass=$newpass”;

In the header section, uncomment whichever $header .= “Authorization: line that matches your authentication method (user/pass or hash)

Once you’ve configured your API script, chmod to 700 and run from the command line as show in my example. It’s better to lock down the script by changing its ownership only to the user that will be using it, and not giving read, write, or execute permissions to anyone else.

Note: for these scripts to work you have to have PHP compiled with OpenSSL support, otherwise change the socket variables to http over port 2086.

WHM APF Plugin

Posted by Nessa | Posted in uncategorized | Posted on 05-06-2008

19

I’m happy to announce my first ever perl-written plugin for WebHost Manager, which was developed by myself and one of my fellow sysadmins at InMotion Hosting. The first release is available here:

Download v.1.05

Download Now

To explain a little bit of background here, many hosting companies that give some sort of **** about security will leave SSH port 22 closed except for specified IPs. Us being one of them, requests from customers for us to add their IPs to their firewalls is rather redundant when we host over 900 V-dedicated systems and 100 Dedicated boxes where customers can opt for SSH access. Therefore, I decided that it would be well worth our efforts to create a WHM plugin to allow customers to add their own IPs without ever having to contact us. I am aware that some plugin developer already has a more sophisticated APF plugin for WHM but you have to pay for it.

Requirements:

- cPanel/WHM (tested on version 11.18)

- APF 0.9 (tested on 0.9.6)

- iptables enabled and working (if you are able to restart APF without any errors, it’s probably fine)

Note: default privileges will allow anyone with WHM/reseller access to use this plugin. You can manually change this in the addon_add2apf.cgi file if you want.

Installation:

cd /usr/local/cpanel/whostmgr/docroot/cgi
wget http://v-nessa.net/wp-content/scripts/apfadd_whm_1.05.tar.gz
tar -xvzf apfadd_whm_1.05.tar.gz
rm -f apfadd_whm_1.05.tar.gz

Simple enough?

From there, load up WHM and on the left side you’ll see an option to “Add IP to Firewall” and the plugin page will give you examples of what you can add. The script is set up to allow:

Hostname – v-nessa.net
Single IP – 205.134.252.71
IP CIDR – 205.134.252.71/24
Port/IP – d=22:s=205.134.252.71
Port/CIDR – d=22:s=205.134.252.71/24

Of course, the error checking is not perfect, so just be aware of what you’re adding or you might unintentionally ‘break’ your firewall, which usually results in blocked traffic.

Eventually I’m sure I’ll end up adding the ability to manage ports and remove IPs for users with a certain access level, but currently I don’t see a need to do so because I don’t believe that non-root users should have that type of access. Note that per the readme, you can edit the addon file to limit access to users with a certain reseller ACL privilege.

Moving Towards PCI Compliance with cPanel

Posted by Nessa | Posted in uncategorized | Posted on 14-04-2008

14

See also: http://www.thecpaneladmin.com/pci-compliance-package-cpanel-servers/

Those of you who are server admins or use certain merchant services know what I’m taking about — it’s that dreaded security scan that picks apart your server to tell you everything that it thinks is wrong, assuming you have the knowledge or access to fix it: yes, the PCI scan. PCI compliancy is a somewhat new procedure used by security companies and financial institutions to measure the security of a webserver that collects and stores sensitive information. The reasons for getting a scan vary, but are most commonly for legal reasons or just the assurance that your server is subject to certain vulnerabilities.

After dealing with 2-3 PCI scans a week for the last year, I’ve put together a common procedure for how to make your server compliant to current PCI standards. Note that each scan company is different and may report other issues, and if you’re using ControlScan then, well, I feel sorry for you. I’m also assuming that you are on a Linux server running cPanel and LAMP.

Step 1: Make sure you have a firewall

PCI scans are nazis about unjustified open ports, so only open the ones that you need in order for services to run effectively. Manually configuring iptables is a pain in the ass, so I recommend using APF or CSF (if you have cPanel) and then configuring the allow rules to only allow ports for active services.

Note that both indicate the opening of cPanel ports 2082, 2095, and 2086, but some scans will complain about these being nonsecure. If that is the case you can configure within WHM to only use the secure ports, then remove the nonsecure ones from the firewall so they can’t be accessed. You should also close MySQL port 3306 for external hosts and allow them on a per-IP basis to anyone other than localhost has to be allowed.

Step 2: Update your system

This is an obvious one, but you’d be surprised how many people still have old packages installed on the server. With cPanel, running /scripts/upcp will usually update the vital system software as long as you have your update configuration in WHM set to allow it, but otherwise I would recommend doing a yum update, up2date, or whatever else you use to manage packages to make sure everything is up to date.

Nowadays old versions of MySQL, PHP, and Apache are no longer squeezing through either, so you need to upgrade to at least MySQL 4.1.22, PHP 5.2.5, and Apache 1.3.39 (some scans will want Apache 2.0.x).

Step 3: FIx OpenSSL

If you did a package update this was probably already taken care of, but if you installed via source you need to make sure you’re using at least 0.9.7j, which is the oldest version that most PCI scans allow. You can get your sources from here, and it may require a recompile of Apache and other services that use it. To check your OpenSSL version, type ‘openssl‘ from your SSH prompt and then type ‘version‘.

Note to Redhat/Fedora/CentOS users: If you’re running a somewhat recent version of your OS your openSSL version probably is something like 0.9.7a, but due to Redhat backporting this may be a false-positive. If you’re on any Redhat-based distribution, just tell your scan company and they’ll bypass OpenSSL checks.

Step 4: Check your SSL certificates

In order to pass a PCI scan your server must have at least one SSL certificate signed by a recognized certificate authority, and any services using SSL need to be using a certificate as well. Go cough up $30-$100 and buy a decent 264-bit SSL certificate and install it not just for Apache, but also for all of your active services. WebHost Manager has a section for installing service SSL certificates to make this process easier.

Step 5: Disable SSLv2 and other weak encryption methods

This one always gets me, because there is no way to disable SSLv2 for everything at once, at least not one that I know of. What makes this part the worse is that not all services support the choosing of SSL protocols and ciphers, but luckily unless you are using ControlScan the ones that don’t are probably not going to show up. Here’s how you do it for common services that are reported:

Apache:

Add these lines to your httpd.conf (you may to add them to each secure vhost as well):

SSLProtocol -ALL +SSLv3 +TLSv1
SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM

POP3 and IMAP:

Edit the following files:

/usr/lib/courier-imap/etc/pop3d-ssl
/usr/lib/courier-imap/etc/imapd-ssl

Comment out the existing TLS_CIPHER_LIST line and replace it with the following and restart courier-imap:

TLS_CIPHER_LIST="ALL:!SSLv2:!ADH:!NULL:!EXPORT:!DES:!LOW:@STRENGTH"

Exim:

Add the following to exim.conf:

tls_require_ciphers = ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM:!SSLv2

For other services that might be on your system, take a look at this guide.

Step 6: Disable mod_userdir (or whatever cPanel is calling it nowadays)

If you are able to go to http://yourserverip/~yourusername, then you have mod_userdir enabled and the scan will probably complain. You can disable this in WHM under Security Center > Apache mod_userdir Tweak, or in httpd.conf add “userdir disabled user1 user2 user3 …etc”

Step 7: Put Apache in incognito mode and disable the bad stuff

If you try to get an Apache error (like a 404 error), the footer of that page probably contains more information that you may want to share about your Apache setup. You can disable this in your httpd.conf by adding these lines:

ServerSignature Off
ServerTokens Prod
FileETag None

You can read more about these here.

Another thing that some scans report is the use of 413 errors. You should add this line to httpd.conf as a workaround:

ErrorDocument 413 /index.php (or any other file)

Just about all scans will complain if the ‘trace’ and ‘track’ apache methods are enabled on your server. You can fix this by adding these lines to your Virtualhost entries or .htaccess files:

RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)$ [NC]
RewriteRule ^.*$ - [F]

You should also disable directory indexes, which can be done most easily in your cPanel’s index manager. Directory indexes allow the listing of files inside folders that do not have an index page. You can also disable these in your .htaccess files:

Options All -Indexes

Ending notes

Really, it doesn’t matter how secure your server is if your web application scan is poorly programmed, so your server should not be the ending point in security. Some PCI scan companies are able to detect common vulnerabilities in web applications, but you should take the extra steps to stay ahead of the game and update your site software on a regular basis.