Server Administration & Management

Linux OS Hardening Part-1

1. Secure /tmp and /var/tmp

If they are running cPanel (I usually look for the ‘/scripts’ directory) then run /scripts/securetmp This will remount the ‘/tmp’ and ‘/var/tmp’ as ‘noexec’.

# /scripts/securetmp

Sometimes cPanel has an issue with /tmp permissions. Run the following:

# ls -al /

if you see: drwxr-xr-x   5 root   root   xxxxx mon xx xx:xx /tmp
You’ll need to chmod the /tmp directory to 1777 in order to set the sticky bit.

# chmod 1777 /tmp

If they are not running cPanel you will manually need to mount the filesystems as nonexecutable. If the user has a separate partition for /tmp, you can simply remount it with noexec,nosuid options. You can edit /etc/fstab with this options, then type “mount –o remount /tmp”. You can then create a symbolic link from /var/tmp to /tmp (“ln –s /tmp /var/tmp”). Keep in mind you will need to backup any files in /var/tmp and move them to /tmp. Pay special attention to the MySQL socket, as it will like need to be recreated. After creating the symbolic link, remove the MySQL socket and recreate it:

# mount -o rw,noexec,nodev,nosuid,remount /tmp

# rm –rf /tmp/mysql.sock

# ln –s /var/lib/mysql/mysql.sock /tmp/mysql.sock

If they do not have a separate partition for /tmp, you will need to create a loopback filesystem. Issue the following series of commands:

# dd if=/dev/zero of=/dev/tmpMnt bs=1024 count=512000

# mke2fs /dev/tmpMnt

# mkdir /tmp.bak

# mv /tmp/* /tmp.bak/ (verify that dot-files are also moved)

# mount -o loop,noexec,nosuid,rw /dev/tmpMnt /tmp

# mv /tmp.bak/* /tmp/ (again, very that dot-files are also moved)

# rm -rf /tmp.bak

# chmod 1777 /tmp

# vi /etc/fstab (add: /dev/tmpMnt /tmp ext2 loop,nosuid,noexec,rw 0 0)

The above commands create a 512MB loopback filesystem for /tmp, then mounts it as non-executable. From here, you can create a symbolic link from /var/tmp as described above.


2. Secure /usr/local/apache/proxy

Remove the directory and create a symbolic link from it to a secured /tmp:

# rm -rf /usr/local/apache/proxy

# ln -s /tmp /usr/local/apache/proxy


3. Secure /dev/shm

/dev/shm is basically a ramfs. As it is world-writable we recommend unmount it or at least removing its permissions:

# umount /dev/shm (you cannot be in the directory when executing this command)

# vi /etc/fstab (comment out # the entry for /dev/shm)


# chmod o-w /dev/shm


4. Secure /var/spool/ directories

This will remove world write access.

# chmod -R o-w /var/spool


5. Make sure the machine is current on patches

If the machine has cPanel on it please make sure the pkgSkipList contains the following (run /usr/sbin/up2date –configure):


You can run /scripts/checkup2date and it will add these automatically.

From here it is usually best to let cPanel install some of the needed RPM’s it knows it needs. You can accomplish this by running /scripts/rpmup

Now you can go ahead and run /usr/sbin/up2date -l to see what packages are available for install/upgrade.

Right under ‘Fetching rpm headers…’ will be all the packages available to the server. To update these run

# /usr/sbin/up2date -u

Now under ‘The following Packages were marked to be skipped by your configuration:’ it will list the packages available but are being skipped by the skiplist above. We are mostly worried about the kernel. If you see a kernel listed here, run:

# /usr/sbin/up2date -uf kernel kernel-smp kernel-utils kernel-source

Once this has completed you will want to make sure we are booting the correct kernel. Run /bin/uname -r to see which kernel is booting currently. From here run /bin/vi /boot/grub/grub.conf and you should see the newly installed kernel and more than likley others kernels that were previously installed. If the customer was already running a RedHat kernel (usually something like ‘2.4.21-15.0.4-EL’) than it is usually safe to change it to boot the new RedHat kernel you just installed. It should be listed as the very first kernel, if so all you would do is change the ‘default=x’ to ‘default=0’. If the customer was running a customer kernel (something like ‘2.6.6’ or ‘2.4.26-grsecvx’) than you would want to leave the ‘default=x’ line set to the kernel they were booting before.

If the server is running cPanel make sure it has the latest stable version by typing:

# /scripts/upcp

Make sure you restart cPanel after this (if it installed a newer version) by running: service cPanel restart


6. Disable unnecessary services

Verify the runlevel that we are currently running in by running ‘runlevel’. This will more than likely be ‘3’. Run: /sbin/chkconfig –list | grep <insert runlevel number>:on

This will list all the services that are starting on boot for the runlevel.

