From 0769f2378cc0a37728a5a63e9ecc227224601f97 Mon Sep 17 00:00:00 2001 From: ivanr Date: Fri, 7 Sep 2007 13:16:40 +0000 Subject: [PATCH] More multipart improvements. Added MULTIPART_MISSING_SEMICOLON. --- apache2/msc_multipart.c | 67 ++++++++++++++++++++++++++++++++++------- apache2/msc_multipart.h | 1 + apache2/re_variables.c | 24 +++++++++++++++ 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/apache2/msc_multipart.c b/apache2/msc_multipart.c index 38dd1707..d42e825f 100644 --- a/apache2/msc_multipart.c +++ b/apache2/msc_multipart.c @@ -637,6 +637,12 @@ int multipart_init(modsec_rec *msr, char **error_msg) { return -1; } + if (strncasecmp(msr->request_content_type, "multipart/form-data", 19) != 0) { + msr->mpd->flag_error = 1; + *error_msg = apr_psprintf(msr->mp, "Multipart: Invalid MIME type."); + return -1; + } + /* Count how many times the word "boundary" appears in the C-T header. */ if (multipart_count_boundary_params(msr->mp, msr->request_content_type) > 1) { msr->mpd->flag_error = 1; @@ -646,9 +652,28 @@ int multipart_init(modsec_rec *msr, char **error_msg) { msr->mpd->boundary = strstr(msr->request_content_type, "boundary"); if (msr->mpd->boundary != NULL) { + char *p = NULL; char *b = NULL; + int seen_semicolon = 0; int len = 0; + /* Check for extra characters before the boundary. */ + for (p = (char *)(msr->request_content_type + 19); p < msr->mpd->boundary; p++) { + if (!isspace(*p)) { + if ((seen_semicolon == 0)&&(*p == ';')) { + seen_semicolon = 1; /* It is OK to have one semicolon. */ + } else { + *error_msg = apr_psprintf(msr->mp, "Multipart: Invalid boundary in C-T (malformed)."); + return -1; + } + } + } + + /* Have we seen the semicolon in the header? */ + if (seen_semicolon == 0) { + msr->mpd->flag_missing_semicolon = 1; + } + b = strchr(msr->mpd->boundary + 8, '='); if (b == NULL) { msr->mpd->flag_error = 1; @@ -658,13 +683,18 @@ int multipart_init(modsec_rec *msr, char **error_msg) { /* Check parameter name ends well. */ if (b != (msr->mpd->boundary + 8)) { - if (isspace(*(msr->mpd->boundary + 8))) { - /* Flag for whitespace after parameter name. */ - msr->mpd->flag_boundary_whitespace = 1; - } else { - msr->mpd->flag_error = 1; - *error_msg = apr_psprintf(msr->mp, "Multipart: Invalid boundary in C-T (parameter name)."); - return -1; + /* Check all characters between the end of the boundary + * and the = character. + */ + for (p = msr->mpd->boundary + 8; p < b; p++) { + if (isspace(*p)) { + /* Flag for whitespace after parameter name. */ + msr->mpd->flag_boundary_whitespace = 1; + } else { + msr->mpd->flag_error = 1; + *error_msg = apr_psprintf(msr->mp, "Multipart: Invalid boundary in C-T (parameter name)."); + return -1; + } } } @@ -874,7 +904,7 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf, log_escape_nq(msr->mp, msr->mpd->buf)); return -1; } - } else { + } else { /* It looks like a boundary but we couldn't match it. */ char *p = NULL; /* Check if an attempt to use quotes around the boundary was made. */ @@ -905,6 +935,23 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf, msr->mpd->flag_unmatched_boundary = 1; } + } else { /* We do not think the buffer contains a boundary. */ + /* Look into the buffer to see if there's anything + * there that resembles a boundary. + */ + if (msr->mpd->buf_contains_line) { + int i, len = (MULTIPART_BUF_SIZE - msr->mpd->bufleft); + char *p = msr->mpd->buf; + + for(i = 0; i < len; i++) { + if ((p[i] == '-')&&(i + 1 < len)&&(p[i + 1] == '-')) { + if (strncmp(p + i + 2, msr->mpd->boundary, strlen(msr->mpd->boundary)) == 0) { + msr->mpd->flag_unmatched_boundary = 1; + break; + } + } + } + } } /* Process as data if it was not a boundary. */ @@ -1069,7 +1116,7 @@ int multipart_get_arguments(modsec_rec *msr, char *origin, apr_table_t *argument if (arg == NULL) return -1; arg->name = parts[i]->name; - arg->name_len = strlen(parts[i]->name); // TODO + arg->name_len = strlen(parts[i]->name); arg->value = parts[i]->value; arg->value_len = parts[i]->length; arg->value_origin_offset = parts[i]->offset; @@ -1094,8 +1141,6 @@ char *multipart_reconstruct_urlencoded_body_sanitise(modsec_rec *msr) { if (msr->mpd == NULL) return NULL; - // TODO Cache this data somewhere in the structure - /* calculate the size of the buffer */ body_len = 1; parts = (multipart_part **)msr->mpd->parts->elts; diff --git a/apache2/msc_multipart.h b/apache2/msc_multipart.h index 54022c6b..c68d2780 100644 --- a/apache2/msc_multipart.h +++ b/apache2/msc_multipart.h @@ -108,6 +108,7 @@ struct multipart_data { int flag_crlf_line; int flag_unmatched_boundary; int flag_boundary_whitespace; + int flag_missing_semicolon; }; diff --git a/apache2/re_variables.c b/apache2/re_variables.c index c033329d..6ba6cbe8 100644 --- a/apache2/re_variables.c +++ b/apache2/re_variables.c @@ -1324,6 +1324,18 @@ static int var_multipart_lf_line_generate(modsec_rec *msr, msre_var *var, msre_r } } +/* MULTIPART_MISSING_SEMICOLON */ + +static int var_multipart_missing_semicolon_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, + apr_table_t *vartab, apr_pool_t *mptmp) +{ + if ((msr->mpd != NULL)&&(msr->mpd->flag_missing_semicolon != 0)) { + return var_simple_generate(var, vartab, mptmp, "1"); + } else { + return var_simple_generate(var, vartab, mptmp, "0"); + } +} + /* MULTIPART_STRICT_ERROR */ static int var_multipart_strict_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, @@ -1338,6 +1350,7 @@ static int var_multipart_strict_error_generate(modsec_rec *msr, msre_var *var, m ||(msr->mpd->flag_data_after != 0) ||(msr->mpd->flag_header_folding != 0) ||(msr->mpd->flag_lf_line != 0) + ||(msr->mpd->flag_missing_semicolon != 0) ) { return var_simple_generate(var, vartab, mptmp, "1"); } @@ -2378,6 +2391,17 @@ void msre_engine_register_default_variables(msre_engine *engine) { PHASE_REQUEST_BODY ); + /* MULTIPART_MISSING_SEMICOLON */ + msre_engine_variable_register(engine, + "MULTIPART_MISSING_SEMICOLON", + VAR_SIMPLE, + 0, 0, + NULL, + var_multipart_missing_semicolon_generate, + VAR_CACHE, + PHASE_REQUEST_BODY + ); + /* MULTIPART_STRICT_ERROR */ msre_engine_variable_register(engine, "MULTIPART_STRICT_ERROR",