Wednesday August 16, 2006
Auditing Zones Yes,
I'm still paranoid. Having the
X2100 out on the web is like being a fish in the ocean, and I'm at the bottom of the food chain. At some point I'll start creating some services, but I have this constant "look over my shoulder" gut feeling. I've got the web server up and running, but it's disabled at the moment :)
Securing one's only child server is like
Fight Club. The first rule of Fight Club is to not talk about Fight Club. However, I'm willing to take one for the team. I've got ipfilters running and zones are are running all necessary services with any
unneeded services disabled. The global zone is doing pretty much nothing. Logging is enabled ... everywhere.
With the help of Sun Blueprints (
here and
here for example) and others (
here and
here), I thought I would utilize
BART. However, I've only got one server. Unless someone wants to donate a second server and the monthly hosting fees, I don't have the luxury of auditing (BARTing) my system over ssh (
Update: anyone want to take a guess as to why we don't call it File Audit and Reporting Tool?). So I took a related route by making the global zone the "master" system, sans SSH. BART is run from the global zone and audits the local zones from the global zone. While listening to the news last night, I threw together a script (below) to automate the auditing, with cron running the script via automated intervals. If you follow the blueprints, you can create a separate account with just enough privileges to run BART, but nothing more.
One feature I want to add is a second cron script to scan the "reports" directory, and email (via "zlogin mailzone mail ...") any potential issues. Before that, I have to write some code to clean up old reports & daily manifests.
#!/usr/bin/bash
#
# BART_DIR: top level directory for bart input and output files
#
BART_DIR=/var/bart
#
# RULES_DIR. While it is an option to have one rules file for all
# zones, this script copies a rules file template, which can later be
# customized for each zone
#
RULES_DIR=${BART_DIR}/rules
#
# CONTROL_MANIFEST_DIR contains The "Control" manifest. This contains the
# baseline manifest for each zone.
#
CONTROL_MANIFEST_DIR=${BART_DIR}/manifests
#
# DAILY_DIR containes manifests created daily, with a subdirectory for each
# zone.
#
DAILY_DIR=${BART_DIR}/daily
#
# REPORT_DIR, whith a sub-directory for each zone, contains the daily
# comparisons between the control manifest and the daily manifest.
# These files will show file modifications
#
REPORT_DIR=${BART_DIR}/reports
#
# RULES_TEMPLATE. Default rules file that will be utilized by default for
# each zone.
#
RULES_TEMPLATE=${RULES_DIR}/rules.template
#
# The bart binary.
#
BART=/usr/bin/bart
#
# List of all zones on the host, running or not
#
zones=`/usr/sbin/zoneadm list -cp | cut -d':' -f 2`
#
# Pre-create the various directories. This requires "/var/bart" (by default)
# to exist and have appropriate permissions.
#
if [ ! -d ${RULES_DIR} ];
then
mkdir -p ${RULES_DIR}
fi
if [ ! -d ${DAILY_DIR} ];
then
mkdir -p ${DAILY_DIR}
fi
if [ ! -d ${CONTROL_MANIFEST_DIR} ];
then
mkdir -p ${CONTROL_MANIFEST_DIR}
fi
if [ ! -d ${REPORT_DIR} ];
then
mkdir -p ${REPORT_DIR}
fi
#
# For each zone, run bart. The first time through, create the control
# manifest. Run this script before putting any newly created zone on
# the network. Creating a control manifest of compromised zone doesn't
# do much good :)
#
for zone in ${zones}
do
#
# Get the base directory of the zone. Wish there were a formal CLI
# way of doing this (zoneadm get property would be nice). If you have
# a better way of doing this, ping me.
#
zonepath=`grep ${zone} /etc/zones/index | cut -d':' -f 3`
#
# Pre-create various "file" and "directory" variables before the heavy lifting.
#
CONTROL_MANIFEST_FILE=${CONTROL_MANIFEST_DIR}/${zone}.control.manifest
RULE_FILE=${RULES_DIR}/${zone}.rules
DATE=`date '+%m_%d_%y'`
DAILY_TEST_MANIFEST=${DAILY_DIR}/${zone}/${DATE}.manifest
REPORT_FILE=${REPORT_DIR}/${zone}/${DATE}.report
#
# Determining the global zone base directory is different than local
# zones
if [ "${zone}" = "global" ];
then
BASE_ZONE_DIR=/
else
BASE_ZONE_DIR=${zonepath}/root
fi
#
# If the control file doesn't exist, create it. If it does exist, create
# the daily manifest and generate a report.
#
if [ ! -f ${CONTROL_MANIFEST_FILE} ];
then
if [ ! -f ${RULES_DIR}/rules.template ];
then
echo "Rules template does not exist, please create ${RULES_DIR}/rules.template"
exit 1
fi
#
# If a rules file doesn't exist, copy the template
#
if [ ! -f ${RULES_DIR}/${zone}.rules ];
then
cp ${RULES_DIR}/rules.template ${RULE_FILE}
fi
${BART} create -R ${BASE_ZONE_DIR} -r ${RULE_FILE} > ${CONTROL_MANIFEST_FILE}
else
#
# Create the zone's report and daily sub directory
#
if [ ! -d ${REPORT_DIR}/${zone} ];
then
mkdir -p ${REPORT_DIR}/${zone}
fi
if [ ! -d ${DAILY_DIR}/${zone} ];
then
mkdir -p ${DAILY_DIR}/${zone}
fi
#
# Generate the daily manifest
#
${BART} create -R ${BASE_ZONE_DIR} -r ${RULE_FILE} > ${DAILY_TEST_MANIFEST}
#
#
# Generate the daily report by comparing the control manifest with the
# daily manifest
#
${BART} compare -r ${RULE_FILE} ${CONTROL_MANIFEST_FILE} \
${DAILY_TEST_MANIFEST} > ${REPORT_FILE}
fi
done
Per the script, here is a sample "rules.template" file. Customize to your needs.
/usr/sbin
/usr/bin
/etc
CHECK all
IGNORE dirmtime
(2006-08-16 08:27:22.0)
Permalink
Posted by Matty on August 16, 2006 at 11:19 AM PDT #
Matty, many thanks for the heads up. Actually, I did not catch that. However, I can't see what the issue is the way I use it (doesn't mean there isn't an issue :) ).
I run the above script as non-root user, and the only permissions that user has is file_dac_read and file_dac_search. No file_dac_write. Basically, the search in read-only mode to zone mount points. One general concern with running tools fromt the global zone is that the zone's mount point gets changed from 700 to something more accessible.
I'll ping around and see what the potential issues are. I'm scratching my head on the warning. However, warning's like that shouldn't be ignored. Again, thanks for the heads up.
Posted by John Clingan on August 16, 2006 at 12:37 PM PDT #
Matty, I found this. In particular, from the Solaris Security Toolkit:
"Because of security risks, you should never access a non-global zone file system from outside that zone. A path that is not dangerous in a non-global zone can be dangerous in the global zone. For example, a non-global zone administrator can link the /etc/shadow file to the ../../../shadow file. Inside the non-global zone, this is harmless, but modifications to the file from the global zone, using the path /opt/testzone/etc/shadow, would edit the global zones /etc/passwd file. Again, a non-global zone should never be hardened, undone, cleaned, or even audited unless you are logged into that zone."
I think the problem is not a specific technical one, it's a "best practices" problem. The more users directly address a local zone from the global zone, the greater the chance for either inadvertant destructive behavior or the inadvertant creation of security holes.
That being said, everything accomplished via the "above" script can be done via zlogin, although it will take some thinking about how to accomplish this as securely as possible as a non-root user.
Posted by John Clingan on August 16, 2006 at 12:58 PM PDT #
Posted by Bernd Haug on August 17, 2006 at 09:34 AM PDT #
Bernd, excellent point. Thanks for the link!
Posted by John Clingan on August 17, 2006 at 01:22 PM PDT #