From 6b27ecd4a18e531286faa6215078f2bb49df01d3 Mon Sep 17 00:00:00 2001
From: Frederick Ulrich <frederick.r.ulrich.mil@mail.mil>
Date: Fri, 22 Sep 2017 14:25:37 -0400
Subject: [PATCH] added documentation of work

---
 srg/README.md                                 |  37 ++++++
 srg/firewall/.gitignore                       |   1 +
 srg/firewall/README.md                        |  57 ++++++++
 srg/firewall/Vagrant/.gitignore               |   1 +
 srg/firewall/Vagrant/README.md                | 124 ++++++++++++++++++
 srg/firewall/Vagrant/Vagrantfile              |  35 +++++
 .../Vagrant/chrome-socks-proxy-tutorial.sh    |  21 +++
 srg/firewall/Vagrant/copy-keys.sh             |   3 +
 srg/firewall/Vagrant/get-configs.sh           |  12 ++
 srg/firewall/check-stig-pfsense.py            |  15 ++-
 srg/firewall/requirements.txt                 |   1 +
 srg/firewall/util.py                          |   8 +-
 12 files changed, 306 insertions(+), 9 deletions(-)
 create mode 100644 srg/README.md
 create mode 100644 srg/firewall/Vagrant/.gitignore
 create mode 100644 srg/firewall/Vagrant/README.md
 create mode 100644 srg/firewall/Vagrant/Vagrantfile
 create mode 100755 srg/firewall/Vagrant/chrome-socks-proxy-tutorial.sh
 create mode 100755 srg/firewall/Vagrant/copy-keys.sh
 create mode 100755 srg/firewall/Vagrant/get-configs.sh
 create mode 100644 srg/firewall/requirements.txt

diff --git a/srg/README.md b/srg/README.md
new file mode 100644
index 00000000..25e76068
--- /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 ad21e529..6deb3a1a 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 8dfce692..d6c31ddd 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 00000000..8000dd9d
--- /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 00000000..d8e41525
--- /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 00000000..e397466a
--- /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 00000000..2c082ae1
--- /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 00000000..72fbee60
--- /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 00000000..d8a177a4
--- /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 541030fb..1e1decb4 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 00000000..524b9296
--- /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 6902f176..b13efe94 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)
 
-- 
GitLab