Generating OVAL documents with genoval.sh
1.
OVAL and genoval.sh
Introduction
While developing a security guide for Gentoo (Hardened), I chose to use the OVAL
and XCCDF formats as defined by NIST. These formats, although not GuideXML,
allow for integration with other security-related tools.
One huge advantage of XCCDF and OVAL, compared to regular documents, is that
they allow for the definitions to be executed by tools that are compatible with
the SCAP language. In other words, you can have your system checked (as far as
possible) against the content of the document. The disadvantage however is that
this requires a lot of XML code which makes it quite difficult to read
and maintain.
The genoval.sh script, documented here, helps a bit in the maintenance of
such documents. It translates more readable lines into OVAL XML code.
Code Listing 1.1: Example translation result |
sysctl net.ipv4.ip_forward must be 0 [rule-sysctl-ipv4-forward]
<Rule id="rule-sysctl-ipv4-forward">
<title>sysctl net.ipv4.ip_forward must be 0</title>
<description>sysctl net.ipv4.ip_forward must be 0</description>
<fix>echo 0 > /proc/sys/net/ipv4/ip_forward</fix>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
<check-content-ref name="oval:org.gentoo.dev.swift:def:21" href="scap-gentoo-oval.xml" />
</check>
</Rule>
<definition class="compliance" id="oval:org.gentoo.dev.swift:def:21" version="1">
<metadata>
<title>sysctl net.ipv4.ip_forward must be 0</title>
<description>sysctl net.ipv4.ip_forward must be 0</description>
</metadata>
<criteria>
<criterion test_ref="oval:org.gentoo.dev.swift:tst:21" comment="sysctl net.ipv4.ip_forward must be 0" />
</criteria>
</definition>
...
<ind-def:textfilecontent54_test id="oval:org.gentoo.dev.swift:tst:21" version="1" check="at least one" comment="sysctl net.ipv4.ip_forward must be 0" check_existence="at_least_one_exists">
<ind-def:object object_ref="oval:org.gentoo.dev.swift:obj:6" />
<ind-def:state state_ref="oval:org.gentoo.dev.swift:ste:18" />
</ind-def:textfilecontent54_test>
...
<ind-def:textfilecontent54_object id="oval:org.gentoo.dev.swift:obj:6" version="1" comment="Non-comment lines in /proc/sys/net/ipv4/ip_forward">
<ind-def:filepath>/proc/sys/net/ipv4/ip_forward</ind-def:filepath>
<ind-def:pattern operation="pattern match">^[[:space:]]*([^#[:space:]].*[^[:space:]]?)[[:space:]]*$</ind-def:pattern>
<ind-def:instance datatype="int" operation="greater than or equal">1</ind-def:instance>
</ind-def:textfilecontent54_object>
...
<ind-def:textfilecontent54_state id="oval:org.gentoo.dev.swift:ste:18" version="1" comment="The match of 0">
<ind-def:subexpression operation="pattern match">0</ind-def:subexpression>
</ind-def:textfilecontent54_state>
|
As you can see, the single line expands into more than 30 lines across two
documents. Now, the OVAL language is very powerful so for more complex
activities, it is imo no problem to manually sift through it. But for generic
tests (like regular expression matches of files or variables) this can better be
automated. And that's the purpose of genoval.sh.
Setting up genoval.sh
To setup genoval, you can git clone from my "small.coding" repository.
The genoval code is in the subdirectory called genoval (har har).
Code Listing 1.2: Getting genoval.sh |
$ git clone http://github.com/sjvermeu/small.coding.git
|
Edit the Makefile since it points to my personal directories and as
such will probably not work for you ;-)
You will notice that it contains the sources for the Gentoo security benchmark
as well. Consider that a nice example to work from ;-)
Defining the rules
Start by defining the rules that you want to check for. The file is called
definitions.conf and currently supports the following definition
lines (the highlighted parts can be changed to your liking):
Code Listing 1.3: Example definitions.conf |
/home is a separate file system [rule-partition-home]
/tmp is a separate file system of type tmpfs [rule-partition-tmp]
mount point /home is mounted with nosuid option [rule-home-mount-nosuid]
file /etc/ssh/sshd_config must have a line that matches ^PermitRootLogin.*no [rule-sshd-norootlogin]
file /etc/ssh/sshd_config may not have a line that matches ^UsePAM.*yes [rule-sshd-nousepam]
sysctl net.ipv4.ip_forward must be 0 [rule-sysctl-ipv4-forward]
gentoo variable USE must contain pam [rule-gentoo-use-pam]
gentoo variable GCC_SPECS must be [rule-gentoo-gccspecs-empty]
gentoo profile must contain hardened [rule-gentoo-profile-hardened]
kernel config CONFIG_GRKERNSEC_TPE must be y [rule-kernel-grsec-tpe]
kernel config CONFIG_GRKERNSEC_USER must be enabled [rule-kernel-grsec-user]
kernel config CONFIG_GRKERNSEC_IGNOREMRE must not be set [rule-kernel-grsec-ignoremre]
|
The lines contain information how the system should be. It always ends
with the rule name between [ and ].
Editing the XCCDF file
The XCCDF file contains the benchmark document itself (the guide that describes
to the user how to harden his system). To use XCCDF with genoval.sh, edit
the scap-gentoo-xccdf.xml.template file (if you use your own XML
files, make sure it ends with -xccdf.xml.template). The purpose of
genoval.sh here is to automatically generate Rule definitions, which you
can do as follows:
Code Listing 1.4: Snippet from XCCDF for genoval |
<Group id="gt-system-kernel-sysctl-ipv4forward">
<title>Disable IPv4 Forwarding</title>
<description>
The <h:code>net.ipv4.ip_forward</h:code> sysctl setting controls if
IP forwarding is allowed or not on the system.
<h:br />
<h:br />
Unless the system is used as a router or gateway, IPv4 forwarding
should be disabled.
</description>
<!-- @@GEN START rule-sysctl-ipv4-forward -->
<!-- @@GEN END rule-sysctl-ipv4-forward -->
</Group>
|
The @@GEN START rule-sysctl-ipv4-forward and the END one are
important here: between these lines, genoval.sh will insert the necessary
Rule code. The name (rule-sysctl-ipv4-forward) is taken from the
definitions.conf file.
Make sure that you add a select line in the beginning of the document on
the Profile:
Code Listing 1.5: Adding a select line for rule-sysctl-ipv4-forward |
<Profile id="Gentoo-Default">
...
<select idref="rule-sysctl-ipv4-forward" selected="true" />
</Profile>
|
Editing the OVAL file
The OVAL content is automatically generated from the
scap-gentoo-oval.xml.template file, which contains the necessary
placeholders between which genoval.sh will generate the necessary lines.
If you need to add your own OVAL statements, just edit this template file but
never between the START and END statements for genoval.sh!
Also, make sure that the name of the file is similar to the XCCDF one, just with
oval instead of xccdf in the name.
Calling genoval.sh
To execute the magic, call genoval.sh with three arguments:
-
Name of the XCCDF template file (currect directory)
-
Namespace to use for the OVAL ids (like "org.gentoo.dev.swift")
-
Directory in which to save the results
For instance:
Code Listing 1.6: Calling genoval.sh |
$ ./genoval.sh scap-gentoo-xccdf.xml.template org.gentoo.dev.swift .
File scap-gentoo-oval.xml already exists. Renaming to scap-gentoo-oval.xml.20111223134826.607527446
Loading in ./lib/00-lib-gentoo.sh...
Loading in ./lib/00-lib-sysctl.sh...
Loading in ./lib/99-lib-fix.sh...
Loading in ./lib/99-lib-general.sh...
|
The genoval.sh script does not just overwrite an existing OVAL file. Instead,
it makes a backup first. I do this because I might want to check the differences
during development.
Once generated, you can execute the following to generate a report as well as
guide:
Code Listing 1.7: Running XCCDF/OVAL content |
# emerge --info --verbose > emerge-info-verbose
# zcat /proc/config.gz > kernel-config || cp /usr/src/linux/.config # kernel-config
# export GENOVAL_SCRIPTOUTPUTDIR=$(pwd)
# oscap xccdf generate guide scap-gentoo-xccdf.xml > guide.html
# oscap xccdf eval --oval-results --profile Gentoo-Default --results xccdf-results.xml --report report.html
# oscap xccdf generate fix --result-id OSCAP-Test-Gentoo-Profile xccdf-results.xml > fixscript.sh
|
|