Security is everyone's responsibility. A weak entry point in any system could allow intruders to gain access to critical information and cause havoc on an entire network. One of the core principles of information security is the CIA triad, which stands for the Confidentiality, Integrity, and Availability of information systems.
The CIA triad is a bedrock concept of computer security as customers and users expect their data to be protected. For example, a customer expects that their credit card information is securely stored (confidentiality), that their orders are not changed behind the scenes (integrity), and that they have access to their order information at all times (availablility).
To provide CIA, security professionals apply a defense in depth strategy. The idea of defense in depth is to add several layers of security to prevent one single layer failing and the entire security system collapsing. For example, a system administrator cannot simply turn on a firewall and consider the network or system secure. One must also audit accounts, check the integrity of binaries, and ensure malicious tools are not installed. To implement an effective security strategy, one must understand threats and how to defend against them.
What is a threat as it pertains to computer security? Threats are not limited to remote attackers who attempt to access a system without permission from a remote location. Threats also include employees, malicious software, unauthorized network devices, natural disasters, security vulnerabilities, and even competing corporations.
Systems and networks can be accessed without permission, sometimes by accident, or by remote attackers, and in some cases, via corporate espionage or former employees. As a user, it is important to prepare for and admit when a mistake has led to a security breach and report possible issues to the security team. As an administrator, it is important to know of the threats and be prepared to mitigate them.
When applying security to systems, it is recommended to start by securing the basic accounts and system configuration, and then to secure the network layer so that it adheres to the system policy and the organization's security procedures. Many organizations already have a security policy that covers the configuration of technology devices. The policy should include the security configuration of workstations, desktops, mobile devices, phones, production servers, and development servers. In many cases, standard operating procedures (SOPs) already exist. When in doubt, ask the security team.
The rest of this introduction describes how some of these basic security configurations are performed on a FreeBSD system. The rest of this chapter describes some specific tools which can be used when implementing a security policy on a FreeBSD system.
In securing a system, a good starting point is an audit of
	accounts.  Ensure that root has a strong password and
	that this password is not shared.  Disable any accounts that
	do not need login access.
To deny login access to accounts, two methods exist.  The
	first is to lock the account.  This example locks the
	toor account:
#pw locktoor
The second method is to prevent login access by changing
	the shell to /usr/sbin/nologin.  Only the
	superuser can change the shell for other users:
#chsh -s /usr/sbin/nologintoor
The /usr/sbin/nologin shell prevents
	the system from assigning a shell to the user when they
	attempt to login.
In some cases, system administration needs to be shared
	with other users.  FreeBSD has two methods to handle this.  The
	first one, which is not recommended, is a shared root password
	used by members of the wheel group.  With this
	method, a user types su and enters the
	password for wheel
	whenever superuser access is needed.  The user should then
	type exit to leave privileged access after
	finishing the commands that required administrative access.
	To add a user to this group, edit
	/etc/group and add the user to the end of
	the wheel entry.  The user must be
	separated by a comma character with no space.
The second, and recommended, method to permit privilege escalation is to install the security/sudo package or port. This software provides additional auditing, more fine-grained user control, and can be configured to lock users into running only the specified privileged commands.
After installation, use visudo to edit
	/usr/local/etc/sudoers.  This example
	creates a new webadmin group, adds the
	trhodes account to
	that group, and configures that group access to restart
	apache24:
#pw groupadd webadmin -M trhodes -g 6000#visudo%webadmin ALL=(ALL) /usr/sbin/service apache24 *
Passwords are a necessary evil of technology.  When they
	must be used, they should be complex and a powerful hash
	mechanism should be used to encrypt the version that is stored
	in the password database.  FreeBSD supports the
	DES, MD5,
	SHA256, SHA512, and
	Blowfish hash algorithms in its crypt()
	library.  The default of SHA512 should not
	be changed to a less secure hashing algorithm, but can be
	changed to the more secure Blowfish algorithm.