Look for services that are not needed such as:


Note: do NOT disable ‘netfs’ as this will break /scripts/securetmp

Stop each service you find like so:

# /etc/init.d/<service name> stop

To disable the services run:

# /sbin/chkconfig –level 123456 <service name> off for each service.


7. Check for who has shell access and restrict accordingly

This will return only the users that have a valid login shell to the machine.

for i in `/usr/bin/chsh –list-shells | grep -v ‘(noshell|nologin)’`; do grep $i /etc/passwd; done

To lock the appropriate accounts down do the following:

# /usr/bin/chsh -s /usr/local/cpanel/bin/noshell <insert username>


8. Add new user for SSH login

# /usr/sbin/adduser -G wheel -d /home/<cxxxxx > -c “<cxxxxx>” -m < cXXXXX>

Change the Password for the new user to something random and hard to guess (letters and digits) (preferably 10 characters at least) You can use: password generator

Note: Make sure you tell the customer what you changed this to and update the hw object in Orbit.


9. Disable root login with SSH

Run the following

#vi /etc/ssh/sshd_config

Change ‘PermitRootLogin yes’ to ‘PermitRootLogin no’ Make sure it is uncommented (take the ‘#’ out from the front of the line if it is there). This disables the ability to ssh into server as root. Customer must use newly created login and then ‘su’ to root if needed after login.

Change ssh port to 33988 to avoid Brute Force attacks on port 22.

Remove protocol 1 (leave the 2 next to protocol) and uncomment line.

Uncomment #Banner and change /some/path to /etc/motd

Save file and exit. (:x)


10. Displaying Login Banners

To display a warning banner, vi the /etc/motd file and paste the following:

# vi /etc/motd

Only authorized users may log into this commercial computer system. Users (authorized or unauthorized) have no explicit or implicit expectation  of privacy. Any or all uses of this system and all files on this system may be intercepted, monitored, recorded, copied, audited,  inspected, and  disclosed to authorized sites, ISPs, and law enforcement personnel, as well as authorized officials of other agencies, domestic, foreign, and The Planet Information Security team. By using this system, the user consents to such interception, monitoring, recording, copying,  auditing, inspection, and disclosure at the discretion of authorized site or The Planet Information Security team. Unauthorized  or improper use of this system may result civil and criminal penalties. By continuing to use this system you indicate your awareness of  and consent to these terms and conditions of use.

LOG OFF IMMEDIATELY if you do not agree to the conditions stated in this  warning under  US CODE:  Title 18,  U.S.C.


11. Create the btmp file

As root, run

# /bin/touch /var/log/btmp

This will allow the user to type ‘lastb’ and display all ‘bad’ logins to the server.


12. /etc/securetty

The /etc/securetty file allows you to specify which TTY devices the root user is allowed to login on. Remove all ttys from /etc/securetty except tty1. Which means only root is allowed to login on tty1, forcing the user have to log in as wheel and su if they need more devices as root.

The file will look like this:



”’sometimes there will not be a ttS0.”’


13. Root email

LogWatch: An email gets sent out everyday that contains basic information about the server such as free space, bad login attempts to the machine, etc. It sends this report to root@localhost. If the customer does not ever check the mail on the server locally they will never see these emails. If they DO NOT have cPanel do the following to ensure they get emailed these reports ‘vi /root/.forward’. In this file put the customers primary email address in the only line in this file and save it out. This essentually forwards all of root’s email to this email address.

Note that if they are running Qmail you may need to edit /root/.qmail. Qmail uses a slightly different syntax: an ampersand (&) is placed before the e-mail address:

echo “&user@host.com” > /root/.qmail


14. Apache (optional)

Note: not entirely necessary since we are doing O/S Hardening and not application hardening

Run /bin/vi /etc/httpd/conf/httpd.conf (assuming this is where the running httpd.conf file is installed) and either add the following lines, or if they already exist, change them to reflect the following

ServerTokens Prod #This will tell Apache to hide all the modules it has installed and only report that they are running Apache as the webserver)

ServerSignature Off #This will tell Apache to not show what version of Apache is running on the server when someone hits a page not found,etc).


15. Enabling Password Restrictions

The following files and parameters in the table are used when a new account is created with the useradd command. These settings are recorded for each user account in the /etc/shadow file. Therefore, make sure to configure the following parameters before you create any user accounts using the useradd command:

# vi /etc/login.defs

PASS_MAX_DAYS       60       Maximum number of days a password is valid.
PASS_MIN_DAYS       7         Minimum number of days before a user can change the password since the last change.
PASS_MIN_LEN         n/a      This parameter does not work. It is superseded by the PAM module “pam_cracklib”. See Setting  Password Restrictions for more information.
PASS_WARN_AGE      7         Number of days when the password change reminder starts.

INACTIVE       14       Number of days after password expiration that account is disabled.
EXPIRE                     Account expiration date in the format YYYY-MM-DD.

Ensure that the above parameters are changed in the /etc/login.defs and /etc/default/useradd files.


16. Setting Password Restrictions

The following example shows how to enforce the following password rules:

Minimum length of password must be 8
Minimum number of lower case letters must be 1
Minimum number of upper case letters must be 1
Minimum number of digits must be 1
Minimum number of other characters must be 1
Restrict the use of previous passwords

pam_cracklib.so        minlen=8        Minimum length of password is 8
pam_cracklib.so        lcredit=-1       Minimum number of lower case letters is 1
pam_cracklib.so        ucredit=-1      Minimum number of upper case letters is 1
pam_cracklib.so        dcredit=-1      Minimum number of digits is 1
pam_cracklib.so        ocredit=-1      Minimum number of other characters is 1

/etc/pam.d/system-auth file and add/change the following pam_cracklib arguments highlighted in bold:

auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_unix.so
account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet
account required /lib/security/$ISA/pam_permit.so
password requisite /lib/security/$ISA/pam_cracklib.so retry=3 minlen=8 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 difok=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow remember=26
password required /lib/security/$ISA/pam_deny.so
session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so

NOTE: If the /etc/security/opasswd doesn’t exist, create the file.

# ls -l /etc/security/opasswd

-rw——-  1 root root 0 Dec  8 06:54 /etc/security/opasswd


17. SUID/SGID Audit

To search the entire system for SUID or SGID files, you can run the following command:

# find / -path /proc -prune -o -type f -perm +6000 -ls

To remove the setuid/gid bit for files do:

# chmod u-s (file) “OR”

# chmod g-s (file)

Only on the following files:


Also be sure to chmod 0 all the r-tools in /usr/bin. These are /usr/bin/rcp /rsh /rlogin, /telnet.

Then do ls –al (file) to confirm that suid/gid has been removed


18. World Writable Directory Audit

To search entire system for world writable directories, you can run the following:

# find / -path /proc -prune -o -perm -2 ! -type l -ls

The “! -type l” parameter skips all symbolic links since symbolic links are always world-writable. However, this is not a problem as long as the target of the link is not world-writable, which is checked by the above find command.

Be sure to chmod wget and permissions on var/spool/samba,mail, and vbox (world writable directories). Also check permissions on system binaries (telnet, etc).


19. Unowned Files Audit

# find / -path /proc -prune -o -nouser -o -nogroup


20. Kernel Tunable Parameters

add to the /etc/sysctl.conf configuration file to make the change permanent after reboots.

# Enable TCP SYN Cookie Protection

net.ipv4.tcp_syncookies = 1

#Increase the backlog q size

net.ipv4.tcp_max_syn_backlog= 10240

#Decrease the total time we keep half-open connections in #the backlog q to 9 seconds


#Disable IP Source Routing

net.ipv4.conf.all.accept_source_route = 0

#Enable IP Spoofing Protection

net.ipv4.conf.all.rp_filter = 1

#Enable Logging of Spoofed Packets, Source Routed #Packets, Redirect Packets

net.ipv4.conf.all.log_martians = 1

To activate the configured kernel parameters immediately at runtime, use: (you can copy and paste)

# sysctl -p


21. Modify Permission/Ownership of sysctl.conf (Kernel Runtime Configurator)

# chown root:root /etc/sysctl.conf

# chmod 600 /etc/sysctl.conf


22. Audit permissions on key system log files in var/log

# ls -al /var/log

Remove the “other” groups read and execute permissions on log files. Most of these log files are owned by root but an audit still needs to be done to ensure integrity of log files.


23. Verify permissions on passwd, shadow, and group

# cd /etc

# ls -al group shadow passwd

Should return 644 permissions on passwd and group Should return 400 permissions on shadow (on cPanel boxes this should be 600)


24. Cron permissions

Restrict cron/at to authorized users by creating the cron.allow file. The cron.allow file only controls administrative access to the crontab command for scheduling and modifying cron jobs

# echo root > cron.allow

# echo root > at.allow

# echo nobody >> cron.deny

# echo nobody >> at.deny

# chown root:root cron.allow at.allow

# chmod 400 cron.allow at.allow

The system crontab files are accessed by only the cron daemon (which runs with superuser privileges) and the crontab command (which has setuid to root). Allowing regular users to read or modify system crontab files can lead to elevated privileges. Therefore, do the following countermeasures:

# chown root:root /etc/crontab

# chmod 400 /etc/crontab

# chown -R root:root /var/spool/cron

# chmod -R go-rwx /var/spool/cron

May 28, 2011 Posted by | Apache, cPanel, Cron, Security, Tips & Tricks, Unix/Linux | , , , , , , , , | Leave a comment