Good evening. This presentation is based on my GIAC GSNA Gold technical paper entitled “Auditing Mac OS X Compliance with the Center for Internet Security Benchmark Using Nessus.” I wrote the paper as the beginning of the compliance checks for a customer that wanted an automated method to check the compliance of their Mac OS X machines against a baseline. Their baseline was derived from the Mac OS X v10.5 Benchmark from Center for Internet Security (CIS, www.ciseurity.org ). The CIS Benchmark for Mac OS X was released May 2008. It contained Level 1 and Level 2 items. Implementing Level 1 is the minimum recommendation and should not break any applications. Level 2 increases the security posture of the machine but could break applications. In both Level 1 and 2, there are 118 Benchmark items: 66 Level 1 items and 52 Level 2 items. Of those 118 items, there are 51 listed as “Scorable,” indicating that they can be verified with an automated check. Many of the remain items are listed as manual; in other words there is no easy way to automate the checking for that item. The Benchmark includes items which are operational policy issues that can’t be checked on the machines. Unlike Windows, Mac OS X does not have a “security template” or Group Policy Object capability. That means checking the compliance of a Mac against the benchmark requires manually examining the contents of files or other manual checks. The customer could have used a shell script to check the compliance of their Macs but they were already using Nessus to do compliance checks on Windows machines and wanted to use the same tool. When I began writing the compliance checks I wanted to be able to use them on any Mac so I imposed the constraint that only built-in tools would be used and not require installing any scripts or tools in the target machines. 1 In this presentation, you will learn how you can check for secure configurations of Mac OS X (10.5) using Nessus 3 and later. We will learn how the compliance check features of Nessus are used to check security settings on Mac OS X in addition to using the local security checks to scan for vulnerabilities. We will will also learn how to customize the compliance checks for use in your Mac OS X environment. You'll also receive pointers to a detailed list of compliance checks that everyone using a Mac should know and use. References: Center for Internet Security. (2008, May). CIS Level 1 & 2 Benchmark for Mac OS X. Retrieved November 4, 2008 from Center for Internet Security web site: http:// www.cisecurity.org/bench_macosx.html (registration required) Tenable Network Security. (2008, August 1). Nessus Compliance Checks – Auditing UNIX and Windows Device Configurations. Retrieved October 30, 2008, from Tenable Network Security web site: https://plugins-customers.nessus.org/support-center/nessus_compliance_checks.pdf Smith, R.D. (2008, November 7). Auditing Mac OS X Compliance with the Center for Internet Security Benchmark Using Nessus. Retrieved December 31, 2008 from GIAC web site: http:// www.giac.org/certified_professionals/practicals/GSNA/00487.php 2 Nessus started out as an open-source network-based vulnerability scanner. It works solely by checking for open ports and then analyzing the ports and the service behind each port to determine if the machine has a vulnerability. Nessus uses a client-server architecture in which the Nessus daemon conducted the scan against specified targets. The client tells the server which vulnerabilities to check for by specifying a set of plugins to run along with any information necessary for the plugins to run. The Nessus plugins told the server how to conduct the vulnerability checks and the expected results. Once the scan was completed, the server sent the results to the client. When Tenable Security introduced Nessus 3, it went from open source to closed source. Tenable also made several improvements to the capabilities of the Nessus server. The biggest change was the addition of the capability to do local checks. Now a plugin can tell Nessus to log in to the remote target machine and conduct various types of checks. In other words, Nessus can find local client-side vulnerabilities on the machine instead of just network vulnerabilities. For example, it can find that the machine has a vulnerable version of Adobe Reader installed. Tenable Security also made several changes in the licensing of Nessus 3. Currently there are two type of licenses: HomeFeed and ProfessionalFeed. The HomeFeed license is free and allows installation and use in a noncommercial environment. The ProfessionalFeed is required if you use Nessus in a commercial environment or for scanning third parties. You need a ProfessionalFeed license installed to enable the compliance checks capability. Compliance checks use .audit files to specify the checks that will be performed on the target machine and the expected results. Tenable has created Windows and UNIX versions of .audit files to give the ability to specify unique checks on the different OSs. For example, you can check registry values and permissions on a Windows machine with Windows .audit files. We are going to talk exclusively about Unix .audit files for the rest of this talk, although many of the concepts can be applied to the Windows .audit files as well. 3 The .audit files are XML-like in structure. A simple one line tag, <check_type:"Unix"> specifies that this is a UNIX .audit file and a </check_type> tag closes the file. The rest of the .audit file specifies the compliance check items. You can do built-in checks that examine some standard security related parameters on UNIX machines. For example, looking for accounts with an invalid default shell based on the list of shells listed in /etc/shells. Some of these built-in check items don’t work on all versions of UNIX or Linux, for example the min_password_age built-in check is not supported on Mac OS X targets. Custom items are usually check parameters that are not standard across the various flavors of UNIX or Linux or are customized for a particular installation. For the Mac OS X dot-audit files, the majority of the check items used were command execution and file content checks. File content checks can look for existence of text in the file or the lack of text depending on how check is specified. Grammar custom check allows you to use regular expressions to define the correct grammar or construction of a particular file and then check that file There are several other types of custom items that are specific for a particular UNIX or Linux distribution. For example, on RedHat derived systems, you can look at the status of services using chkconfig command or check the version of a particular installed rpm package. Let’s look at some examples of specifying built-in check items. 4 Here are two examples of built in checks. You can tell they are built-in checks since they start with an <item> tag and end with an </item> tag. The checks are built from keywordvalue pairs. The name keyword is required and specifies the built-in check. The next keyword, description is also required. One of the requirements for the description keyword is each check must have a unique description value, but that requirement is handled by Tenable for the built-in checks. Each built-in check may require other keyword-value pairs. For example, the min_password_length requires the value keyword-value pair that specifies the range of acceptable password lengths. For the account_bad_home_permissions check needs the mode keyword-value pair set to the acceptable permissions for a user’s home directory. The severity keyword is one of the optional keyword-value pairs that can be used with any check. The value set using this keyword modifies the severity of the Nessus finding when the check fails. The default severity is HIGH. In the account_bad_home_permissions check example, I have changed the severity to MEDIUM. One thing to remember when writing the checks, the keyword-value pair must be on a single line in the .audit file. In the min_password_length example, the description line has been wrapped onto a second line for display purposes. These checks are well documented in Tenable’s guide to .audit files so I won’t cover them in depth. Now let’s look at the custom compliance checks. 5 The first difference between the built-in checks and the custom checks is the tags are “custom_item” not “item.” Also in most cases, the custom checks need more key-value pairs to the specify the check. The system keyword specifies the operating system that the check applies to. To determine the correct value, run uname on the system. For example on a Mac OS X system, in a Terminal.app window you would get: RDS-MacBook-Pro:~ rick$ uname Darwin The type keyword tells Nessus which one of the 10 kinds of custom checks to perform. This example is a FILE_CHECK so the Nessus compliance check plugin will check the file exists and it matches the specified properties of the file. The properties that can be checked are owner, group owner, permissions, and the MD5 checksum of the file. The description keyword is required and the value must be unique just like for built-in checks. The info keyword-value pairs are optional and are used to add information to the Nessus finding output. In this example, I’ve included information about the applicable section of the CIS benchmark. In the rest of the examples only the Benchmarks Section info keywordvalue pairs will be shown. The file keyword is required and specifies the file to check. You can specify the full path to the file or you can use the search_locations keyword to tell Nessus the directories to search for a file with the name specified by the file keyword. The checks can be specified by using the owner, group, mode, or md5 keyword-value pairs. In this example the mode keyword is used with a value of 0700. For the mode keyword, you can specify the mode as either an absolute mode, “0644”, or as a symbolic mode, “-rw-r--r—”. Now let’s look at checking the contents of a file. 6 For most UNIX systems, checking the configuration settings usually involves looking for the correct value in a text-based configuration file. That is exactly what a FILE_CONTENT_CHECK checks does. It searches the contents of a text file for a match to the regular expression given in the regex keyword. The check will fail if the file does not exist or the contents of the file doesn’t match the expected results. The description keyword is required and the value must be unique just like the built-in checks. The file keyword specifies the file to examine. You can specify the full path to the file or you can specify the search_locations keyword to tell Nessus the directories to search for a file with the name specified by the file keyword. The regex and the expect keywords tell Nessus what content to look for in the text file and the correct results. For this example, the regex keyword is set so we are looking for the line containing “TIMESYNC=” along with the possibility of some other text on either side of it. To break the regular expression down, we see that the regular expression starts and ends with the two characters, “.*”. In regular expressions, a “.” means any character and a “*” means the preceding character can be repeated zero or more times. This gives the possibility of text at either end of the line. The “$” represents the end of the line. So putting it back together, the regular expression will match a line with any number of characters before “TIMESYNC=” and any number of characters after until the end of the line. The expect keyword is set to the same regular express as the regex keyword except the desired value is inserted at the correct position. In this example, we want to see if the TIMESYNC variable in the /etc/hostconfig file is assigned “-YES-” as its value. So the regular expression for the expect keyword has “-YES-” in place of the “.*$”. For the check to pass, the line which matched the regex keyword pattern can contain any number of characters before “TIMESYNC=-YES-” and nothing after. This type of check doesn’t work for configuration files where the text to check is on multiple lines or the configuration files aren’t text files. We will need to use command execution checks for many of the configuration file checks. 7 The command execution compliance checks gives us the capability to use the output of a command run on the target system to verify the compliance of the target system. The Nessus compliance check plugin runs the command then verifies the output is correct. On Unix systems, the Nessus compliance plugin will run the command with sudo using the supplied sudo credentials unless the nosudo keyword is set to “YES.” There are limitations on command execution compliance checks that we need to understand before we look at some examples. The first limitation that you need to understand is the commands must be as a single line. You can pipe commands together but you have to end up with one line of output. That is the second limitation of the CMD_EXEC checks. When the compliance check plugin does the comparison of the command output to the expect keyword value, it only looks at the first line of the command output. I used two workarounds. • The first workaround is the obvious one. You can pipe multiple commands to get the desired results. This works well if the final command gives one line of output. • The second workaround is to use Perl one-liners. Perl one-liners allows you to “compress” multiple lines of text into a single line of output. You can use a Perl one-liners when the output of the command has multiple lines of output. Or when you need to examine an XML-base Apple binary property list file (plist) where the configuration setting information is on multiple lines. You can also use the Perl oneliners to examine the command output when it is too complex to examine with a simple regular expression. You can use any scripting language for these checks, like Ruby or python, if you can create the same functionality on one line in those languages. Now let’s look at some examples. 8 The first example is a relatively simple command execution check. This example compliance check verifies that a password is required to be entered to boot the machine. This is an example of a command that produces multiple lines of output but the data that needs to be examined is on one line. For this check the type keyword is set to CMD_EXEC. Again, this type of check requires that you specify a unique value for the description keyword. The other two required keywords are cmd and expect. The cmd keyword value is the exact command that needs to be run to get the expected results. For this example, the nvram command is used to get or set firmware NVRAM variables. The “–p” option lists all of the NVRAM variables. The output is piped through grep to search for the line containing the “security-mode” NVRAM variable. The expected output is the NVRAM variable name followed by any number of any characters (indicated by the “.*” combination) and then the desired value of “command.” For the cmd keyword, you have to put the exact command line inside double-quotes. Any double quotes or back slashes you need to use in the command line itself you must escape by with a backslash. We will see this in the complex command execution examples. 9 This example is another simple command execution compliance check. Apple stores some configuration information in Apple binary property list (plist) files. You have to use the defaults command line tool to get or set the variables stored in the files. This compliance check verifies the Mac OS X automatic logon feature has been disabled. In this example, the defaults command is used to read in the /Library/ Preferences/.GlobalPreferences plist file and print out the value of the com.apple.userpref.DisableAutoLogin variable. The expected results is a value of 1, which is the value if the automatic logins are disabled. If automatic logins are not disabled, the value returned would be 0. Now let’s look at some complex examples of command execution compliance checks. 10 In this example compliance check, we are checking whether the Apache httpd daemon is configured to start on boot. The Apache configuration stored in an XML-based Apple property list (plist) file. These files are text files but the setting name and the corresponding value are stored on different lines in the text so you can’t use simple FILE_CONTENT checks. The contents of the plist file for the check on the above are listed below. You can see the Disabled key and its value, “true” are different lines. rick$ cat /System/Library/LaunchDaemons/org.apache.httpd.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http:// www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabled</key> <true/> <key>Label</key> <string>org.apache.httpd</string> <key>OnDemand</key> <false/> … </dict> </plist> 11 To handle these files, you can use Perl one-liners to find the value of the setting and create the single line of output that can be checked by the Nessus compliance check engine. The Perl command line options you need to use and understand are: -0777 Puts Perl in to “file slurp” mode. Perl will read in the entire file as one line into the input record. -e Allows you to define Perl code to be executed by the compiler, that is, create a one-liner. -n Creates an implicit loop. It loops around your -e code so it will read all of the files given on the command line a line at a time. -l Causes Perl to automatically chomp the input record (remove the line feed and carriage return characters) This example check is an if-else conditional that looks for the desired key with the correct value using a regular expression. If it is found, “Disabled” or “Service Enabled” is printed as output. The compliance check looks for “Disabled” as the output. This is a good example of escaping double quotes and back slashes in the command line. (Yes, the Perl code can be written in other ways to do the same check in less space but this way it is readable by people who aren’t familiar with Perl.) 12 This example is one of the more complex compliance checks I implemented. The CIS benchmark requires that a banner with organization defined content is set for the OpenSSH daemon, sshd. This check does two things: checks the /etc/sshd_config file for a banner being configured and checks the banner file content. To create the configuration check command, I used two command line tools and two Perl one-liners. The first step is using grep to find the Banner configuration line in the sshd_config file. rick$ grep -E '^Banner' /etc/sshd_config Banner /etc/motd Then cut is used to get the banner file name out of the Banner line from the sshd_config file. rick$ grep -E '^Banner' /etc/sshd_config | cut -d " " -f2 /etc/motd The third step, and the first Perl one-liner, uses a system call to list the contents of the banner file, in this example /etc/motd. rick$ grep -E '^Banner' /etc/sshd_config | cut -d " " -f2 | \ perl -nle 'system("cat", $_);' !!Authorized Uses ONLY!! All activity may be monitored and reported. 13 The last step is to concatenate the contents of the banner file into one line as the output for the compliance check engine. rick$ grep -E '^Banner' /etc/sshd_config | cut -d " " -f2 | \ perl -nle 'system("cat", $_);’ | \ perl -0777 -ne 's/\n//g;s/\r//g;print;' !!Authorized Uses ONLY!!All activity may be monitored and reported. The expect keyword is written to match on this value. NOTE: This is the banner text that I used as an example for my GIAC GSNA technical paper. This check needs to be customized for your organization’s approved banner text. 14 The first step in configuring the scan policy in Nessus is ensuring the correct plugins are enabled. On the Plugin Selections tab, enabling the “MacOS X Local Checks” family ensures Nessus logs in to the target machines to login via OpenSSH to check the configuration of the machine from the inside. The local security checks are a prerequisite for the compliance checks. Under the Policy Compliance family, enabling the Unix Compliance Checks enables the compliance check plugin. Both of these should be enabled by default in a new scan policy. 15 On the Credentials tab, you need to supply ssh credentials for an admin account in order for the Nessus server to remotely login to the Mac OS X target machines and conduct the local security checks. You can specify either a username and password or a set of SSH publicprivate keys to login to the remote machines. Nessus prefers root logins to do the checks but since the root user is disabled by default on Mac OS X, you also need to supply sudo credentials. On the Advanced tab, select Unix Compliance from the pull-down menu. Then enter the .audit files. NOTE: The instructions above assume you are using NessusClient to connect to a Nessus server that was registered with a ProfessionalFeed License and has updated plugins. NOTE: If Nessus fails to conduct the local security checks, verify you have entered the correct credentials and that Remote Login is enabled and allowed through any firewall. Test by establishing an ssh connection into the target from the Nessus server using the same credentials. NOTE: If you don’t see the Policy Compliance category of plugins, then you probably don’t have a ProfessionalFeed license. You can also look for the unix_compliance_check.nbin, compliance_check.nbin, and compliance_check_windows_file_content.nbin files in the directory where your plugins are stored. These “nbin” files are compiled Nessus plugins as opposed to the standard Nessus Attack Script Language (NASL) plugins. The complied plugins contain Tenable Security’s proprietary code. 16 I designed my test setup with the goals of testing each check completely as possible and also as fast as possible. To do that, I used two targets, one configured to pass the check and one to fail the check. If possible, I used the default configuration as one of the configurations for testing. To minimize the number of findings while I was testing, both targets were patched up to Mac OS X v10.5.5, which was the latest version when I was testing. I created a Nessus Audit Admin account on both machines. For hardware, I also needed to check configurations on the PowerPC-based and Intelbased Macs. My two test targets were a MacBook Pro 15 (Intel-based) and a PowerMac G4 867MHz (PowerPC-based). Using the old PowerMac gave me a machine that did not have an iSight camera and Bluetooth installed. For some configuration checks, the configuration of the machines was switched to verify that each machine could pass For Nessus, I used NessusClient 3.2.1 on a MacBook Pro 17, also running Mac OS X v10.5.5. The Nessus server version 3.2.1 was running on a Dell Latitude D600 running openSuSE 11.0 Linux. The Nessus server was registered with a ProfessionalFeed license. For testing new compliance checks, I used a test .audit file containing only one compliance check. Each compliance check was tested by itself to ensure that the check failed or passed on the appropriate machine. After running a Nessus scan against the two machines, the results were filtered for the Plugin ID of the UNIX compliance checks plugin, 21157. The complex command execution compliance checks required multiple iterations. Starting out in a Terminal window on one of the targets, the command line with the Perl oneliner is written and tested iteratively until the check worked. The command line testing also helped determine the value for the expect keyword. Once the one-liner worked on one target, the compliance check was added to the test .audit file. Then both targets were scanned, the results checked. Then the Perl one-liner or the expect keyword value would be modified. The cycle repeated until the check worked correctly on both machines. 17 In this presentation, we covered how to write a number of different types of Nessus compliance checks. Built-in checks can be used for some benchmark items, but most of the items require a custom compliance check. We also covered some techniques to check the configuration settings in a number of different file types with custom compliance checks. And, how to set up a test environment for testing your own compliance checks. Overall, Nessus compliance checks work well for checking the security configuration of Mac OS X machine against the CIS benchmark. Using the techniques in this presentation I was able to write compliance checks to cover 62 benchmarks items, over half of the total items and more than the 51 Scorable items. The majority of the checks I implemented, 50 of 62, were system context items, that is, they check a system wide configuration. The rest were user context items and the check must be run against the configuration of all user accounts. I implemented 12 user context items but they only check the configuration of the user account that Nessus uses to log in. Most of the benchmark items that I couldn’t check completely were in user context. To access the account configuration files, you need to su to each account. I couldn’t find a way to check those items without enabling the superuser, or root, account and providing the root credentials to Nessus. The complete set of .audit files for checking a Mac OS X system against the CIS Benchmark are available from my GIAC GSNA technical paper. Email me at rdsmith@mac.com if you have questions. 18