diff --git a/srg/README.md b/srg/README.md new file mode 100644 index 0000000000000000000000000000000000000000..25e7606862b3fa173d1469f96246d400d42d0039 --- /dev/null +++ b/srg/README.md @@ -0,0 +1,37 @@ + +This directory contains automated checkers for the network's +STIG compliance. The directory is laid out as follows: +``` + srg/ + parse-stigxml.py + os/ + V-3000.sls + ... + other-vuln-id.sls + firewall/ + Vagrant/ + check-stig-pfsense.py + V-3000.py + ... + other-vuln-id.py + db/ + check-stig-db.py + V-3000.sh + ... + other-vuln-id.sh + ... + other_software_to_stig/ +``` + +## Parsing STIG .xml Files +In this directory, there is a script called `parse-stigxml.py`. +Proper usage is `/path/to/parse-stigxml.py <xmlfile>`. +The input is a DISA created .xml file specifying the requirements for a STIG. +The script generates a CSV version of that XML file with +three rows: `V-ID`, `title`, `description`, `fix text`. +However, more output methods can be trivially generated in the future such as +Excel or the backend of a web app that visualizes the network's +STIG compliance status. + +*NOTE* - This script requires xmltodict. You can install the dependency +and any others with `sudo pip3 install -r srg/firewall/requirements.txt` diff --git a/srg/firewall/.gitignore b/srg/firewall/.gitignore index ad21e5296b14e1f97c05708911b901116c8e3098..6deb3a1a2c0b574f30b74715829892c60e32ff12 100644 --- a/srg/firewall/.gitignore +++ b/srg/firewall/.gitignore @@ -1,3 +1,4 @@ *.pyc *.log *.ckl +*.xml diff --git a/srg/firewall/README.md b/srg/firewall/README.md index 8dfce69264119169b6cdaaddd4bb262ca36e054f..d6c31ddd76792b7f7e75445a32e6dbba45b14a20 100644 --- a/srg/firewall/README.md +++ b/srg/firewall/README.md @@ -1,3 +1,60 @@ +This is a guide to using the STIG checker for the pfsense firewall. +All paths here will be relative to the root of the git repo unless otherwise +specified. + +## Generating FIREWALL.ckl (and other template .ckl files) +Download: + 1) the STIG viewer from the DISA website. It is a .jar file. + 2) the `.zip` folder corresponding to your STIG. This should contain + many files but you are primarily interested in the `.xml` in this folder. + +Then, launch the STIG viewer. Import your STIG which is the +`.xml` file in the `.zip` folder . You will then have the +opporunity to export or save your changes in the form of a .ckl file. +Do this and the resulting file is your template .ckl file. + +**IMPORTANT** - Rename this FIREWALL.ckl and place it in srg/firewall. + +## Tool Usage +You can either use check-pfsense-stig.py in a development environment +or in a production environment (on the actual firewall). + +### Development Environment +First, if you have not already make sure to read the guide to setting up +the (development environment)[Vagrant/README.md]. + +Make sure to do a `sudo pip3 install -r requirements.txt` in order +to get the python3 dependencies for this application. + +Start by launching your pfsense virtual machine in virtual box. +If you read and followed the directions in the guide, this should +already be configured properly. + +Then do a `vagrant up` in the folder `srg/firewall/Vagrant/`. +Then `vagrant ssh` in order to get onto the vagrant guest. + +In the vagrant guest terminal, +run `./check-stig-pfsense.py --all --run_ssh` +The output of the command (FIREWALL.ckl) will be placed in the folder containing +this README. +There will also be output to stdout. + +### Prod Environment +Remember to install the python3 dependencies and to do +a git clone of this repository. +Then edit srg/firewall/util.py to make sure the private key +path accurately reflects the path to private key that will allow +you to access root on the pfsense firewall. +Then edit the variable that corresponds to the IP address of the firewall. + +Last, make sure that the public key on your host is added to the +`~/.ssh/authorized_keys` file on the pfsense firewall. +From there you can run `./check-stig-pfsense.py --all --run_ssh` + +## Calculating Current Status of STIG checking developing +Simply run `./status.sh`. This will print out which +vulnerability IDs are In Progress, Not Started, and Done. + ## Firewall Rules [ ] (Rule V-3000)[V-3000.py]: The network device must log all interface access control lists (ACL) deny statements. diff --git a/srg/firewall/Vagrant/.gitignore b/srg/firewall/Vagrant/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8000dd9db47c0b9dd34046ec17880dcbb27e5eb9 --- /dev/null +++ b/srg/firewall/Vagrant/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/srg/firewall/Vagrant/README.md b/srg/firewall/Vagrant/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d8e41525d7d451232024373187ca2c77d8d61300 --- /dev/null +++ b/srg/firewall/Vagrant/README.md @@ -0,0 +1,124 @@ + + +Requirements: Debian-flavored linux, chromium + + +End State: have a development environment +with a virtual network on top of virtual box using +using Vagrant as the configuration manager. +The network specifies a debian machine connected +to a pfsense firewall. +This environment will make developing the STIG checker +for a network firewall (and hopefully future network devices) +easier +```bash +mkdir ~/vta && cd ~/vta +# make sure you have forked vta/saltstack on gitlab +# your gitlab username instead of vta +git clone git@git.cybbh.space:{your username}/saltstack.git +``` + +## Install/Launch Vagrant machine + +First install vagrant and virtual box +Do not do a apt-get install vagrant, you need a newer version. +As for vbox, I think you can do an apt install of vbox, but +if you want the newest, you should install from .deb package +on the vbox website. + +According to your distribution, replace 'xenial' by 'yakkety', 'vivid', 'wheezy', 'squeeze', etc +(`lsb_release -a`). + +```bash +# install vbox +sudo sh -c 'echo "deb http://download.virtualbox.org/virtualbox/debian xenial contrib" >> /etc/apt/sources.list.d/virtualbox.list' +wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - +wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add - +yes | sudo apt-get update +yes | sudo apt install virtualbox-5.1 + +# install vagrant +wget https://releases.hashicorp.com/vagrant/2.0.0/vagrant_2.0.0_x86_64.deb +sudo dpkg -i vagrant_2.0.0_x86_64.deb +sudo apt-get install -f +# install vbox plugin +vagrant plugin install vbox-plugin +# confirm that it is installed +vagrant list plugins +``` + +Now, take a look at `./Vagrantfile`. This specifies +the vagrant box we will be creating and what its network +configuration will be. +In this directory, do a `vagrant up` and `vagrant ssh`. +This will create the box described in `./Vagrantfile` +and then give you a terminal in it via `ssh`. + + +## Install pfsense firewall +We do not have an image of our pfsense router, +so you will have to install and configure from +a pfsense .iso. + +First obtain the pfsense iso: +```bash +wget https://nyifiles.pfsense.org/mirror/downloads/pfSense-CE-2.3.4-RELEASE-amd64.iso.gz +tar -xJvf pfsense-CE-2.3.4-RELEASE-amd64.iso.gz +``` + +Then, in virtualbox, create a FreeBSD machine. +Make sure the machine has two network adapters. +The first one can be either Bridged or NAT'd. +The second one should be on an "Internal Network" type adapter +called "intnet". + +Once the machine has been created, go to settings/storage +for the machine and set the CD drive to point to the pfsense .iso. + +After, a basic graphic install you will be prompted to restart the machine +and remove the .iso from the CD drive. + +This initial installation should provide a LAN with network address +192.168.1.0/24, pfsense LAN interface address at 192.168.1.1. + +## Configuring the pfsense firewall using WebConfigurator +At this point, we can access the web interface of the router through the +LAN interface. But we need to be on the LAN of the firewall. +Our already vagrant machine should be on this LAN already. + +Let's spin up a proxy through our +vagrant machine to access the web interface. +of the firewall. +First, make sure your vagrant machine is still running using +`vagrant status`. +Close all instances of chromium browser. +From the directory that this README is contained in run: + +```bash +./chrome-socks-proxy-tutorial.sh +``` + +At this point, we have setup a proxy to our (already running, hopefully) +vagrant box. Using that proxy, we access the web configurator +through the chromium (or replace with chrome) browser that the script +should have opened up. + +In your web browser that is using the proxy, browser to https://192.168.1.1. +You will be presented with a login portal. Use the credentials admin:pfsense +to get in. Use this interface to configure the router according to your uses. + +CTL-C on the terminal running the proxy service when you are done. + +## Setting up Firewall for SSH access +You will need to add an authorized key to the admin/root account in order +to allow ssh'ing without a password. +To do this from the web portal go to Settings/Users. Click edit on the admin +user. +Scroll to the bottom where you see the option to add an ssh key. +Add the public key on the vagrant box you have created (`~/.ssh/authorized_keys`) +Or you can execute the following command from the vagrant machine: +```bash +# ssh password is pfsense +scp /home/vagrant/.ssh/authorized_keys root@192.168.1.1:/root/.ssh/authorized_keys +``` + diff --git a/srg/firewall/Vagrant/Vagrantfile b/srg/firewall/Vagrant/Vagrantfile new file mode 100644 index 0000000000000000000000000000000000000000..e397466a929356a2368f25dea1d0b2608ca70176 --- /dev/null +++ b/srg/firewall/Vagrant/Vagrantfile @@ -0,0 +1,35 @@ + + +Vagrant.configure("2") do |config| + #config.vm.box = "debian/contrib-jessie64" + config.vm.box = "debian/contrib-stretch64" + config.vm.box_version = "9.1.0" + + # get the dirname of the stig checking script for firewall (../) + firewall_root = File.dirname(File.dirname(__FILE__)) + # set up shared folder that points to script STIG script + config.vm.synced_folder firewall_root, "/stig" + + # configure networking + router_ip = "192.168.1.1" + config.vm.network "forwarded_port", guest: 22, host: 12346, id: "ssh" + config.vm.network "private_network", + ip: "192.168.1.5", + network: "192.168.1.0", + broadcast: "192.168.1.255", + gateway: router_ip, + netmask: "255.255.255.0", + virtualbox__intnet: "intnet" + + # install python3 and xmltodict + config.vm.provision "shell", + run: "once", + inline: "apt-get install -y python3 python3-pip && pip3 install xmltodict" + + # finalize networking setup by setting default route to + # interface connected to pfsense firewall + config.vm.provision "shell", + run: "always", + inline: "ip route del default || true; ip route add default via #{router_ip} dev eth1" + +end diff --git a/srg/firewall/Vagrant/chrome-socks-proxy-tutorial.sh b/srg/firewall/Vagrant/chrome-socks-proxy-tutorial.sh new file mode 100755 index 0000000000000000000000000000000000000000..2c082ae173e70d8c931736e996e6a2089f122054 --- /dev/null +++ b/srg/firewall/Vagrant/chrome-socks-proxy-tutorial.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +############### +# Constants +############### +PRIV_KEY=".vagrant/machines/default/virtualbox/private_key" +PROXY_PORT=1090 +CHROME="/opt/google/chrome/chrome" +if [[ ! -e "$CHROME" ]]; then + echo "[-] Could not find Chrome at $CHROME using Chromium" + if [[ -e "`which chromium-browser`" ]]; then + CHROME=`which chromium-browser` + else + echo "[-] Chromium is not installed on this computer" + exit 1 + fi +fi + +ssh -ND $PROXY_PORT vagrant@localhost -p 12346 -i $PRIV_KEY & PROXY_PID="$!" +$CHROME --proxy-server="socks5://localhost:$PROXY_PORT" +kill $PROXY_PID diff --git a/srg/firewall/Vagrant/copy-keys.sh b/srg/firewall/Vagrant/copy-keys.sh new file mode 100755 index 0000000000000000000000000000000000000000..72fbee60cf22e467142c9e3b74760b58abb802cb --- /dev/null +++ b/srg/firewall/Vagrant/copy-keys.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +scp /home/vagrant/.ssh/authorized_keys root@192.168.1.1:/root/.ssh/authorized_keys diff --git a/srg/firewall/Vagrant/get-configs.sh b/srg/firewall/Vagrant/get-configs.sh new file mode 100755 index 0000000000000000000000000000000000000000..d8a177a4d359932debc44ebfcc86a663a7127fc1 --- /dev/null +++ b/srg/firewall/Vagrant/get-configs.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# this is a script to be run on vagrant machine that gets the config +# files from the pfsense firewall. These can be inspected by the developer +# offline to help develop rules for parsing these configs +ROUTER_IP="192.168.1.1" +PRIV_KEY="/vagrant/.vagrant/machines/default/virtualbox/private_key" +CONFIG="/cf/conf/config.xml" +CONFIG_DEF="/conf.default/config.xml" + +scp -i $PRIV_KEY root@$ROUTER_IP:$CONFIG /vagrant/config-cf.xml +scp -i $PRIV_KEY root@$ROUTER_IP:$CONFIG_DEF /vagrant/config-default.xml diff --git a/srg/firewall/check-stig-pfsense.py b/srg/firewall/check-stig-pfsense.py index 541030fbcc1f80bdb91bef63d73ac989bf690304..1e1decb4ba4d09d04ea946bcb4a64a86624d7bcd 100755 --- a/srg/firewall/check-stig-pfsense.py +++ b/srg/firewall/check-stig-pfsense.py @@ -8,8 +8,9 @@ import shutil # custom made python module with helper methods import util +# run from script dir SCRIPT_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) - +os.chdir(SCRIPT_DIR) def sanitize(s): return s.replace("%", "%%") @@ -28,16 +29,18 @@ def print_findings(vuln, xml_out, findings): perl -i -0pe 's/(?<=$ENV{vuln})(.*?)<STATUS>Not_Reviewed<\/STATUS>/$1<STATUS>NotAFinding<\/STATUS>/s' $checklist ''' # logging.info('Findings : {}\n'.format(findings)) - comments = "perl -i -0pe 's/(?<={})(.*?)<COMMENTS><\/COMMENTS>/$1<COMMENTS>{}<\/COMMENTS>/s' {}" - finding_details = "perl -i -0pe 's/(?<={})(.*?)<FINDING_DETAILS><\/FINDING_DETAILS>/$1<FINDING_DETAILS>{}<\/FINDING_DETAILS>/s' {}" + comments = "perl -i -0pe 's/(?<={})(.*?)<COMMENTS><\/COMMENTS>/$1<COMMENTS>$ENV{{comments}}<\/COMMENTS>/s' {}" + finding_details = "perl -i -0pe 's/(?<={})(.*?)<FINDING_DETAILS><\/FINDING_DETAILS>/$1<FINDING_DETAILS>$ENV{{details}}<\/FINDING_DETAILS>/s' {}" status = "perl -i -0pe 's/(?<={})(.*?)<STATUS>Not_Reviewed<\/STATUS>/$1<STATUS>{}<\/STATUS>/s' {}" - os.system(comments.format(vuln, findings, xml_out)) + os.environ["comments"] = findings.msg + os.environ["details"] = findings.msg + os.system(comments.format(vuln, xml_out)) if findings.finding != util.PASS: print(findings, file=sys.stderr) - os.system(finding_details.format(vuln, findings, xml_out)) + os.system(finding_details.format(vuln, xml_out)) os.system(status.format(vuln, "Open", xml_out)) else: - # print(findings, file=sys.stdout) + print(findings, file=sys.stdout) print("NotAFinding", file=sys.stdout) os.system(status.format(vuln, "NotAFinding", xml_out)) diff --git a/srg/firewall/requirements.txt b/srg/firewall/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..524b92961ceb81e342e730681e7052b0723972f8 --- /dev/null +++ b/srg/firewall/requirements.txt @@ -0,0 +1 @@ +xmltodict==0.11.0 diff --git a/srg/firewall/util.py b/srg/firewall/util.py index 6902f176c500637a660eae1b952a204c5c378b08..b13efe949cd988d7e5a664d13aab4fec6b96c4a3 100644 --- a/srg/firewall/util.py +++ b/srg/firewall/util.py @@ -93,10 +93,12 @@ def check_artifact(cmd, artifact, # artifact but we still want to show the output. # For example, rule, V-3062 which shows that passwords are not # stored in the clear + out_with_context = ProcessOut("root$ {}\n".format(cmd) + out.stdout, + out.stderr) if no_artifact: - return (PASS, out) + return (PASS, out_with_context) if out.stdout == artifact: - return (PASS, out) + return (PASS, out_with_context) else: - return (FAIL, out) + return (FAIL, out_with_context)