Blowfish is not part of AES and is not considered compliant with any Federal Information Processing Standards (FIPS). Its use may not be permitted in some environments.
To determine which hash algorithm is used to encrypt a
	user's password, the superuser can view the hash for the user
	in the FreeBSD password database.  Each hash starts with a symbol
	which indicates the type of hash mechanism used to encrypt the
	password.  If DES is used, there is no
	beginning symbol.  For MD5, the symbol is
	$.  For SHA256 and
	SHA512, the symbol is
	$6$.  For Blowfish, the symbol is
	$2a$.  In this example, the password for
	dru is hashed using
	the default SHA512 algorithm as the hash
	starts with $6$.  Note that the encrypted
	hash, not the password itself, is stored in the password
	database:
#grep dru /etc/master.passwddru:$6$pzIjSvCAn.PBYQBA$PXpSeWPx3g5kscj3IMiM7tUEUSPmGexxta.8Lt9TGSi2lNQqYGKszsBPuGME0:1001:1001::0:0:dru:/usr/home/dru:/bin/csh
The hash mechanism is set in the user's login class.  For
	this example, the user is in the default
	login class and the hash algorithm is set with this line in
	/etc/login.conf:
:passwd_format=sha512:\
To change the algorithm to Blowfish, modify that line to look like this:
:passwd_format=blf:\
Then run cap_mkdb /etc/login.conf as
	described in Section 13.13.1, “Configuring Login Classes”.  Note that this
	change will not affect any existing password hashes.  This
	means that all passwords should be re-hashed by asking users
	to run passwd in order to change their
	password.
For remote logins, two-factor authentication should be used. An example of two-factor authentication is “something you have”, such as a key, and “something you know”, such as the passphrase for that key. Since OpenSSH is part of the FreeBSD base system, all network logins should be over an encrypted connection and use key-based authentication instead of passwords. For more information, refer to Section 13.8, “OpenSSH”. Kerberos users may need to make additional changes to implement OpenSSH in their network. These changes are described in Section 13.5, “Kerberos”.
Enforcing a strong password policy for local accounts is a fundamental aspect of system security. In FreeBSD, password length, password strength, and password complexity can be implemented using built-in Pluggable Authentication Modules (PAM).
This section demonstrates how to configure the minimum and
	maximum password length and the enforcement of mixed
	characters using the pam_passwdqc.so
	module.  This module is enforced when a user changes their
	password.
To configure this module, become the superuser and
	uncomment the line containing
	pam_passwdqc.so in
	/etc/pam.d/passwd.  Then, edit that line
	to match the password policy:
password        requisite       pam_passwdqc.so         min=disabled,disabled,disabled,12,10 similar=deny retry=3 enforce=usersThis example sets several requirements for new passwords.
	The min setting controls the minimum
	password length.  It has five values because this module
	defines five different types of passwords based on their
	complexity.  Complexity is defined by the type of characters
	that must exist in a password, such as letters, numbers,
	symbols, and case.  The types of passwords are described in
	pam_passwdqc(8).  In this example, the first three types
	of passwords are disabled, meaning that passwords that meet
	those complexity requirements will not be accepted, regardless
	of their length.    The 12 sets a minimum
	password policy of at least twelve characters, if the password
	also contains characters with three types of complexity.  The
	10 sets the password policy to also allow
	passwords of at least ten characters, if the password contains
	characters with four types of complexity.
The similar setting denies passwords
	that are similar to the user's previous password.  The
	retry setting provides a user with three
	opportunities to enter a new password.
Once this file is saved, a user changing their password will see a message similar to the following:
%passwdChanging local password for trhodes Old Password: You can now choose the new password. A valid password should be a mix of upper and lower case letters, digits and other characters. You can use a 12 character long password with characters from at least 3 of these 4 classes, or a 10 character long password containing characters from all the classes. Characters that form a common pattern are discarded by the check. Alternatively, if no one else can see your terminal now, you can pick this as your password: "trait-useful&knob". Enter new password:
If a password that does not match the policy is entered, it will be rejected with a warning and the user will have an opportunity to try again, up to the configured number of retries.
Most password policies require passwords to expire after
	so many days.  To set a password age time in FreeBSD, set
	passwordtime for the user's login class in
	/etc/login.conf.  The
	default login class contains an
	example:
