diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index 71d955e273..492a4194a8 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -159,6 +159,9 @@ void *create_directory_config(apr_pool_t *mp, char *path) /* xml external entity */ dcfg->xml_external_entity = NOT_SET; + /* remote addr define */ + dcfg->remote_define = NOT_SET_P; + return dcfg; } @@ -598,6 +601,10 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) merged->xml_external_entity = (child->xml_external_entity == NOT_SET ? parent->xml_external_entity : child->xml_external_entity); + /* remote add define */ + merged->remote_define = (child->remote_define == NOT_SET_P + ? parent->remote_define : child->remote_define); + return merged; } @@ -721,6 +728,9 @@ void init_directory_config(directory_config *dcfg) /* xml external entity */ if (dcfg->xml_external_entity == NOT_SET) dcfg->xml_external_entity = 0; + /* remote addr define */ + if (dcfg->remote_define == NOT_SET_P) dcfg->remote_define = "default"; + } /** @@ -2286,6 +2296,15 @@ static const char *cmd_web_app_id(cmd_parms *cmd, void *_dcfg, const char *p1) return NULL; } +static const char *cmd_remote_addr_define(cmd_parms *cmd, void *_dcfg, const char *p1) +{ + directory_config *dcfg = (directory_config *)_dcfg; + + dcfg->remote_define = p1; + + return NULL; +} + static const char *cmd_sensor_id(cmd_parms *cmd, void *_dcfg, const char *p1) { directory_config *dcfg = (directory_config *)_dcfg; @@ -3475,6 +3494,14 @@ const command_rec module_directives[] = { "id" ), + AP_INIT_TAKE1 ( + "SecRemoteAddrDefine", + cmd_remote_addr_define, + NULL, + CMD_SCOPE_MAIN, + "Define a request header field to define remote addr" + ), + AP_INIT_TAKE1 ( "SecSensorId", cmd_sensor_id, diff --git a/apache2/apache2_util.c b/apache2/apache2_util.c index 2f33c87e39..033517696e 100644 --- a/apache2/apache2_util.c +++ b/apache2/apache2_util.c @@ -198,6 +198,10 @@ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec * apr_size_t nbytes, nbytes_written; apr_file_t *debuglog_fd = NULL; int filter_debug_level = 0; + char *remote = NULL; + char *parse_remote = NULL; + char *saved = NULL; + char *str = NULL; char str1[1024] = ""; char str2[1256] = ""; @@ -268,9 +272,24 @@ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec * "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", r->useragent_ip ? r->useragent_ip : r->connection->client_ip, str1, hostname, log_escape(msr->mp, r->uri), unique_id); #else - ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server, - "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", r->connection->remote_ip, str1, - hostname, log_escape(msr->mp, r->uri), unique_id); + if(strcasecmp(msr->txcfg->remote_define, "default") == 0) { + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server, + "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", r->connection->remote_ip, str1, + hostname, log_escape(msr->mp, r->uri), unique_id); + } else { + remote = (char *)apr_table_get(msr->r->headers_in, msr->txcfg->remote_define); + if(remote == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server, + "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", r->connection->remote_ip, str1, + hostname, log_escape(msr->mp, r->uri), unique_id); + } else { + parse_remote = apr_pstrdup(msr->mp, remote); + str = apr_strtok(parse_remote, ",", &saved); + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server, + "[client %s] ModSecurity: %s%s [uri \"%s\"]%s", str, str1, + hostname, log_escape(msr->mp, r->uri), unique_id); + } + } #endif /* Add this message to the list. */ diff --git a/apache2/libinjection/sqlparse.c b/apache2/libinjection/sqlparse.c index 258707cd1f..9a23f3a103 100644 --- a/apache2/libinjection/sqlparse.c +++ b/apache2/libinjection/sqlparse.c @@ -155,19 +155,12 @@ void st_assign_char(stoken_t * st, const char stype, const char value) void st_assign(stoken_t * st, const char stype, const char *value, size_t len) { - size_t last = len < (ST_MAX_SIZE - 1) ? len : (ST_MAX_SIZE - 1); + size_t last = len < ST_MAX_SIZE ? len : (ST_MAX_SIZE - 1); st->type = stype; - strncpy(st->val, value, last); + memcpy(st->val, value, last); st->val[last] = CHAR_NULL; } -void st_assign_cstr(stoken_t * st, const char stype, const char *value) -{ - st->type = stype; - strncpy(st->val, value, ST_MAX_SIZE - 1); - st->val[ST_MAX_SIZE - 1] = CHAR_NULL; -} - void st_copy(stoken_t * dest, const stoken_t * src) { memcpy(dest, src, sizeof(stoken_t)); @@ -313,7 +306,7 @@ size_t parse_eol_comment(sfilter * sf) const char *endpos = (const char *) memchr((const void *) (cs + pos), '\n', slen - pos); if (endpos == NULL) { - st_assign_cstr(current, 'c', cs + pos); + st_assign(current, 'c', cs + pos, slen - pos); return slen; } else { st_assign(current, 'c', cs + pos, endpos - cs - pos); @@ -404,7 +397,7 @@ size_t parse_slash(sfilter * sf) /* * unterminated comment */ - st_assign_cstr(current, 'c', cs + pos); + st_assign(current, 'c', cs + pos, slen - pos); return slen; } else { /* @@ -441,7 +434,7 @@ size_t parse_backslash(sfilter * sf) size_t pos = sf->pos; if (pos + 1 < slen && cs[pos + 1] == 'N') { - st_assign_cstr(current, '1', "NULL"); + st_assign(current, '1', "NULL", 4); return pos + 2; } else { return parse_other(sf); @@ -479,16 +472,16 @@ size_t parse_operator2(sfilter * sf) /* * special 3-char operator */ - st_assign_cstr(current, 'o', "<=>"); + st_assign(current, 'o', "<=>", 3); return pos + 3; } else if (is_operator2(op2)) { if (streq(op2, "&&") || streq(op2, "||")) { - st_assign_cstr(current, '&', op2); + st_assign(current, '&', op2, 2); } else { /* * normal 2 char operator */ - st_assign_cstr(current, 'o', op2); + st_assign(current, 'o', op2, 2); } return pos + 2; } else { @@ -530,7 +523,7 @@ size_t parse_string_core(const char *cs, const size_t len, size_t pos, * string ended with no trailing quote * assign what we have */ - st_assign_cstr(st, 's', cs + pos + offset); + st_assign(st, 's', cs + pos + offset, len - pos - offset); st->str_close = CHAR_NULL; return len; } else if (*(qpos - 1) != '\\') { @@ -639,6 +632,30 @@ size_t parse_var(sfilter * sf) } } +size_t parse_money(sfilter *sf) +{ + stoken_t *current = &sf->syntax_current; + const char *cs = sf->s; + const size_t slen = sf->slen; + size_t pos = sf->pos; + size_t xlen; + + /* + * $1,000.00 or $1.000,00 ok! + * This also parses $....,,,111 but that's ok + */ + xlen = strlenspn(cs + pos + 1, slen - pos - 1, "0123456789.,"); + if (xlen == 0) { + /* + * just ignore '$' + */ + return pos + 1; + } else { + st_assign(current, '1', cs + pos, 1 + xlen); + return pos + 1 + xlen; + } +} + size_t parse_number(sfilter * sf) { stoken_t *current = &sf->syntax_current; @@ -655,7 +672,7 @@ size_t parse_number(sfilter * sf) xlen = strlenspn(cs + pos + 2, slen - pos - 2, "0123456789ABCDEFabcdef"); if (xlen == 0) { - st_assign_cstr(current, 'n', "0X"); + st_assign(current, 'n', "0X", 2); return pos + 2; } else { st_assign(current, '1', cs + pos, 2 + xlen); @@ -664,10 +681,10 @@ size_t parse_number(sfilter * sf) } start = pos; - while (isdigit(cs[pos])) { + while (pos < slen && isdigit(cs[pos])) { pos += 1; } - if (cs[pos] == '.') { + if (pos < slen && cs[pos] == '.') { pos += 1; while (pos < slen && isdigit(cs[pos])) { pos += 1; @@ -678,23 +695,25 @@ size_t parse_number(sfilter * sf) } } - if (cs[pos] == 'E' || cs[pos] == 'e') { - pos += 1; - if (pos < slen && (cs[pos] == '+' || cs[pos] == '-')) { - pos += 1; - } - while (isdigit(cs[pos])) { + if (pos < slen) { + if (cs[pos] == 'E' || cs[pos] == 'e') { pos += 1; + if (pos < slen && (cs[pos] == '+' || cs[pos] == '-')) { + pos += 1; + } + while (pos < slen && isdigit(cs[pos])) { + pos += 1; + } + } else if (isalpha(cs[pos])) { + /* + * oh no, we have something like '6FOO' + * use microsoft style parsing and take just + * the number part and leave the rest to be + * parsed later + */ + st_assign(current, '1', cs + start, pos - start); + return pos; } - } else if (isalpha(cs[pos])) { - /* - * oh no, we have something like '6FOO' - * use microsoft style parsing and take just - * the number part and leave the rest to be - * parsed later - */ - st_assign(current, '1', cs + start, pos - start); - return pos; } st_assign(current, '1', cs + start, pos - start); @@ -895,7 +914,7 @@ int sqli_tokenize(sfilter * sf, stoken_t * sout) */ if (last->type == 'n' && !cstrcasecmp(last->val, "IN")) { st_copy(last, current); - st_assign_cstr(sout, 'f', "IN"); + st_assign(sout, 'f', "IN", 2); return TRUE; } else { /* diff --git a/apache2/libinjection/sqlparse_data.h b/apache2/libinjection/sqlparse_data.h index a76af56de3..9d14bd4ef1 100644 --- a/apache2/libinjection/sqlparse_data.h +++ b/apache2/libinjection/sqlparse_data.h @@ -585,7 +585,7 @@ static const pt2Function char_parse_map[] = { &parse_operator2, /* 33 */ &parse_string, /* 34 */ &parse_eol_comment, /* 35 */ - &parse_white, /* 36 */ + &parse_money, /* 36 */ &parse_operator1, /* 37 */ &parse_operator2, /* 38 */ &parse_string, /* 39 */ diff --git a/apache2/libinjection/sqlparse_private.h b/apache2/libinjection/sqlparse_private.h index 0d16c033e6..154accf6e6 100644 --- a/apache2/libinjection/sqlparse_private.h +++ b/apache2/libinjection/sqlparse_private.h @@ -60,6 +60,7 @@ int is_operator2(const char *key); int is_sqli_pattern(const char *key); size_t parse_none(sfilter * sf); +size_t parse_money(sfilter * sf); size_t parse_other(sfilter * sf); size_t parse_white(sfilter * sf); size_t parse_operator1(sfilter *sf); diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index 9f001523cd..35ddddf65f 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -579,7 +579,7 @@ struct directory_config { /* Hash */ apr_array_header_t *hash_method; - const char *crypto_key; + const char *crypto_key; int crypto_key_len; const char *crypto_param_name; int hash_is_enabled; @@ -598,6 +598,9 @@ struct directory_config { /* xml */ int xml_external_entity; + + /* remote addr */ + const char *remote_define; }; struct error_message_t { diff --git a/apache2/re_variables.c b/apache2/re_variables.c index 26669734ff..98448d0442 100644 --- a/apache2/re_variables.c +++ b/apache2/re_variables.c @@ -700,13 +700,41 @@ static int var_useragent_ip_generate(modsec_rec *msr, msre_var *var, msre_rule * static int var_remote_addr_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { - return var_simple_generate(var, vartab, mptmp, msr->remote_addr); + char *remote = NULL; + char *parse_remote = NULL; + char *saved = NULL; + char *str = NULL; + + if(strcasecmp(msr->txcfg->remote_define, "default") == 0) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "Set variable \"%s\" to \"%s\".", var->name, msr->remote_addr); + } + return var_simple_generate(var, vartab, mptmp, msr->remote_addr); + } else { + remote = (char *)apr_table_get(msr->r->headers_in, msr->txcfg->remote_define); + if(remote == NULL) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "Request header \"%s\" not present setting variable \"%s\" to \"%s\".", msr->txcfg->remote_define, + var->name, msr->remote_addr); + } + return var_simple_generate(var, vartab, mptmp, msr->remote_addr); + } else { + parse_remote = apr_pstrdup(msr->mp, remote); + str = apr_strtok(parse_remote, ",", &saved); + msr->remote_addr = apr_pstrdup(msr->mp, str); + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "Request header \"%s\" is present setting variable \"%s\" to \"%s\".", msr->txcfg->remote_define, + var->name, msr->remote_addr); + } + return var_simple_generate(var, vartab, mptmp, msr->remote_addr); + } + } } /* REMOTE_HOST */ static int var_remote_host_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, - apr_table_t *vartab, apr_pool_t *mptmp) + apr_table_t *vartab, apr_pool_t *mptmp) { const char *value1 = ap_get_remote_host(msr->r->connection, msr->r->per_dir_config, REMOTE_NAME, NULL);