By Seán Boran
www.boran.com/security/sp/Solaris_hardening1.html
Notes:
- a second Version of this article includes Solaris
8 and Yassp beta#5 (very old)
- a third version includes Yassp beta#15
- a fourth version uses Jass (this is the most
recent and up-to-date)
- This version will not longer be updated, but it is still useful, as it runs through
MANUAL hardening, as opposed to allowing a tool like Yassp to do all the work for you.
Originally published October 25, 1999. This article presents a concise step-by-step approach to securely installing Solaris for use in a firewall DMZ, or other sensitive environment. There are many books and web articles on general hardening, but deciding exactly how to do it for your Solaris system can be tricky.
The focus in this article is on preparing the Operating System to securely run services, rather than the setup of the services themselves. Firewall engines like Raptor, Firewall-1, Sunscreen etc. are not examined here.
This article is specific to Solaris 2.7, other versions are similar, but
will have some differences in startup file names, kernel parameters etc. It is
planned to update this article for Solaris 8 when it is shipped in March 2000.
This article has been updated since the original release, see the Additional Notes section.
We welcome your feedback on this article.
We divide up the process into the following steps:
Connect the serial console, switch on, halt to the OK prompt by sending a Stop-A (~#,
~%b, or F5 depending on whether you use tip, cu or a vt100 terminal),
then start the installation procedure -
"boot cdrom - install".
Install the minimum end user bundle (or even better the core packages), set hostname, terminal, IP parameters, timezone, etc. Don't enable naming services like NIS or NFS. Don't enable power management. Don't mount any remote file systems (NFS).
Choose manual disk partitioning: Keep /usr and /opt separate from root, so that they
can be later mounted read-only (see below). Consider a separate, large /var filesystem for
syslog/web/news/proxy servers. Servers containing lots of data (web, ftp) should use a
separate disk for their data.
If you don't wish to mount partitions read-only, then put the whole boot disk under root.
Suggestion for a 2GB disk: 200MB / (+var), 200MB swap, 600MB /usr and 1GB on /opt.
Suggestion for a 1GB disk: 300MB / (+var+opt), 200MB swap, 500MB /usr.
Set a strong password (7 or 8 chars with numbers, letters and punctuation) for root, and reboot.
No man pages are installed with the user bundle, so install some while the the Solaris CD is still mounted:
cd /cdrom/cdrom0/s0/Solaris_2.7/Product;
pkgadd -d . SUNWman SUNWdtmaz SUNWdtma SUNWjvman SUNWpmowm SUNWolman SUNWolman SUNWtltkm SUNWxwman SUNWxwpmnUpdate indices, so that "man -k keyword" will allow searching of relevant man pages:
/usr/lib/makewhatis /usr/man; /usr/lib/makewhatis /usr/openwin/man;
/usr/lib/makewhatis /usr/local/man
Install the recommended & security patches from Sun. Typically a separate CD "Maintenance Release" is provided with a patch bundle. Reboot and logon again as root. The list of patches installed can be listed with showrev -p .
Disk mounting: To reduce the risk of trojan horses and unauthorised modifications, in /etc/vfstab, mount / with options "remount,nosuid", /var with "nosuid", /tmp with "size=100m,nosuid" (allow /tmp to only use 100MB of swap space and disallow execution of SUID programs).
The commands listed below assume you use the C-Shell. If you use the C-Shell, the
following will make editing easier and enable history functions:
csh;
setenv TERM vt100; setenv VISUAL vi; setenv EDITOR vi;
set filec; set history=40; alias h history; alias ls 'ls -aF \!*';
Shutdown the network interface during this phase, just in case (the interface name depends on the architecture e.g. hme0 or le0):
ifconfig le0 down
Disable NFS :
rm /etc/rc2.d/{S73nfs.client,K28nfs.server} /etc/rc3.d/S15nfs.server /etc/dfs/dfstab
Disable Sendmail daemon. Although sendmail is not running as a daemon, the binary is still present and email can be sent from (but not received by) the host. The only host that needs to receive email, the mail gateway, should use smap or an equivalent to minimise sendmail risks.
rm /etc/rc2.d/S88sendmail
And add a root cron entry to process the mail queue hourly:
0 * * * * /usr/lib/sendmail -q
Disable more services (automounter, power mgt., serial protocols, caching fs, etc.):
rm /etc/rc2.d/{S74autofs,S30sysid.net,S71sysid.sys,S72autoinstall} /etc/auto_*;
rm /etc/rc2.d/{S93cacheos.finish,S73cachefs.daemon,S80PRESERVE};
rm /etc/rc2.d/{S85power,K07dmi};
rm /etc/rc3.d/S77dmi;
If you have server/developer packages:
rm /etc/rc2.d/{S47asppp,S89bdconfig,S70uucp}
Disable RPC: This is highly desirable, but will break some programs like CDE or Disksuite. If you don't disable RPC, then a packet filter that blocks it is an absolute must.
rm /etc/rc2.d/S71rpc
Disable printing (unless there's a local printer attached):
rm /etc/rc2.d/{S80lp,S80spc}
Consider disabling the naming Services Caching Daemon: I've had problems with nscd (& Soalris 2.5) and don't like daemons running that I don't trust. It might offer performance advantages however, and some applications such as Netscape webproxy V3.5 needs it.
mv /etc/rc2.d/S76nscd /etc/rc2.d/.S76nscd
Disable CDE: unless you insisted on a graphical console?
rm /etc/rc2.d/S99dtlogin
Consider disabling NTP - Network Time Protocol. (NTP is accurate but complex, uses bandwidth and is an additional security worry. I prefer to use rdate to one central host, which then uses NTP to get accurate time). See also the additional notes below. To disable it:
mv /etc/rc2.d/S74xntpd /etc/rc2.d/.S74xntpd
Disable SNMP, unless you do really need to use HP Openview or whatever. I prefer simple ping/traceroute scripts. If SNMP is switched on, only allow read (not write) access and change the community string.
rm /etc/rc2.d/K07snmpdx /etc/rc3.d/S76snmpdx
Inetinit: Disable ip forwarding, source routing (if there is more than one network interface), and avoid echo broadcasts. Add a few lines to the end of /etc/init.d/inetinit:
## hardening
ndd -set /dev/ip ip_forward_directed_broadcasts 0
ndd -set /dev/ip ip_forward_src_routed 0
ndd -set /dev/ip ip_forwarding 0
ndd -set /dev/ip ip_respond_to_echo_broadcast 0
ndd -set /dev/ip ip_strict_dst_multihoming 1
And in /etc/default/inetinit, prevent TCP sequence prediction (IP spoofing) attacks, by generating initial sequence numbers as suggested in RFC 1948.
TCP_STRONG_ISS=2
This change can be edited automatically with:
mv /etc/default/inetinit /etc/default/inetinit.orig;
sed 's/TCP_STRONG_ISS=1/TCP_STRONG_ISS=2/' /etc/default/inetinit.orig \
> /etc/default/inetinit; chgrp sys /etc/default/inetinit;
Prevent some buffer-overflow attacks by adding the following lines to /etc/system. This protects against forms of attack where the code to be executed lives on the stack. The OS won't allow the code to be executed, but it requires hardware support (it's only effective on sun4u/sun4d/sun4m systems).
* Hardening
set noexec_user_stack=1
set noexec_user_stack_log=1
Use default routes: add the IP address of the router to /etc/defaultrouter, or create a
startup file in /etc/rc2.d/S99static_routes using the "route" command. To
disable dynamic routing:
touch /etc/notrouter
mv /usr/sbin/in.routed /usr/sbin/.in.routed
/etc/init.d/inetsvc:
- Disable multicasting by commenting the lines around "route add 224.0.0.0."
(it's about 14 lines, make sure you get all the ones in brackets).
- Enable logging of all INETD connections: Add add "-t" to the inetd startup
line at the bottom, it should read: /usr/sbin/inetd -s -t . Even better: disable
inetd (see below)
Configure /etc/hosts with a list of critical machines (which you don't want resolved via DNS).
/etc/inetd.conf:
Reboot.
The system has now gone through a first hardening phase and should be still working! Connect it to a secure, isolated network where standard tools/software can be downloaded. Boot and login on the console as root. Check for error messages on the console during boot, fix if necessary.
Tools are typically copied down with ftp. Avoid using the root account on the target
server and change the password to a temporary one during the downloads, change back
afterwards.
Once SSH has been installed, use it, rather than ftp for downloads.
At this stage standard tools/utilities are going to be installed, the most important being SSH. These tools should already have been compiled and tested extensively on another machine. They are typically transferred as tar files, by CD or FTP.
/.cshrc /.profile: set aliases, variables (such as VISUAL, EDITOR and PATH don't include "."). Set umask to 077, or 027.
DNS client (avoid if not needed): add domain name & DNS servers to /etc/resolv.conf. Add a DNS entry for "hosts" in /etc/nsswitch.conf.
Email: If hosts are not supposed to send email outside the subnet, don't configure the
mailhost alias. Delete /usr/lib/sendmail if you don't need any kind of email.
Otherwise edit /etc/mail/aliases (at least point root to a real address), set mailhost
in /etc/hosts and in /etc/mail/sendmail.cf set the following to ensure all outgoing email
is channeled over mailhost:
Dj$w.YOURDOMAIN.COM.
DSmailhost
DRmailhost
DHmailhost
O FallbackMXhost=mailhost
Add a hostname.YOURDOMAIN.COM alias for this machine in /etc/hosts.
Send a test email to check the config:
mailx -v -s test_email root </dev/null
More OS patches: The Patch CD above won't be quite up to date. Get the Patchdiag tool from Sunsolve along with and update patchdiag.xref and run it to see what recommended and security patches are needed, then download & install the missing ones.
Configure logging:
Enable SU logging to console in /etc/default/su.
Enable logging of failed attempts to login:
touch /var/adm/loginlog; chmod 600 /var/adm/loginlog; chgrp sys /var/adm/loginlogSyslog logging: Split up log analysis according to the example syslog.conf which enables more logging than the default and splits up services into separate logfiles. Designate one machine as the loghost (in /etc/hosts) or log locally.
Syslog "loghost"
Give the loghost a whopping great disk for logs.
Create empty logs & set permissions:
cd /var/log; touch daemonlog authlog kernlog userlog maillog lprlog cronlog newslog locallog alertlog;
chmod 600 daemonlog authlog kernlog userlog maillog lprlog cronlog newslog locallog alertlog;
kill -1 `pgrep syslogd`Use rotate_log to prune & compress logs, add the root cron entries:
## Prune syslog logs weekly, keeping the last 6 months or so:
55 23 * * 6 /secure/rotate_log -n 40 alertlog
55 23 * * 6 /secure/rotate_log -n 40 authlog
55 23 * * 6 /secure/rotate_log -n 20 cronlog
55 23 * * 6 /secure/rotate_log -n 40 daemonlog
55 23 * * 6 /secure/rotate_log -n 40 kernlog
55 23 * * 6 /secure/rotate_log -n 40 locallog
55 23 * * 6 /secure/rotate_log -n 20 newslog
55 23 * * 6 /secure/rotate_log -n 40 userlog
55 23 * * 6 /secure/rotate_log -n 10 lprlog
55 23 * * 6 /secure/rotate_log -n 20 maillogDisable the Solaris log pruning (& other) lines in the root cron, since you're doing it yourself:
#10 3 * * 0,4 /etc/cron.d/logchecker
#10 3 * * 0 /usr/lib/newsyslog
#15 3 * * 0 /usr/lib/fs/nfs/nfsfind
#1 2 * * * [ -x /usr/sbin/rtc ] && /usr/sbin/rtc -c > /dev/null 2>&1
#30 3 * * * [ -x /usr/lib/gss/gsscred_clean ] && /usr/lib/gss/gsscred_cleanPruning of login & other logs:
## Empty login/logout records at year end
0 0 31 12 * /secure/wtrim.pl wtmp 20
0 0 31 12 * /secure/wtrim.pl wtmpx 20
# Solaris 2.x logs:
0 4 * * 6 /secure/rotate_log -L /var/adm -n 30 loginlog
0 4 * * 6 /secure/rotate_log -L /var/adm -n 30 sulog
0 4 * * 6 /secure/rotate_log -L /var/adm -n 2 vold.log
0 4 * * 6 /secure/rotate_cron
Crons
Remove unnecessary crons:
rm /var/spool/cron/crontabs/{lp,sys,adm}
Don't delete the adm cron if you want sar performance collection or accounting .Root cron entries:
Set date once a day with a reliable source using rdate (you may prefer NTP, it's more accurate, but complex, uses bandwidth and is an additional security worry):
## Synchronise the time:
0 * * * * /usr/bin/rdate YOURTIMEHOST >/dev/null 2>&1
File permissions: tighten basic permissions, and restrict certain tools to root or disable:
chmod 0500 /usr/sbin/snoop /usr/sbin/devinfo
chmod o-r /var/spool/cron/crontabs/*
chmod 000 /bin/rdist
chmod o-rx /etc/security
chmod og-rwx /var/adm/vold.log
chmod u-s /usr/lib/sendmail #Not for mailgateways or multi-user hosts
chmod 400 /.shosts /etc/sshd_config /etc/ssh_known_hostsThen download, compile and run Casper Dik's script ftp://ftp.fwi.uva.nl/pub/solaris/fix-modes.tar.gz for improving file and directory permissions (runs on Solaris 2.2-2.7).
Documentation:
Document configuration changes in a text file such as /etc/mods, update after each change, with date, author, files affected, description.
cat > /etc/mods <<EOF
29.11.99 sb New install of Solaris2.7 & tools according to hardening guidelines
EOFSet login banners to warn users about unauthorised access (you'll need this if you want to prosecute intruders). For Telnet and SSH, use /etc/issue (for pre-login) /etc/motd (for post-login), containing, for example:
ATTENTION: You have logged onto a secured XXXX Corporation server.
Access by non YYYY administrators is forbidden.
For info contact YYYY@XXX.com
Reboot, login via SSH.
Now, ps -e should show a small process list:
PID TTY TIME CMD
0 ? 0:00 sched
1 ? 0:00 init
2 ? 0:00 pageout
3 ? 0:09 fsflush
156 ? 0:00 ttymon
152 ? 0:00 sac
447 ? 0:06 sshd
88 ? 0:00 inetd
98 ? 0:00 cron
136 ? 0:00 utmpd
605 ? 0:00 syslogd
175 console 0:00 ttymon
469 pts/1 0:00 csh
466 ? 0:01 sshd
625 pts/1 0:00 psand netstat -a should show a minimum of network connections (e.g. only SSH).
UDP
Local Address Remote Address State
-------------------- -------------------- -------
*.syslog Idle
*.* Unbound
TCP
Local Address Remote Address Swind Send-Q Rwind Recv-Q State
-------------------- -------------------- ----- ------ ----- ------ -------
*.* *.* 0 0 0 0 IDLE
*.22 *.* 0 0 0 0 LISTEN
*.* *.* 0 0 0 0 IDLE
Mount /usr and /opt read-only (in /etc/vfstab with "ro" option). This reduces the risk of trojan horses and unauthorised modifications.
Mount other partitions nosuid (SUID programs cannot assume other identities).
Reboot.
Run the mount command to check that filesystems options are effective.
Consider installing applications on a separate partition or /opt. If /opt is used, it will have to be mounted read-write during installation and testing, and switched back to read-only afterwards.
Depending on the function of the server, applications such as ftpd, BIND, proxies, etc. are installed at this point. Web servers and firewall engines in particular, are complex and require careful configuration. The following is a general checklist that servers/applications should conform to:
- Is the umask set restrictively (e.g. 022) by or before the application starts?
- Does it run as a non root user with minimum privileges? Is it's password "blocked" and shell set to a dummy value such as /bin/false? If the password is really needed, is it set to min 8 chars with numbers, letters and punctuation?
- If it runs as root, to bind to a low port, does it immediately fork to a non privileged user to minimise risks?
- Are file permissions set so that only the application user can read/write files are there are no world read/writeable files?
- Does the application write log permissions securely? Does it write passwords in the install log (don't laugh - it's common!).
1. FTP server (ftpd):
- If you use Washington University wu-ftpd (for it's better logging, access control and other features), be wary. It has a history of bugs (e.g. see CERT advisories CA-93:06, CA-94:07, CA-95:16 and Auscert AA-97.03 and AA-1999.02). Use at least V2.6.0 or later.
- Configure /etc/ftpusers to list system accounts, so they cannot not be used for ftp e.g. disable use of ftp by root, add "root" to /etc/ftpusers.
One way of doing this for all system accounts on your fresh new system is:
awk -F: '{print $1}' /etc/passwd > /etc/ftpusers- FTP can be selectively enabled per user via /etc/ftpusers or by using the following trick: For users who shouldn't have ftp access to this machine, give their accounts a non-standard shell (such as bash or tcsh) and don't enter this new shell into /etc/shells. FTP access will be denied. Conversely, if a non-standard shell is required, it must appear in /etc/shells for FTP to work correctly.
- Enable logging: adding the "-l" option in /etc/inetd.conf (the additional -d option adds debug output).
- FTP can be restricted on an IP address or hostname basis with the tcp wrappers.
- For anonymous ftp, be VERY careful. A chroot environment is a MUST. See the in.ftpd man page which includes a script. Avoid allowing uploads. If uploads are necessary, don't allow downloads of uploaded files, hide uploaded file names and don't allow them to be overwritten (otherwise you may end up as an illegal software repository).
- For normal "user ftp", chroot is also recommended.
- Put the ftp data area on a separate disk partition and mount it nosuid.
2. DNS servers:
- Use the latest BIND (Berkeley Internet Name Server) rather than Sun's named. BIND has more features, is easier to debug (with dig) and is updated quickly when security problems are found. See www.isc.org/products/BIND
- Use 8.2.2-P5 or later (which includes security fixes).
- Create a "dns" user and group and start with "/usr/local/sbin/named -u dns", so that BIND will fork and change identity to the dns user (rather than the all powerful root). Give the dns user read access to BIND configuration files (they should belong to root however).
- Restrict zone transfers to the IP address of secondaries (in /etc/named.conf).
- Consider installing BIND in a chrooted environment.
- A great tool for testing active domains is www.uniplus.ch/direct/testtool/dnstest.html
- Troubleshooting:
- Use nslookup or dig to check server results.
- Client: Check /etc/nsswitch.conf and /etc/resolv.conf if you're having DNS client side problems. Start nslookup with the "-d2" option to get buckets of debugging info. Try killing the nscd daemon.
- Server: Use spaces and not tabs in Sun's old /etc/named.boot (bind uses named.conf). Start named with the debug option "-d" and read the console & logs. Typically logs are found in the syslog "daemon" section.
- See www.ebsinc.com/solaris/dns.html
- To get statistics from the name server, do the following
kill -ABRT `cat /etc/named.pid`
This puts the statistics into the file /usr/tmp/named.stats.- Send a HUP signal to named, to reread the config file after changes.
kill -HUP `cat /etc/named.pid`
3. A good article on general chroot environments, also called "padded cells" can be read at Sunworld www.sunworld.com/swol-01-1999/swol-01-security.html
4. HTTP servers:
- If content doesn't change often, store it on CD-ROM, it simplifies change control and provides greater resilience to the hackers favourite of "site defacing". The HTTPD server will cache pages, ensuring that access speed does not depend on CD-ROM speed.
- Separate "simple read-only" content servers from E-commerce servers.
- Check out the CIAC Bulletin J-042 which describes best practices for Internet web servers.
- Setup for a simple Apache 1.3.6 server:
- Download (e.g. from sunfreeware.com) and install as root in /usr/local/apache. Create "apache" user & group with blocked password.
- httpd.conf non-default changes: Set port, switch off server signatures, set ServerAdmin, ServerName, set User & Group=apache.
- File permissions - by default everything will belong to bin, which is fine. Remove world access, give minimum rights to apache group:
chgrp -R apache /usr/local/apache; chmod -R o-rwx /usr/local/apache;
You probably won't need CR-ROMs or floppies anymore, so disable the volume manager:
mv /etc/rc2.d/S92volmgt /etc/rc2.d/.S92volmgt
If you do need to mount a CD in the future, start vold manually & check for new devices:
drvconfig; disks; vold &; volcheck; df -kConsider installing a script to check that important daemons are running. Install monitor_processes.pl and add a root cron entry:
## Check that important processes are running during office hours:
## [If you run 7x24, modify accordingly]
0,30 8-19 * * 1-5 /secure/monitor_processes.pl inetd sshd httpdIf partitions such as /opt or /usr had to be mounted read-write during the application install/testing, mount them read-only now.
Reinitialise tripwire (or equivalent integrity checker).
Backup the system to two tapes, one offsite.
Run a network scan on the system, to ensure that only expected services are visible. A commercial tool such as ISS or a free one like Nessus, nmap or Satan should do the job. Print out the results and archive.
If possible, have additional people do the final testing, just in case something was forgotten.
Test in detail - What works? What is forbidden? Check console/log entries. Does the system behave as expected? Watch the logs very frequently during the first few days of production.
Test in detail. Check log entries. Does the system behave as expected?
Have applications been tested in detail, by different people with different points of view, from different access points on the network?
The following activities should take place hourly, daily, weekly or monthly, depending on how critical the system is:
This article has been very specific, in the interest of making it practical. However, each security administrator has his own methods and each site has different requirements.
sunsolve.sun.com
sunsolve.sun.ch
sunsolve.sun.ch/sunsolve/patchdiag/
sunsolve.sun.ch/private-cgi/patches/patchdiag.xref
Seán Boran is an IT security consultant based in Switzerland and the author of the online IT Security Cookbook.