Compiling an up-to-date Standalone EXE of Volatility 2.6 in Windows

The Windows standalone exe version of Volatility 2.6 at https://www.volatilityfoundation.org/releases does not seem to contain all the latest Windows 10 profiles that are in the latest python source. All is not lost, you can compile your own standalone executable by following these simple steps.

Volatility 2.6 only works with Python 2.7 (and earlier) and ensure you download the 64 Bit version of the various installers.

  1. Install Python 2.7 – https://www.python.org/downloads/release/python-2717/ – Ensure you select the option to add python to your path.
  2. Install Visual C++ Compiler Package for Python – https://www.microsoft.com/en-gb/download/details.aspx?id=44266
  3. Install Visual C++ 2008 (x64) Redistributable – https://www.microsoft.com/en-gb/download/details.aspx?id=15336

At this point you may want to reboot to ensure everything is updated correctly.

4. Install PIL – you can find a link to the 64 Bit Install package at https://stackoverflow.com/questions/19244057/obtaining-pil-instead-of-pillow-for-python-2-7-64-bit-on-windows

5. Install PyCrypto – http://www.voidspace.org.uk/python/pycrypto-2.6.1/

6. Install Yara-Python – https://github.com/VirusTotal/yara-python/releases

7. Install Distorm3 – https://github.com/gdabah/distorm/releases/tag/v3.3.4

8. Once those installs are done launch Python and install OpenPyxl and Pyinstaller. With regards to Pyinstaller, I had issues with 3.6 so use 3.5 instead:

pip install OpenPyxl

pip install pyinstaller==3.5

9. Download and extract latest version of UPX – https://github.com/upx/upx/releases – this helps keep the size of the exe as small as possible. You will need to supply the path to the directory containing the UPX exe in the pyinstaller command.

10. Download and extract the latest version of volatility – https://github.com/volatilityfoundation/volatility

11. Then finally change in to the volatility directory and compile the exe:

pyinstaller –onefile –upx-dir /path/to/upx/directory pyinstaller.spec

When that is all complete you should have a compiled standalone version of Volatility in the dist folder. You can now run Volatility from the command line in Windows.

volatility.exe –info
Volatility Foundation Volatility Framework 2.6.1

Profiles

