# Basic system security

Note that it's ultimately the responsibility of the server admin to ensure his system is secure. These are some basic security tips that can be done to help protect your system. This is not an end-all guide for server security, admins must be diligent, but rather some suggestions for a start to securing your server.

  1. Mount your /tmp partition with the noexec,nosuid options, and mount the /home partition with the nosuid option. This is done in your /etc/fstab and requires those paths to exist as partitions, and not just as subdirectories of /. If you're unsure, type:
mount
1

to get a listing of your partitions and their current mounting options. Use Google for more information on these mounting options.

Be very careful when editing your /etc/fstab, as any errors could prevent your system from starting up. Note that you must not have "nosuid,noexec" for / or /usr, as those partitions have suid binaries normally (su, passwd, etc).

  1. Add dangerous PHP functions to the disable_functions list. This prevents PHP scripts from running "raw" functions that could be used to execute programs on your system.

Note that some PHP scripts do legitimately require these functions to operate, so if your scripts don't run after enabling this function, edit your php.ini to remove the required functions from the list, and restart Apache. To add the disable_functions with CustomBuild, type the following then restart Apache:

cd /usr/local/directadmin/custombuild
./build update
./build secure_php
1
2
3
  1. Do regular updates of system services, libraries and scripts. It's important to keep your system updated once installed. This is the responsibility of the server administrator. There are several tools and options available to help the admin do this. For system libraries like OpenSSL and other low level system items, this is left to the admin to do how he wishes, though usually package systems like yum or apt-get can do this for you. For services and scripts that DA installs, you can use the CustomBuild script.

Use following guide to update manually or automate: </custombuild/upgrading-services>.

  1. Ensure clean_old_webapps is set to yes in options.conf file . This removes all scripts from /var/www/html, after updating you to a new version.

  2. If you're running PHP in mod_php mode, then enabling both PHP SafeMode and open_basedir is wise. Safemode is an internal form of disable_functions which also does a bit more checking. See the documentation on Safemode for more info on this. Open_basedir, which is enabled by default, tells PHP to not allow scripts to access files outside of the set list of paths.

To control SafeMode and Open_Basedir on your PHP CLI system (default), go to Admin Level -> Php Safemode Config .

  1. Start using PHP-FPM as your PHP engine. More information here.

  2. If you don't plan on doing any remote access to MySQL, then setting up mysqld to only listen on 127.0.0.1 would be a good idea. Note that you'll have to keep this in mind if your users start asking you why they can't connect to MySQL from a remote location.

To set MySQL to only bind to 127.0.0.1, add the following to the [mysqld] section of your /etc/my.cnf, then restart mysqld:

    bind-address = 127.0.0.1
1
  1. Enable mod_security.open in new window See the CustomBuild Faqopen in new window for available rulesets and options.

  2. Start using a firewall. Many people use CSF and we recommend so.

  3. Setup your named.conf to not allow recursion. This should be done by default now, but check anyway with this guide.

  4. Prevent Users from using weak passwords by enabling difficult password enforcementopen in new window.

  5. Prevent Users from creating subdomains belonging to other Users with this optionopen in new window.

  6. If you're using DirectAdmin with SSL, it's a good idea to force all SSL connections to use TLS instead of other older SSL protocols.

  7. Change the default SSH port from 22 to a more obscure value via /etc/ssh/sshd_config.

  8. Brute Force Login Attempts are more common, so it's best not to have direct SSH logins for common accounts like root or admin. Generally, it's safe to use a hidden "su" user first, then login to root or other accounts once connected. Disable any accounts (root, admin, etc) that don't need direct access by editing the /etc/ssh/sshd_config. Always test changes before logging out else you may lock yourself out of the box.

Also, DirectAdmin has a Brute Force attack detection system for services, as well as an IP blocker for DA itself.

  1. Force email logins to use a secure connection: http://www.directadmin.com/forum/showthread.php?t=43500open in new window

  2. Disable UserDir Apache ability ( http://12.34.56.78/~username access):

cd /usr/local/directadmin/custombuild
./build set userdir_access no
./build rewrite_confs
1
2
3
  1. Consider using CloudLinux with CageFS: https://www.cloudlinux.com/cagefsopen in new window

  2. Consider enabling a jail-system based on Linux namespaces by compiling it from CustomBuild:

cd /usr/local/directadmin/custombuild
./build update
./build bubblewrap
1
2
3

Note: bubblewrap will not work on LXC/OpenVZ and CloudLinux systems.

# Some steps may already be enabled by default, or less applicable these days as they might use older technology. Feel free to read through each one to check.

# How to check your SSL ciphers to make sure they don't accept SSLv3 to TLSv1.1

If you're trying to become PCI compliant, one common check they do is to see if any of your SSL connections are using SSLv3.

You can fill in these options to generate the desired command:
Host:
Port:

If you want to check your own setup first to ensure it will pass this check, you can use the command:

openssl s_client -port "2222" -host "127.0.0.1" "-ssl3"
1

where you'll replace the items with the respective values you're trying to test.

In the above example, we're checking DA on port 2222 locally (127.0.0.1), but a remote check to anywhere else, with any port can be used.

# The above code will produce some output.

If SSLv3 is not allowed in that connection (which is good), then you'll see about 3 to 7 lines of output, and the last line will show something like:

140506571089736:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1257:SSL alert number 40
140506571089736:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:
1
2

Basically, it will throw some kind of error.

If** the connection worked** (which is bad if testing for -ssl3), then you'll see a full page of output, including all certificate information, as well as the certificate itself.

Some services, like Exim, use TLS for their SSL connection. In that case, you'd use -tls1, -tls1_1, or -tls1_2 to test to for various TLS versions, instead of -ssl3 .

To set ciphers for the services, see this guide.

# How to create MD5 crypt from the command line

If you need to generate an MD5 hash from the command line, the openssl binary can do this very easily.

openssl passwd -1 password
1

where password would be replaced with the password you'd like to encrypt.

# How to prevent a list of users from executing a file

There are many scenarios where you'd not want a User or Users to execute a specific file. For example, wget or perl might be binaries that you don't want Users to run.

In this example, we'll discuss how to use group permissions to prevent a group of Users from executing the file:

  1. Create a group that will be filled with Users. Let's call this group :

Create the group like so:

groupadd "noperl"
1
  1. Next, we'll assign this group to the perl binary, and set its permissions such that no User in the noperl group can execute it:
chgrp "noperl" "/usr/bin/perl"
chmod 705 "/usr/bin/perl"
1
2

where using the 705 permissions, the 0 portion specifies that the group on this file cannot do anything on it (can't read it, can't write to it, and cannot execute it).

  1. Add any users to this group who should not be allowed to execute Perl:
usermod -a -G "noperl" apache
usermod -a -G "noperl" fred
usermod -a -G "noperl" george
1
2
3

where apache, fred, and george cannot run /usr/bin/perl.

This guide can be applied to other binaries as needed, but make sure that you don't block any Users which actually need to use the given binary.

  1. If you want to automate the addition of newly created Users to this group, create the file /usr/local/directadmin/scripts/custom/user_create_post.sh and add the code:
#!/bin/sh
/usr/sbin/usermod -a -G noperl $username 2>&1
RET=$?
exit $RET
1
2
3
4

And make it executable:

chmod 755 /usr/local/directadmin/scripts/custom/user_create_post.sh
1

# How to allow a non-privileged user to execute a root level command

Part of the design of DirectAdmin is to automate root level tasks, while not allowing Users to affect things that they should not.

There might be some cases where you want to allow Users to run something as root, but without giving them root access.

In this example, we'll say we want to let User restart proftpd on command.

The action done can really be anything, but this outlines the basics of how it works. Obviously, you'd need to pick a command that you don't mind them running, possibly more often than you're expecting.

We'll accomplish this by having a root cronjob scanning for files that the User can create, e.g.,

/home/username/

  1. Create a script /root/check_proftpd_restart.sh and add the code:
#!/bin/sh
COUNT=`ls "/home/*/restart_proftpd" 2>/dev/null | grep -c "restart_proftpd"`
if [ "$COUNT" -gt 0 ]; then
   echo "Restarting proftpd, triggered by ";
   ls "/home/*/restart_proftpd"
   echo "action=proftpd&value=restart" >> /usr/local/directadmin/data/task.queue
   rm -f "/home/*/restart_proftpd"
fi
exit 0;
1
2
3
4
5
6
7
8
9

and make it executable:

chmod 755 /root/check_proftpd_restart.sh
1
  1. Then create a cron to run as root every minute which calls it:
echo '* * * * * root /root/check_proftpd_restart.sh' > /etc/cron.d/check_proftpd
chmod 600 /etc/cron.d/check_proftpd
service crond restart
1
2
3
  1. Now anytime a User wants to restart proftpd, they can simply create the file /home/username/restart_proftpd, and within 1 minute, the cronjob will find their file, and tell the task.queue to restart proftpd.

It might take up to 2 full minutes for proftpd to get restarted, as the dataskq would need to find the task.queue in the same manner. If this is too long, the echo task.queue command could be replaced with a more direct service proftpd restart command, just be careful of possible piping issues.