ModSecurity: Open Source Web Application Firewall

ModSecurity for Java - Help Page

ModSecurity is an open source intrusion detection and prevention engine for web applications. It can also be called an web application firewall. It operates embedded into the web server, acting as a powerful umbrella, shielding applications from attacks.

ModSecurity for Java is designed as a Java Filter which makes use of ModSecurity's native code using the JNI technology.


Installation steps

Step 1: Compile ModSecurity native library

Install required packages for compilation. For example, on Debian/Ubuntu like systems:

sudo apt-get install g++ make automake autoconf libtool
                            

Install required dependent packages:

sudo apt-get install libxml2 libxml2-dev libxml2-utils libaprutil1 libaprutil1-dev apache2-prefork-dev
                            

The native libraries needed for ModSecurity for Java are:

  1. zlib1 (Windows only)
  2. libxml2
  3. pcre
  4. libapr-1
  5. libapriconv-1 (Windows only)
  6. libaprutil-1
  7. ModSecurityJNI (JNI wrapper for mod_security code)

These native libraries are used by the ModSecurityFilter.


Download mod_security source code from GitHub, compile and install:

git clone https://github.com/mihaipitu/ModSecurity.git
cd mod_security/
./autogen.sh
./configure --enable-standalone-module --enable-java-module
make
                            

Copy compiled library in a convenient folder:

sudo cp ./java/.libs/libModSecurityJNI.so /usr/lib/
                            

The libModSecurityJNI.so file is the connector that plugs the "standalone" ModSecurity code into the Java application as a Filter.


Step 2: Java Web Applications with ModSecurity Filter

ModSecurity for Java uses Java Filters in order to intercept Http requests and responses. ModsecurityTestApp is an example of Java EE Web application using the ModSecurity Filter. To use the ModSecurity filter in your Java web application, you will need to copy either the source .java files or the compiled .class files into your application.

  • Scenario 1: Add ModSecurity source java files to application and create WAR

    Copy the source files from mod_security/java/ModSecurityTestApp/src/ into your application. By using this option, the ModSecurity Java source code files are compiled with the source files from your web application.

    # pwd
    /tmp/ModSecurity/java/ModSecurityTestApp/src/java/org
    # ls -R
    .:
    apache  modsecurity
    ./apache:
    commons
    ./apache/commons:
    fileupload
    ./apache/commons/fileupload:
    DefaultFileItemFactory.java    DiskFileUpload.java   FileUploadBase.java       MultipartStream.java
    DefaultFileItem.java           FileItemFactory.java  FileUploadException.java  package.html
    DeferredFileOutputStream.java  FileItem.java         FileUpload.java           ThresholdingOutputStream.java
    ./modsecurity:
    ModSecurityFilter.java  MsHttpServletRequest.java         MsHttpServletResponse.java  MsOutputStream.java
    ModSecurity.java        MSHttpServletRequestWrapper.java  MsHttpTransaction.java      MsWriter.java
    [root@localhost org]#
    
  • Scenario 2: Add ModSecurity compiled class files to an already compiled app

    If you already have a compiled app and you would like to add in ModSecurity filtering without recompiling a new WAR file, you can instead use the compiled .class files. Unzip the mod_security/java/ModSecurityTestApp/dist/ModSecurityTestApp.war file and copy the /WEB-INF/classes/ directory into your own WEB-INF/ directory.

    cp -R ModSecurity/java/ModSecurityTestApp/dist/WEB-INF/classes/org/* /opt/tomcat/webapps/WebGoat/WEB-INF/classes/org
    

Step 3: Activate the ModSecurityFilter in web.xml

Add the following entry for the filter tag in your web.xml file:


<filter>
        <filter-name>ModSecurityFilter</filter-name>
	    <filter-class>org.modsecurity.ModSecurityFilter</filter-class>
	    <init-param>
                <param-name>conf</param-name>
                <param-value>c:\inetpub\wwwroot\owasp-crs\modsecurity.conf</param-value> 
                <!-- Path to the main configuration file of ModSecurity. You can activate the core 
                     rules by including in modsecurity.conf file:
                        Include modsecurity_crs_10_setup.conf
                        Include activated_rules\*.conf
                -->
            </init-param>
           <!--
           <init-param>
                <param-name>zlib1</param-name>
                <param-value>c:\work\mod_security\java\libs\zlib1.dll</param-value>
            </init-param>
            <init-param>
                <param-name>libxml2</param-name>
                <param-value>c:\work\mod_security\java\libs\libxml2.dll</param-value> 
            </init-param>
            <init-param>
                <param-name>libpcre</param-name>
                <param-value>c:\work\mod_security\java\libs\pcre.dll</param-value> 
            </init-param>
            <init-param>
                <param-name>libapr-1</param-name>
                <param-value>c:\work\mod_security\java\libs\libapr-1.dll</param-value> 
            </init-param>
            <init-param>
                <param-name>libapriconv-1</param-name>
                <param-value>c:\work\mod_security\java\libs\libapriconv-1.dll</param-value> 
            </init-param>
            <init-param>
                <param-name>libaprutil-1</param-name>
                <param-value>c:\work\mod_security\java\libs\libaprutil-1.dll</param-value> 
            </init-param>
            <init-param>
                <param-name>libModSecurityJNI</param-name>
                <param-value>c:\work\mod_security\java\libs\ModSecurityJNI.dll</param-value> 
            </init-param>
            -->
    </filter>
    <filter-mapping>
	    <filter-name>ModSecurityFilter</filter-name>
	    <url-pattern>/*</url-pattern>
    </filter-mapping>
</filter>
                            
                            

The ModSecurity Filter makes use of the native libraries written in C/C++ using the JNI technology. There are two ways of loading native libraries by Java Web Applications:

  1. Loading native libraries directly in the ModSecurityFilter

    Although this is easier, it is not recommended because the JVM will raise UnsatisfiedLinkError if the ModSecurity Filter is used in multiple applications within the same server or the application is redeployed while the server is running. The libraries are loaded in the ModSecurity class using System.loadLibrary(). In this case the server has to be started with the following VM options:

    -Djava.library.path=/path/to/libraries/folder/
                                        

    You can specify multiple folders for the java.library.path variable by using : (colon) or ; (semi-colon), depending on your environment. Also, the libraries can be loaded using their absolute path by uncommenting the init-param elements in the above filter example.

  2. Loading native libraries when the Web Server starts

    ModSecurityLoader.jar should be placed in the Java server library loader folder (for example, in Tomcat 7: $CATALINA_HOME/lib). The server has to be started with the VM options:

    -Djava.library.path=/path/to/libraries/folder/
                                        

    or alternatively by specifying init-param elements with absolute paths in the ModSecurityLoaderConfig.xml file.


Step 4: Configure ModSecurity Settings

In the web.xml file, you added a path to the main modsecurity.conf file holding directives such as SecRuleEngine, SecAuditEngine, etc... You should update this file as needed for your environment.

# head /root/modsecurity-apache_2.7.2/modsecurity.conf
# -- Rule engine initialization ----------------------------------------------
# Enable ModSecurity, attaching it to every transaction. Use detection
# only to start with, because that minimises the chances of post-installation
# disruption.
#
SecRuleEngine DetectionOnly 

Step 5: Add in Rule Files

The ModSecurity filter knows how to handle "Apache Include" directives in the "conf" param value. This means that if you want to create your own rule files or utilize the OWASP ModSecurity CRS, you should add appropriate Include directives to the main modsecurity.conf file:

# tail /root/modsecurity-apache_2.7.2/modsecurity.conf
# 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.
#
#SecUnicodeCodePage 20127
#SecUnicodeMapFile unicode.mapping
Include /root/owasp-modsecurity-crs/modsecurity_crs_10_setup.conf
Include /root/owasp-modsecurity-crs/base_rules/*.conf 

Step 6: Start Java Server and Confirm ModSecurity Initialization

# /opt/apache-tomcat-7.0.42/bin/startup.sh
Using CATALINA_BASE:   /opt/apache-tomcat-7.0.42
Using CATALINA_HOME:   /opt/apache-tomcat-7.0.42
Using CATALINA_TMPDIR: /opt/apache-tomcat-7.0.42/temp
Using JRE_HOME:        /usr/lib/jvm/java-1.6.0-openjdk
Using CLASSPATH:       /opt/apache-tomcat-7.0.42/bin/bootstrap.jar:/opt/apache-tomcat-7.0.42/bin/tomcat-juli.jar
# cat /opt/apache-tomcat-7.0.42/logs/localhost*.log
Sep 27, 2013 6:35:18 PM org.apache.catalina.core.ApplicationContext log
INFO: ModSecurity for Java (STABLE)/2.7.5 (http://www.modsecurity.org/) configured.
Sep 27, 2013 6:35:18 PM org.apache.catalina.core.ApplicationContext log
INFO: ModSecurity: APR compiled version="1.3.9"; loaded version="1.3.9"
Sep 27, 2013 6:35:18 PM org.apache.catalina.core.ApplicationContext log
INFO: ModSecurity: PCRE compiled version="7.8 "; loaded version="7.8 2008-09-05"
Sep 27, 2013 6:35:18 PM org.apache.catalina.core.ApplicationContext log
INFO: ModSecurity: LUA compiled version="Lua 5.1"
Sep 27, 2013 6:35:18 PM org.apache.catalina.core.ApplicationContext log
INFO: ModSecurity: LIBXML compiled version="2.7.6"
Sep 27, 2013 6:35:18 PM org.apache.catalina.core.ApplicationContext log
INFO: ModSecurity started.

Step 7: Test Rules

The next step is to send some example attacks to your application to ensure that the it is working properly. If you send some XSS attacks for instance, you should see logs similar to the following in the Tomcat logs directory:

Step 8: Verify Audit Logging

In addition to the short, 1-line alert messages sent to the Tomcat logs, ModSecurity will also generate appropriate Audit log entries depending on your configuration. You can review the corresponding Audit log entry for your test request(s) to see fully request/response payloads:

Bonus Testing: BeanShell scripting with ModSecurity

You can use BeanShell scripts in SecRule ModSecurity directives using the exec action. First you need to put the bsh.jar file (which can be downloaded from beanshell.org) into the current directory of your server (for example $CATALINA_HOME/bin in Tomcat). An example of an exec can be the following:

# Alert and Block based on Anomaly Scores
#
SecRule TX:ANOMALY_SCORE "@gt 0" \
    "chain,phase:2,id:'981176',t:none,deny,log,msg:'Inbound Anomaly Score Exceeded (Total Score: %{TX.ANOMALY_SCORE}, SQLi=%{TX.SQL_INJECTION_SCORE}, XSS=%{TX.XSS_SCORE}): Last Matched Message: %{tx.msg}',logdata:'Last Matched Data: %{matched_var}',setvar:tx.inbound_tx_msg=%{tx.msg},setvar:tx.inbound_anomaly_score=%{tx.anomaly_score}"
        SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_level}" chain
                SecRule TX:ANOMALY_SCORE_BLOCKING "@streq on" chain
                        SecRule TX:/^\d+\-/ "(.*)" "setenv:block_session=1,exec:/usr/local/apache/conf/beanshell_script.bsh"

                            

The environment variable set in the SecAction can be accessed in BeanShell scripts using some pseudo-code like this to instruct the app to block the current session:


import org.owasp.webgoat.session.WebSession;

System.getenv("block_session");
if (block_user != null) {
  session.setAttribute(BLOCKED, "true");
}