From 4b6f8eabe1ff305a8c7ee0681f27ed30de33faf3 Mon Sep 17 00:00:00 2001 From: b1v1r Date: Fri, 5 Feb 2010 18:12:53 +0000 Subject: [PATCH] Trim whitespace around phrases used with @pmFromFile and allow for both LF and CRLF terminated lines (MODSEC-126). --- CHANGES | 3 +++ apache2/re_operators.c | 24 ++++++++++++++---------- doc/modsecurity2-apache-reference.xml | 22 ++++++++++++++++++++-- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index 2c4bd037..6463d177 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ 18 Jan 2010 - 2.5.12 -------------------- + * Trim whitespace around phrases used with @pmFromFile and allow + for both LF and CRLF terminated lines. + * Allow for more robust parsing for multipart header folding. Reported by Sogeti/ESEC R&D. diff --git a/apache2/re_operators.c b/apache2/re_operators.c index ab75fdf9..311c466f 100644 --- a/apache2/re_operators.c +++ b/apache2/re_operators.c @@ -255,7 +255,8 @@ static int msre_op_pmFromFile_param_init(msre_rule *rule, char **error_msg) { char buf[HUGE_STRING_LEN + 1]; char *fn; char *next; - char *ptr; + char *start; + char *end; const char *rulefile_path; apr_status_t rc; apr_file_t *fd; @@ -301,7 +302,7 @@ static int msre_op_pmFromFile_param_init(msre_rule *rule, char **error_msg) { } /* Open file and read */ - rc = apr_file_open(&fd, fn, APR_READ | APR_FILE_NOCLEANUP, 0, rule->ruleset->mp); + rc = apr_file_open(&fd, fn, APR_READ | APR_BUFFERED | APR_FILE_NOCLEANUP, 0, rule->ruleset->mp); if (rc != APR_SUCCESS) { *error_msg = apr_psprintf(rule->ruleset->mp, "Could not open phrase file \"%s\": %s", fn, apr_strerror(rc, errstr, 1024)); return 0; @@ -321,21 +322,24 @@ static int msre_op_pmFromFile_param_init(msre_rule *rule, char **error_msg) { return 0; } - /* Remove newline */ - ptr = buf; - while(*ptr != '\0') ptr++; - if ((ptr > buf) && (*(ptr - 1) == '\n')) *(ptr - 1) = '\0'; + /* Trim Whitespace */ + start = buf; + while ((apr_isspace(*start) != 0) && (*start != '\0')) start++; + end = buf + strlen(buf); + if (end > start) end--; + while ((end > start) && (apr_isspace(*end) != 0)) end--; + if (end > start) { + *(++end) = '\0'; + } /* Ignore empty lines and comments */ - ptr = buf; - while((*ptr != '\0') && apr_isspace(*ptr)) ptr++; - if ((*ptr == '\0') || (*ptr == '#')) continue; + if ((start == end) || (*start == '#')) continue; #ifdef DEBUG_CONF fprintf(stderr, "Adding phrase file pattern: \"%s\"\n", buf); #endif - acmp_add_pattern(p, buf, NULL, NULL, strlen(buf)); + acmp_add_pattern(p, start, NULL, NULL, (end - start)); } fn = next; } diff --git a/doc/modsecurity2-apache-reference.xml b/doc/modsecurity2-apache-reference.xml index 54faf0ea..a635afe1 100644 --- a/doc/modsecurity2-apache-reference.xml +++ b/doc/modsecurity2-apache-reference.xml @@ -5804,8 +5804,8 @@ end The contents of the files should be one phrase per line. End - of line markers will be stripped from the phrases, however, - whitespace will not be trimmed from phrases in the file. Empty lines + of line markers will be stripped from the phrases (LF and CRLF), and + whitespace is trimmed from both sides of the phrases. Empty lines and comment lines (beginning with a '#') are ignored. @@ -5815,6 +5815,24 @@ end path of the file containing the rule is prepended to the phrase file path. + + + To allow easier matching of whole IP addresses, you can add + boundary characters to the phrases. For example, use "/1.2.3.4/" + instead of "1.2.3.4". You can then insert these characters into the + target prior to a match: + + SecAction "phase:1,pass,nolog,setvar:tx.remote_addr=/%{REMOTE_ADDR}/" +SecRule TX:REMOTE_ADDR "@pmFromFile ip-blacklist.txt" "deny,status:403 + +# ip-blacklist.txt contents: +# NOTE: All IPs must be prefixed/suffixed with "/" as the rules +# will add in this character as a boundary to ensure +# the entire IP is matched. +# SecAction "phase:1,pass,nolog,setvar:tx.remote_addr='/%{REMOTE_ADDR}/'" +/1.2.3.4/ +/5.6.7.8/ + Example: