Skip to content

Instantly share code, notes, and snippets.

@diablodale
Last active July 3, 2017 14:33
Show Gist options
  • Save diablodale/1a987ca660f2dc53a1ea45e96e72ac0e to your computer and use it in GitHub Desktop.
Save diablodale/1a987ca660f2dc53a1ea45e96e72ac0e to your computer and use it in GitHub Desktop.
ModSecurity OWASP ModSecurity Core Rule Set 3.x config file command line tool editor
#!/usr/bin/env php
<?php
// ModSecurity OWASP ModSecurity Core Rule Set 3.x config file command line tool editor
// https://github.com/SpiderLabs/owasp-modsecurity-crs
//
// The key or rule_id must already exist in the file. It can be active or non-active (commented-out).
//
// Usage to set a key value, e.g. to set SecGeoLookupDB to the value: util/geo-location/GeoIP.dat
// crs-conf-edit crs-setup.conf SecGeoLookupDB util/geo-location/GeoIP.dat
//
// Usage to set a variable within a rule, e.g. in rule 900000 set the variable tx.paranoia_level to the value: 2
// crs-conf-edit crs-setup.conf SecAction 900000 setvar tx.paranoia_level 2
// or
// crs-conf-edit crs-setup.conf SecAction 900200 setvar tx.allowed_methods "GET HEAD POST OPTIONS DELETE PUT"
function err( $message) {
fwrite( STDERR, 'error: ' . $message . PHP_EOL );
exit(1);
}
function replace_callback( $matches )
{
global $argv;
$regex = '/^\s*#*\s*/m';
$whole_match = preg_replace( $regex, '', $matches[0] );
if ( is_null( $whole_match ) ) {
return $matches[0];
}
$has_whitespace = preg_match( '/\s/', $argv[6] );
if ( 1 === $has_whitespace ) {
$quote = "'";
}
else {
$quote = '';
}
$regex = "/setvar:('?)" . preg_quote( $argv[5], '/' ) . '=.+\1(?="|,)/m';
$replacement = 'setvar:' . $quote . $argv[5] . '=' . $argv[6] . $quote;
$whole_match = preg_replace( $regex, $replacement, $whole_match );
if ( is_null( $whole_match ) ) {
return $matches[0];
}
return $whole_match;
}
if ( $argc < 3) {
err( 'missing parameters' );
}
$filename = $argv[1];
$verb = $argv[2];
$text = file_get_contents( $argv[1] );
if ( 'SecAction' !== $verb ) {
if ( $argc != 4 ) {
err( 'missing/extra parameters' );
}
$new_text = preg_replace( '/^\s*#?\s*' . preg_quote( $verb, '/' ) . '[^\n]*/m', $verb . ' ' . $argv[3], $text, -1, $count );
if ( is_null( $new_text ) ) {
err( 'internal failure' );
}
if ( 0 === $count ) {
exit(0);
}
}
else {
if ( $argc !== 7 ) {
err ( 'missing/extra parameters' );
}
$rule_id = $argv[3];
if ( !ctype_digit( $rule_id ) ) {
err( 'rule id must be numeric' );
}
if ( 'setvar' !== $argv[4] ) {
err( 'unknown rule modifier: ' . $argv[4] );
}
$regex = '/^\s*#*\s*SecAction([^"]|\n)*"id:' . $rule_id . '([^"]|\n)+"/m';
$new_text = preg_replace_callback( $regex, 'replace_callback', $text, -1, $count );
if ( is_null( $new_text) ) {
err( 'internal failure' );
}
if ( 0 === $count ) {
exit(0);
}
}
if ( false === file_put_contents( $filename, $new_text, LOCK_EX ) ) {
err( 'can not update file' );
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment