Ouadjet

ouadjet.png

Ouadjet is an auto-learning, whitelisting HTTP reverse proxy. It consists of :

  • An XML model
  • Some python code for learning from HTTP events (Log -> XML)
  • Some python code for generating the filtering config from the XML file.

Ouadjet uses Apache mod_security audit logs to create HTTP filtering rules for GET and POST requests in a XML document. Then modsecurity rules are generated using XML rules.

Presentation

A lecture about Ouadjet was given by INL at the Solutions Linux meeting in Paris on Jan 31st, 2007. The pdf support of this conference is available (in French) : 2007_SL_INL_PE_whitelistant.pdf

Rules generalization

  • For a non empty field, the maximum length is set to 10 bytes
    • Example: « a » => (1 octet) « [a-z]{1,10} »
  • For a field with more than 3 bytes, minimum length is set to 3 bytes
    • Example: « abcdefghijkl » (12 octets) => « [a-z]{3,12} »
  • One lower case letter will be genaralize to all lower case letters
    • Example: « xx » => « [a-z]{2,10} »
  • Same with upper case
    • Example: « M » => « [A-Z]{1,10} »
  • One decimal digit will use [0-9] :
    • Example: « 109 » => « [0-9]{1,10} »

Download

Ouadjet is licensed under the GNU GPL version 2.

Install modsecurity

  • Download mod-security version 1.9.x
  • Install required dependencies, eg. with Debian: sudo apt-get install apache2-prefork-dev
  • Decompress archive: tar xvzf modsecurity-VERSION.tar.gz
  • Move into the new directory: cd modsecurity-VERSION/apache2
  • Run compilation and install the new module with: sudo apxs2 -cia mod_security.c
  • Reload Apache2 server: sudo /etc/init.d/apache2 restart

Example

rules.xml

<rulesetdef version='alpha'>
  <global>
    <defineParamClassRegex regex='' name='Empty'/>
    <defineParamClassRegex regex='[a-z !]{0,10}' name='regex4'/>
    <defineParamClassRegex regex='[0-9]{1,10}' name='Number_1_10'/>
    <defineParamClassRegex regex='[a-z\r\n]{3,13}' name='regex6'/>
  </global>
  <rule state='enabled' id='1' name='Match all images'>
    <filters>
      <filter value='GET' arg='request_method'/>
    </filters>
    <path>.*\.(png|gif|jpg|jpeg|ico)</path>
  </rule>
  <rule state='enabled' id='2' name='Match CSS and Javascript'>
    <path>.*\.(css|js)</path>
  </rule>
  <rule state='enabled' id='3' name=''>
    <charset>ASCII</charset>
    <filters>
      <filter value='GET' arg='request_method'/>
      <filter value='http' arg='scheme'/>
    </filters>
    <path>/</path>
  </rule>
  <rule state='enabled' id='7' name=''>
    <charset>ISO-8859-1</charset>
    <filters>
      <filter value='POST' arg='request_method'/>
      <filter value='http' arg='scheme'/>
    </filters>
    <constraints>
      <param multiple='0' optional='0' name='login_username' class='regex4'/>
      <param multiple='0' optional='0' name='secretkey' class='regex6'/>
      <param multiple='0' optional='0' name='js_autodetect_results' class='Number_1_10'/>
      <param multiple='0' optional='0' name='just_logged_in' class='Number_1_10'/>
    </constraints>
    <path>/src/redirect.php</path>
  </rule>
  (...)
</rulesetdef>

mod_security rules

<Location />
SecFilterInheritance Off
SecFilterDefaultAction "deny,log,status:500"

# Rule id 1, .*\.(png|gif|jpg|jpeg|ico)
SecFilterSelective "REQUEST_URI" "!^.*\.(png|gif|jpg|jpeg|ico)(\?|$)" "skipnext:3"
SecFilterSelective "REQUEST_URI" "^.*\.(png|gif|jpg|jpeg|ico)(\?|$)" "chain"
SecFilterSelective "REQUEST_METHOD" "!^(GET)$" "deny,status:500,log,msg:XML_rule_id:1"
SecFilterSelective "REQUEST_URI" "^.*\.(png|gif|jpg|jpeg|ico)" "allow"

(...)
</Location>

<Location /src>
SecFilterInheritance Off
SecFilterDefaultAction "deny,log,status:500"

# Rule id 7, /src/redirect.php
SecFilterSelective "REQUEST_URI" "!^/src/redirect.php(\?|$)" "skipnext:12"
SecFilterSelective "REQUEST_URI" "^/src/redirect.php(\?|$)" "chain"
SecFilterSelective "REQUEST_METHOD" "!^(POST)$" "deny,status:500,log,msg:XML_rule_id:7"
# verif arguments names
SecFilterSelective "ARGS_NAMES" "!^(login_username|secretkey|js_autodetect_results|just_logged_in)$" "deny,status:500,log,msg:XML_rule_id:7"
# argument login_username
SecFilterSelective "REQUEST_METHOD" "!^POST$" "skipnext:1"
SecFilterSelective "ARG_login_username" "!^[a-z !]{0,10}$" "deny,status:500,log,msg:XML_rule_id:7"
# argument secretkey
SecFilterSelective "REQUEST_METHOD" "!^POST$" "skipnext:1"
SecFilterSelective "ARG_secretkey" "!^[a-z\r\n]{3,13}$" "deny,status:500,log,msg:XML_rule_id:7"
# argument js_autodetect_results
SecFilterSelective "REQUEST_METHOD" "!^POST$" "skipnext:1"
SecFilterSelective "ARG_js_autodetect_results" "!^[0-9]{1,10}$" "deny,status:500,log,msg:XML_rule_id:7"
# argument just_logged_in
SecFilterSelective "REQUEST_METHOD" "!^POST$" "skipnext:1"
SecFilterSelective "ARG_just_logged_in" "!^[0-9]{1,10}$" "deny,status:500,log,msg:XML_rule_id:7"
SecFilterSelective "REQUEST_URI" "^/src/redirect.php" "allow"

(...)
</Location>

Authors

See AUTHORS file.