Ouadjet
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
- Download last version using Subversion
svn co http://software.inl.fr/svn/mirror/tools/ouadjet
- Browse source code online
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.