VistaSP0x64 – A Profile for Windows Vista SP0 x64
VistaSP0x86 – A Profile for Windows Vista SP0 x86
VistaSP1x64 – A Profile for Windows Vista SP1 x64
VistaSP1x86 – A Profile for Windows Vista SP1 x86
VistaSP2x64 – A Profile for Windows Vista SP2 x64
VistaSP2x86 – A Profile for Windows Vista SP2 x86
Win10x64 – A Profile for Windows 10 x64
Win10x64_10240_17770 – A Profile for Windows 10 x64 (10.0.10240.17770 / 2018-02-10)
Win10x64_10586 – A Profile for Windows 10 x64 (10.0.10586.306 / 2016-04-23)
Win10x64_14393 – A Profile for Windows 10 x64 (10.0.14393.0 / 2016-07-16)
Win10x64_15063 – A Profile for Windows 10 x64 (10.0.15063.0 / 2017-04-04)
Win10x64_16299 – A Profile for Windows 10 x64 (10.0.16299.0 / 2017-09-22)
Win10x64_17134 – A Profile for Windows 10 x64 (10.0.17134.1 / 2018-04-11)
Win10x64_17763 – A Profile for Windows 10 x64 (10.0.17763.0 / 2018-10-12)
Win10x64_18362 – A Profile for Windows 10 x64 (10.0.18362.0 / 2019-04-23)
Win10x86 – A Profile for Windows 10 x86
Win10x86_10240_17770 – A Profile for Windows 10 x86 (10.0.10240.17770 / 2018-02-10)
Win10x86_10586 – A Profile for Windows 10 x86 (10.0.10586.420 / 2016-05-28)
Win10x86_14393 – A Profile for Windows 10 x86 (10.0.14393.0 / 2016-07-16)
Win10x86_15063 – A Profile for Windows 10 x86 (10.0.15063.0 / 2017-04-04)
Win10x86_16299 – A Profile for Windows 10 x86 (10.0.16299.15 / 2017-09-29)
Win10x86_17134 – A Profile for Windows 10 x86 (10.0.17134.1 / 2018-04-11)
Win10x86_17763 – A Profile for Windows 10 x86 (10.0.17763.0 / 2018-10-12)
Win10x86_18362 – A Profile for Windows 10 x86 (10.0.18362.0 / 2019-04-23)
Win2003SP0x86 – A Profile for Windows 2003 SP0 x86
Win2003SP1x64 – A Profile for Windows 2003 SP1 x64
Win2003SP1x86 – A Profile for Windows 2003 SP1 x86
Win2003SP2x64 – A Profile for Windows 2003 SP2 x64
Win2003SP2x86 – A Profile for Windows 2003 SP2 x86
Win2008R2SP0x64 – A Profile for Windows 2008 R2 SP0 x64
Win2008R2SP1x64 – A Profile for Windows 2008 R2 SP1 x64
Win2008R2SP1x64_23418 – A Profile for Windows 2008 R2 SP1 x64 (6.1.7601.23418 / 2016-04-09)
Win2008R2SP1x64_24000 – A Profile for Windows 2008 R2 SP1 x64 (6.1.7601.24000 / 2016-04-09)
Win2008SP1x64 – A Profile for Windows 2008 SP1 x64
Win2008SP1x86 – A Profile for Windows 2008 SP1 x86
Win2008SP2x64 – A Profile for Windows 2008 SP2 x64
Win2008SP2x86 – A Profile for Windows 2008 SP2 x86
Win2012R2x64 – A Profile for Windows Server 2012 R2 x64
Win2012R2x64_18340 – A Profile for Windows Server 2012 R2 x64 (6.3.9600.18340 / 2016-05-13)
Win2012x64 – A Profile for Windows Server 2012 x64
Win2016x64_14393 – A Profile for Windows Server 2016 x64 (10.0.14393.0 / 2016-07-16)
Win7SP0x64 – A Profile for Windows 7 SP0 x64
Win7SP0x86 – A Profile for Windows 7 SP0 x86
Win7SP1x64 – A Profile for Windows 7 SP1 x64
Win7SP1x64_23418 – A Profile for Windows 7 SP1 x64 (6.1.7601.23418 / 2016-04-09)
Win7SP1x64_24000 – A Profile for Windows 7 SP1 x64 (6.1.7601.24000 / 2018-01-09)
Win7SP1x86 – A Profile for Windows 7 SP1 x86
Win7SP1x86_23418 – A Profile for Windows 7 SP1 x86 (6.1.7601.23418 / 2016-04-09)
Win7SP1x86_24000 – A Profile for Windows 7 SP1 x86 (6.1.7601.24000 / 2018-01-09)
Win81U1x64 – A Profile for Windows 8.1 Update 1 x64
Win81U1x86 – A Profile for Windows 8.1 Update 1 x86
Win8SP0x64 – A Profile for Windows 8 x64
Win8SP0x86 – A Profile for Windows 8 x86
Win8SP1x64 – A Profile for Windows 8.1 x64
Win8SP1x64_18340 – A Profile for Windows 8.1 x64 (6.3.9600.18340 / 2016-05-13)
Win8SP1x86 – A Profile for Windows 8.1 x86
WinXPSP1x64 – A Profile for Windows XP SP1 x64
WinXPSP2x64 – A Profile for Windows XP SP2 x64
WinXPSP2x86 – A Profile for Windows XP SP2 x86
WinXPSP3x86 – A Profile for Windows XP SP3 x86

Installing HAProxy 2.0.8 with TLS 1.3 Support and Modsecurity on CentOS 7.6

So this is something I have been battling with for a little while and finally seem to have a robust set of deployment steps for CentOS. It might not be the best way to do it, but it is the way that I have done it. I love HAProxy as it is lightweight, versatile and reliable. This implementation is being used in front of a number of Azure resources and enhances security via the adjusted Ciphers/Protocols.

I struggled quite a bit getting modsecurity to compile with LUA support but finally managed to get that sorted. And whilst a lot of sites seem to cover individual portions of this , I thought it would be good to lay it all out for you. So here we go …….

So the starting point for this deployment is a clean CentOS build, i tend to go for a minimal CentOS installation as I do not want unwanted services and applications on my environment. This helps with your security posture.

First things to install are the EPEL Repo, Development tools and a bunch of pre-reqs for compiling HAProxy and Modsecurity:

yum -y install epel-release
yum -y update
yum -y groupinstall "Development Tools"
yum -y install openssl openssl-devel perl pcre-devel zlib-devel systemd-devel wget net-tools libxml2 libxml2-devel expat-devel httpd-devel curl-devel yajl-devel libevent libevent-devel readline-devel ssdeep ssdeep-devel

Next install the IUS Repository and the LUA 5.3 package:

yum -y install https://centos7.iuscommunity.org/ius-release.rpm
yum -y install lua53u lua53u-devel

Download and extract the latest version of OpenSSL:

cd /usr/src

wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz
tar xfvz openssl-1.1.1d.tar.gz

Configure OpenSSL to use a custom install path and shared library, then install:

cd openssl-1.1.1d
./config --prefix=/opt/openssl-1.1.1d shared
make
make install
cd ..

Update the system library path information so it knows where to find the OpenSSL 1.1.1d libraries:

echo /opt/openssl-1.1.1d/lib > /etc/ld.so.conf.d/openssl-1.1.1d.conf
ldconfig -v

Before we start on the HAProxy install, you need to make a patch file that makes some adjustments to the HAProxy Modsecurity contrib Makefile so it works with CentOS and Modsecurity 2.9.3.

Create a file in /tmp called contrib_modsec_makefile.patch and put the following in it:

--- Makefile	2019-10-23 07:06:13.000000000 +0100
+++ /root/contrib_modsec_Makefile	2019-11-01 14:09:51.537626204 +0000
@@ -6,19 +6,19 @@
 LD = $(CC)
 
 ifeq ($(MODSEC_INC),)
-MODSEC_INC := modsecurity-2.9.1/INSTALL/include
+MODSEC_INC := modsecurity-2.9.3/INSTALL/include
 endif
 
 ifeq ($(MODSEC_LIB),)
-MODSEC_LIB := modsecurity-2.9.1/INSTALL/lib
+MODSEC_LIB := modsecurity-2.9.3/INSTALL/lib
 endif
 
 ifeq ($(APACHE2_INC),)
-APACHE2_INC := /usr/include/apache2
+APACHE2_INC := /usr/include/httpd
 endif
 
 ifeq ($(APR_INC),)
-APR_INC := /usr/include/apr-1.0
+APR_INC := /usr/include/apr-1
 endif
 
 ifeq ($(LIBXML_INC),)
@@ -35,7 +35,7 @@
 
 CFLAGS  += -g -Wall -pthread
 INCS += -I../../include -I../../ebtree -I$(MODSEC_INC) -I$(APACHE2_INC) -I$(APR_INC) -I$(LIBXML_INC) -I$(EVENT_INC)
-LIBS += -lpthread  $(EVENT_LIB) -levent_pthreads -lcurl -lapr-1 -laprutil-1 -lxml2 -lpcre -lyajl
+LIBS += -lpthread  $(EVENT_LIB) -levent_pthreads -lcurl -lapr-1 -laprutil-1 -lxml2 -lpcre -lyajl -llua-5.3 -lfuzzy
 
 OBJS = spoa.o modsec_wrapper.o

Ok back to it. Making sure your are in /usr/src, download the latest version of HAProxy, check the checksum and once that is done, extract it. Then navigate to the modsecurity contributions folder:

wget https://www.haproxy.org/download/2.0/src/haproxy-2.0.8.tar.gz
wget https://www.haproxy.org/download/2.0/src/haproxy-2.0.8.tar.gz.sha256 
sha256sum -c haproxy-2.0.8.tar.gz.sha256
tar xfvz haproxy-2.0.8.tar.gz
cd haproxy-2.0.8/contrib/modsecurity

Next you have to modify the Makefile using the patch created earlier:

patch Makefile < /tmp/contrib_modsec_makefile.patch

Then download and extract modsecurity 2.9.3:

wget https://www.modsecurity.org/tarball/2.9.3/modsecurity-2.9.3.tar.gz
wget https://www.modsecurity.org/tarball/2.9.3/modsecurity-2.9.3.tar.gz.sha256
sha256sum -c modsecurity-2.9.3.tar.gz.sha256
tar xfvz modsecurity-2.9.3.tar.gz
cd modsecurity-2.9.3

The following steps, for config and install, are straight from the contrib/modsecurity README:

./configure --prefix=$PWD/INSTALL --disable-apache2-module --enable-standalone-module --enable-pcre-study --enable-pcre-jit --enable-lua-cache
make
make -C standalone install
mkdir -p $PWD/INSTALL/include
cp standalone/*.h $PWD/INSTALL/include
cp apache2/*.h $PWD/INSTALL/include

cd ..

make
make install

Once the install has finished, it is time to install HAProxy:

cd ../..

mkdir -p /etc/haproxy/cert

make TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 SSL_LIB=/opt/openssl-1.1.1d/lib SSL_INC=/opt/openssl-1.1.1d/include USE_LUA=1 USE_THREAD=1 LUA_LIB=/usr/lib64 LUA_INC=/usr/include/lua-5.3 LUA_LIB_NAME=lua-5.3

make install

id -u haproxy &> /dev/null || useradd -s /usr/sbin/nologin -r haproxy

Next thing to tackle is the OWASP Rules, so download and extract those then rename them to something a little more concise:

cd /opt/
wget https://github.com/SpiderLabs/owasp-modsecurity-crs/zipball/v3.0/master
unzip master
mv SpiderLabs-owasp-modsecurity-crs-a216353 owasp-modsecurity-crs

The recommended method of obtaining the files is to use git, feel free to do so, the above worked fine for me though.

With the rules extracted you need to manipulate a few files:

cd owasp-modsecurity-crs
cp crs-setup.conf.example crs-setup.conf

cd rules

mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf

And copy out a few:

mkdir /opt/modsecurity

cp /usr/src/haproxy-2.0.8/contrib/modsecurity/modsecurity-2.9.3/unicode.mapping /opt/modsecurity/unicode.mapping

cp /usr/src/haproxy-2.0.8/contrib/modsecurity/modsecurity-2.9.3/modsecurity.conf-recommended /opt/modsecurity/modsecurity.conf

In order for modsecurity to know about the CRS config and rules (and avoid a potential issue mentioned in the contrib README) you need to append the following to the end of /opt/modsecurity/modsecurity.conf:

include /opt/owasp-modsecurity-crs/crs-setup.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
include /opt/owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf
include /opt/owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf

There is one other possible change needed to /opt/modsecurity/modsecurity.conf to ensure it can find the unicode.mapping file. Find the section below and ensure it points to the correct location:

# Specify your Unicode Code Point.
# This mapping is used by the t:urlDecodeUni transformation function
# to properly map encoded data to your language. Properly setting
# these directives helps to reduce false positives and negatives.
#
SecUnicodeMapFile /opt/modsecurity/unicode.mapping 20127

As the standalone modsecurity module is based on spoe you need to create a config file. Create /etc/haproxy/spoe-modsecurity.conf containing the following:

[modsecurity]
    spoe-agent modsecurity-agent
        messages     check-request
        option       var-prefix  modsec
        timeout      hello       100ms
        timeout      idle        30s
        timeout      processing  1s
        use-backend  spoe-modsecurity
    spoe-message check-request
        args   unique-id method path query req.ver req.hdrs_bin req.body_size req.body
        event  on-frontend-http-request

The next file to create is your HAProxy config file, so create /etc/haproxy/haproxy.cfg containing your haproxy configuration, mine was:

global
    maxconn 20480
    ssl-dh-param-file /etc/haproxy/dhparam.pem
    log 127.0.0.1 local0
    stats socket 127.0.0.1:14567
    tune.ssl.default-dh-param	2048
    server-state-file /tmp/haproxy_server_state
    ssl-default-bind-options ssl-min-ver TLSv1.2
    ssl-default-server-options ssl-min-ver TLSv1.2
    ssl-default-bind-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256
    ssl-default-server-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256

defaults
    log global
    mode http
    option httplog
    timeout connect 5s
    timeout client  50s
    timeout server 50s
    # Newly added timeouts
    timeout http-request 10s
    timeout http-keep-alive 2s
    timeout queue 5s
    timeout tunnel 2m
    timeout client-fin 1s
    timeout server-fin 1s
	
frontend myfrontend
    # primary cert is /etc/haproxy/cert/haproxy.pem
    bind *:443 ssl crt /etc/haproxy/cert/haproxy.pem alpn h2,http/1.1
    option			http-keep-alive
    option			forwardfor
    acl https ssl_fc
    filter spoe engine modsecurity config /etc/haproxy/spoe-modsecurity.conf
    http-request deny if { var(txn.modsec.code) -m int gt 0 }
    http-request set-header		X-Forwarded-Proto http if !https
    http-request set-header		X-Forwarded-Proto https if https
    timeout client		30000
    acl			ACL1	var(txn.txnhost) -m str -i host.domain.com
    http-request set-var(txn.txnhost) hdr(host)
    use_backend example1  if  ACL1
    
backend spoe-modsecurity
      mode tcp
      balance roundrobin
      timeout connect 5s
      timeout server  3m
      server modsec1 127.0.0.1:12345

backend example1
    # a https backend
    http-response set-header Strict-Transport-Security max-age=31536000;\ includeSubDomains;\ preload;
    http-response set-header X-Frame-Options DENY
    http-response set-header X-XSS-Protection 1;mode=block
    http-response set-header X-Content-Type-Options nosniff
    http-response set-header Referrer-Policy same-origin
    http-response set-header Cache-Control private,\ no-cache,\ no-store,\ max-age=0,\ no-transform,\ must-revalidate
    http-response set-header Pragma no-cache
    http-response del-header Server
    http-response del-header X-Powered-By
    server backendhost backendhost.otherdomain.com:443 ssl verify none

As per the README in the contrib section, the important lines in this from a modsecurity point of view are:

Frontend 
    ....
    filter spoe engine modsecurity config /etc/haproxy/spoe-modsecurity.conf
    http-request deny if { var(txn.modsec.code) -m int gt 0 }
    ....

backend spoe-modsecurity
      mode tcp
      balance roundrobin
      timeout connect 5s
      timeout server  3m
      server modsec1 127.0.0.1:12345

These define the modsecurity spoe filter with associated config file and the backend referenced in that config file.

Once you have done that make sure your certificate for your listener exists as /etc/haproxy/cert/haproxy.pem and set up your Diffie-Hellman parameters file by running:

openssl dhparam -out /etc/haproxy/dhparam.pem 2048

With that completed , we are now in to the home straight. Ideally we need HAProxy and the standalone modsecurity module to run as services. So lets get that sorted.

Created a service file for HAProxy, /lib/systemd/system/haproxy.service , containing the following:

[Unit]
Description=HAProxy Load Balancer
After=network.target

[Service]
Environment=LD_LIBRARY_PATH=/opt/openssl-1.1.1d/lib/
EnvironmentFile=-/etc/default/haproxy
EnvironmentFile=-/etc/sysconfig/haproxy
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock"
ExecStartPre=/usr/local/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS
ExecStart=/usr/local/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS
ExecReload=/usr/local/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=always
SuccessExitStatus=143
Type=notify

[Install]
WantedBy=multi-user.target

Then create a service file for modsecurity, /lib/systemd/system/modsecurity.service, containing the following:

[Unit]
Description=Modsecurity Standalone
After=network.target

[Service]
EnvironmentFile=-/etc/default/modsecurity
EnvironmentFile=-/etc/sysconfig/modsecurity
Environment="CONFIG=/opt/modsecurity/modsecurity.conf" "PIDFILE=/run/modesecurity.pid" "EXTRAOPTS=-d -n 1"
ExecStart=/usr/local/bin/modsecurity $EXTRAOPTS -f $CONFIG
ExecReload=/usr/local/bin/modsecurity $EXTRAOPTS -f $CONFIG
ExecReload=/bin/kill -USR2 $MAINPID
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target

Enable and Start both services by running:

systemctl enable modsecurity.service
systemctl enable haproxy.service
systemctl start modsecurity.service
systemctl start haproxy.service

The HAProxy and modsecurity processes then launch and listen on their respective ports:

[root@localhost modsecurity]# netstat -natp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      13599/haproxy
tcp        0      0 127.0.0.1:14567         0.0.0.0:*               LISTEN      13599/haproxy
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1218/sshd
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1399/master
tcp        0      0 0.0.0.0:12345           0.0.0.0:*               LISTEN      1217/modsecurity

You can then test things work; The initial mode that is configured is Detection Only, which is why the Headers that get added by the backend get returned: :

[root@localhost owasp-modsecurity-crs]# curl -I https://host.domain.com/?../etc/passwd
HTTP/1.1 302 Found
date: Tue, 12 Nov 2019 19:23:15 GMT
content-type: text/html
last-modified: Tue, 12 Nov 2019 19:23:15 GMT
accept-ranges: bytes
location: /?../etc/passwd/
strict-transport-security: max-age=31536000; includeSubDomains; preload;
x-frame-options: DENY
x-xss-protection: 1;mode=block
x-content-type-options: nosniff
referrer-policy: same-origin
cache-control: private, no-cache, no-store, max-age=0, no-transform, must-revalidate
pragma: no-cache

But you can see in the modsecurity logs via journalctl, that the attempted “attack” is being detected:

Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029634 [00] <2> New Client connection accepted and assigned to worker 01
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029691 [01] <2> read_frame_cb
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029700 [01] <2> New Frame of 128 bytes received
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029702 [01] <2> Decode HAProxy HELLO frame
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029705 [01] <2> Supported versions : 2.0
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029708 [01] <2> HAProxy maximum frame size : 16380
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029710 [01] <2> HAProxy capabilities : pipelining,async
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029713 [01] <2> HAProxy supports frame pipelining
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029714 [01] <2> HAProxy supports asynchronous frame
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029716 [01] <2> HAProxy engine id : e24539c7-81b3-481d-955e-0b5dd7c0d77
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029718 [01] <2> Encode Agent HELLO frame
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029720 [01] <2> Agent version : 2.0
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029722 [01] <2> Agent maximum frame size : 16380
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029723 [01] <2> Agent capabilities :
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029730 [01] <2> write_frame_cb
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.029765 [01] <2> Frame of 54 bytes send
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.030338 [01] <2> read_frame_cb
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.030348 [01] <2> New Frame of 128 bytes received
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.030350 [01] <2> Decode HAProxy NOTIFY frame
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.030352 [01] <2> STREAM-ID=3 - FRAME-ID=1 - unfragmented frame received - frag_len=0 - len=128 - offset=7
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.030357 [01] Process frame messages : STREAM-ID=3 - FRAME-ID=1 - length=121 bytes
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.030360 [01] Process SPOE Message 'check-request'
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.033798 [00] [client 127.0.0.1] ModSecurity: Warning. Matched phrase "etc/passwd" at ARGS_NAMES:../etc/passwd. [file "/opt/owasp-modsecurity
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.033910 [00] [client 127.0.0.1] ModSecurity: Warning. Matched phrase "etc/passwd" at ARGS_NAMES:../etc/passwd. [file "/opt/owasp-modsecurity
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.081302 [00] [client 127.0.0.1] ModSecurity: Warning. Operator GE matched 5 at TX:anomaly_score. [file "/opt/owasp-modsecurity-crs/rules/REQ
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.083635 [00] [client 127.0.0.1] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/opt/owasp-modsecurity-crs/r
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.086343 [01] Encode Agent ACK frame
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.086351 [01] STREAM-ID=3 - FRAME-ID=1
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.086353 [01] Add action : set variable code=4294967195
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.086366 [01] <2> write_frame_cb
Nov 12 19:10:31 localhost.localdomain modsecurity[1217]: 1573585831.086408 [01] <2> Frame of 30 bytes send
Nov 12 19:10:33 localhost.localdomain modsecurity[1217]: 1573585833.771641 [01] 1 clients connected
Nov 12 19:10:38 localhost.localdomain modsecurity[1217]: 1573585838.774781 [01] 1 clients connected

In order for things to work correctly you need to enable the engine in /opt/modsecurity/modsecurity.conf:

SecRuleEngine On

And change the default action in /opt/owasp-modsecurity-crs/crs-setup.conf:

# Default: Anomaly Scoring mode, log to error log, log to ModSecurity audit log
# - By default, offending requests are blocked with an error 403 response.
# - To change the disruptive action, see RESPONSE-999-EXCEPTIONS.conf.example
#   and review section 'Changing the Disruptive Action for Anomaly Mode'.
# - In Apache, you can use ErrorDocument to show a friendly error page or
#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
#
#SecDefaultAction "phase:1,log,auditlog,pass"
#SecDefaultAction "phase:2,log,auditlog,pass"

# Example: Anomaly Scoring mode, log only to ModSecurity audit log
# - By default, offending requests are blocked with an error 403 response.
# - To change the disruptive action, see RESPONSE-999-EXCEPTIONS.conf.example
#   and review section 'Changing the Disruptive Action for Anomaly Mode'.
# - In Apache, you can use ErrorDocument to show a friendly error page or
#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
#
# SecDefaultAction "phase:1,nolog,auditlog,pass"
# SecDefaultAction "phase:2,nolog,auditlog,pass"

# Example: Self-contained mode, return error 403 on blocking
# - In this configuration the default disruptive action becomes 'deny'. After a
#   rule triggers, it will stop processing the request and return an error 403.
# - You can also use a different error status, such as 404, 406, et cetera.
# - In Apache, you can use ErrorDocument to show a friendly error page or
#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
#
 SecDefaultAction "phase:1,log,auditlog,deny,status:403"
 SecDefaultAction "phase:2,log,auditlog,deny,status:403"

Then restart modsecurity.

Testing now shows the block:

[root@localhost modsecurity]# curl -I https://host.domain.com/?../etc/passwd
HTTP/1.1 403 Forbidden
content-length: 93
cache-control: no-cache
content-type: text/html
connection: close

Right …… That is me done … I hope this “little” article helps someone …

Who, What and Why?

As an IT Professional I spend a lot of time looking for solutions to IT issues that I have at work and home. Some of the solutions are easy to find, some are most definitely not. What they often have in common is that they evolve.

The purpose of this site is to publish some of those solutions and hopefully be of use to some of you. It wont get updated very often , who knows if I even make it past the first post. But the intention is there.

Create your website at WordPress.com
Get started