# :passwordtime=90d:\
So, to set an expiry of 90 days for this login class,
	remove the comment symbol (#), save the
	edit, and run cap_mkdb
	  /etc/login.conf.
To set the expiration on individual users, pass an
	expiration date or the number of days to expiry and a username
	to pw:
#pw usermod -p30-apr-2015-ntrhodes
As seen here, an expiration date is set in the form of day, month, and year. For more information, see pw(8).
A rootkit is any unauthorized
	software that attempts to gain root access to a system.  Once
	installed, this malicious software will normally open up
	another avenue of entry for an attacker.  Realistically, once
	a system has been compromised by a rootkit and an
	investigation has been performed, the system should be
	reinstalled from scratch.  There is tremendous risk that even
	the most prudent security or systems engineer will miss
	something an attacker left behind.
A rootkit does do one thing useful for administrators: once detected, it is a sign that a compromise happened at some point. But, these types of applications tend to be very well hidden. This section demonstrates a tool that can be used to detect rootkits, security/rkhunter.
After installation of this package or port, the system may be checked using the following command. It will produce a lot of information and will require some manual pressing of ENTER:
#rkhunter -c
After the process completes, a status message will be printed to the screen. This message will include the amount of files checked, suspect files, possible rootkits, and more. During the check, some generic security warnings may be produced about hidden files, the OpenSSH protocol selection, and known vulnerable versions of installed software. These can be handled now or after a more detailed analysis has been performed.
Every administrator should know what is running on the
	systems they are responsible for.  Third-party tools like
	rkhunter and
	sysutils/lsof, and native commands such
	as netstat and ps, can
	show a great deal of information on the system.  Take notes on
	what is normal, ask questions when something seems out of
	place, and be paranoid.  While preventing a compromise is
	ideal, detecting a compromise is a must.
Verification of system files and binaries is important because it provides the system administration and security teams information about system changes. A software application that monitors the system for changes is called an Intrusion Detection System (IDS).
FreeBSD provides native support for a basic IDS system. While the nightly security emails will notify an administrator of changes, the information is stored locally and there is a chance that a malicious user could modify this information in order to hide their changes to the system. As such, it is recommended to create a separate set of binary signatures and store them on a read-only, root-owned directory or, preferably, on a removable USB disk or remote rsync server.
The built-in mtree utility can be used
	to generate a specification of the contents of a directory.  A
	seed, or a numeric constant, is used to generate the
	specification and is required to check that the specification
	has not changed.  This makes it possible to determine if a
	file or binary has been modified.  Since the seed value is
	unknown by an attacker, faking or checking the checksum values
	of files will be difficult to impossible.  The following
	example generates a set of SHA256 hashes,
	one for each system binary in /bin, and
	saves those values to a hidden file in root's home directory,
	/root/.bin_chksum_mtree:
#mtree -s3483151339707503-c -K cksum,sha256digest -p/bin>/root/.bin_chksum_mtree#mtree: /bin checksum: 3427012225
The 3483151339707503 represents
	the seed.  This value should be remembered, but not
	shared.
Viewing /root/.bin_cksum_mtree should
	yield output similar to the following:
#          user: root
#       machine: dreadnaught
#          tree: /bin
#          date: Mon Feb  3 10:19:53 2014
# .
/set type=file uid=0 gid=0 mode=0555 nlink=1 flags=none
.               type=dir mode=0755 nlink=2 size=1024 \
                time=1380277977.000000000
    \133        nlink=2 size=11704 time=1380277977.000000000 \
                cksum=484492447 \
                sha256digest=6207490fbdb5ed1904441fbfa941279055c3e24d3a4049aeb45094596400662a
    cat         size=12096 time=1380277975.000000000 cksum=3909216944 \
                sha256digest=65ea347b9418760b247ab10244f47a7ca2a569c9836d77f074e7a306900c1e69
    chflags     size=8168 time=1380277975.000000000 cksum=3949425175 \
                sha256digest=c99eb6fc1c92cac335c08be004a0a5b4c24a0c0ef3712017b12c89a978b2dac3
    chio        size=18520 time=1380277975.000000000 cksum=2208263309 \
                sha256digest=ddf7c8cb92a58750a675328345560d8cc7fe14fb3ccd3690c34954cbe69fc964
    chmod       size=8640 time=1380277975.000000000 cksum=2214429708 \
                sha256digest=a435972263bf814ad8df082c0752aa2a7bdd8b74ff01431ccbd52ed1e490bbe7The machine's hostname, the date and time the specification was created, and the name of the user who created the specification are included in this report. There is a checksum, size, time, and SHA256 digest for each binary in the directory.
To verify that the binary signatures have not changed, compare the current contents of the directory to the previously generated specification, and save the results to a file. This command requires the seed that was used to generate the original specification:
#mtree -s3483151339707503-p/bin</root/.bin_chksum_mtree>>/root/.bin_chksum_output#mtree: /bin checksum: 3427012225
This should produce the same checksum for
	/bin that was produced when the
	specification was created.  If no changes have occurred to the
	binaries in this directory, the
	/root/.bin_chksum_output output file will
	be empty.  To simulate a change, change the date on
	/bin/cat using touch
	and run the verification command again:
#touch /bin/cat#mtree -s3483151339707503-p/bin</root/.bin_chksum_mtree>>/root/.bin_chksum_output#more /root/.bin_chksum_outputcat changed modification time expected Fri Sep 27 06:32:55 2013 found Mon Feb 3 10:28:43 2014
It is recommended to create specifications for the
	directories which contain binaries and configuration files, as
	well as any directories containing sensitive data.  Typically,
	specifications are created for /bin,
	/sbin, /usr/bin,
	/usr/sbin,
	/usr/local/bin,
	/etc, and
	/usr/local/etc.
More advanced IDS systems exist, such
	as security/aide.  In most cases,
	mtree provides the functionality
	administrators need.  It is important to keep the seed value
	and the checksum output hidden from malicious users.  More
	information about mtree can be found in
	mtree(8).
In FreeBSD, many system features can be tuned using
	sysctl.  A few of the security features
	which can be tuned to prevent Denial of Service
	(DoS) attacks will be covered in this
	section.  More information about using
	sysctl, including how to temporarily change
	values and how to make the changes permanent after testing,
	can be found in Section 11.9, “Tuning with sysctl(8)”.
Any time a setting is changed with
	  sysctl, the chance to cause undesired
	  harm is increased, affecting the availability of the system.
	  All changes should be monitored and, if possible, tried on a
	  testing system before being used on a production
	  system.
By default, the FreeBSD kernel boots with a security level of
	-1.  This is called “insecure
	  mode” because immutable file flags may be turned off
	and all devices may be read from or written to.  The security
	level will remain at -1 unless it is
	altered through sysctl or by a setting in
	the startup scripts.  The security level may be increased
	during system startup by setting
	kern_securelevel_enable to
	YES in /etc/rc.conf,
	and the value of kern_securelevel to the
	desired security level.  See security(7) and init(8)
	for more information on these settings and the available
	security levels.
Increasing the securelevel can break
	  Xorg and cause other issues.  Be
	  prepared to do some debugging.
The net.inet.tcp.blackhole and
	net.inet.udp.blackhole settings can be used
	to drop incoming SYN packets on closed
	ports without sending a return RST
	response.  The default behavior is to return an
	RST to show a port is closed.  Changing the
	default provides some level of protection against ports scans,
	which are used to determine which applications are running on
	a system.  Set net.inet.tcp.blackhole to
	2 and
	net.inet.udp.blackhole to
	1.  Refer to blackhole(4) for more
	information about these settings.
The net.inet.icmp.drop_redirect and
	net.inet.ip.redirect settings help prevent
	against redirect attacks.  A redirect
	attack is a type of DoS which sends mass
	numbers of ICMP type 5 packets.  Since
	these packets are not required, set
	net.inet.icmp.drop_redirect to
	1 and set
	net.inet.ip.redirect to
	0.
Source routing is a method for detecting and accessing
	non-routable addresses on the internal network.  This should
	be disabled as non-routable addresses are normally not
	routable on purpose.  To disable this feature, set
	net.inet.ip.sourceroute and
	net.inet.ip.accept_sourceroute to
	0.
When a machine on the network needs to send messages to
	all hosts on a subnet, an ICMP echo request
	message is sent to the broadcast address.  However, there is
	no reason for an external host to perform such an action.  To
	reject all external broadcast requests, set
	net.inet.icmp.bmcastecho to
	0.
Some additional settings are documented in security(7).
All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/
Questions that are not answered by the
    documentation may be
    sent to <freebsd-questions@FreeBSD.org>.
    Send questions about this document to <freebsd-doc@FreeBSD.org>.