Allow ability to force request body buffering to memory. Fixes MODSEC-2.

This commit is contained in:
brectanus 2008-09-03 20:42:28 +00:00
parent 139d651bbf
commit 34798e9abe
8 changed files with 69 additions and 3 deletions

View File

@ -1,7 +1,13 @@
03 Sep 2008 - trunk
-------------------
* Integrate mlogc source.
* Added ctl:requestBodyBuffering=on|off which, when enabled, will force
the request body to be buffered and allow REQUEST_BODY to be inspected.
Previously the REQUEST_BODY target was only populated if the request body
was a parsable type (application/x-www-form-urlencoded or
multipart/form-data) or was forced to be parsed via ctl:requestBodyProcessor.
* Integrated mlogc source.
* Fixed logging the hostname in the error_log which was logging the
request hostname instead of the Apache resolved hostname.

View File

@ -45,6 +45,7 @@ void *create_directory_config(apr_pool_t *mp, char *path) {
dcfg->is_enabled = NOT_SET;
dcfg->reqbody_access = NOT_SET;
dcfg->reqbody_buffering = NOT_SET;
dcfg->reqbody_inmemory_limit = NOT_SET;
dcfg->reqbody_limit = NOT_SET;
dcfg->reqbody_no_files_limit = NOT_SET;
@ -236,6 +237,8 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) {
/* IO parameters */
merged->reqbody_access = (child->reqbody_access == NOT_SET
? parent->reqbody_access : child->reqbody_access);
merged->reqbody_buffering = (child->reqbody_buffering == NOT_SET
? parent->reqbody_buffering : child->reqbody_buffering);
merged->reqbody_inmemory_limit = (child->reqbody_inmemory_limit == NOT_SET
? parent->reqbody_inmemory_limit : child->reqbody_inmemory_limit);
merged->reqbody_limit = (child->reqbody_limit == NOT_SET
@ -480,6 +483,7 @@ void init_directory_config(directory_config *dcfg) {
if (dcfg->is_enabled == NOT_SET) dcfg->is_enabled = 0;
if (dcfg->reqbody_access == NOT_SET) dcfg->reqbody_access = 0;
if (dcfg->reqbody_buffering == NOT_SET) dcfg->reqbody_buffering = 0;
if (dcfg->reqbody_inmemory_limit == NOT_SET)
dcfg->reqbody_inmemory_limit = REQUEST_BODY_DEFAULT_INMEMORY_LIMIT;
if (dcfg->reqbody_limit == NOT_SET) dcfg->reqbody_limit = REQUEST_BODY_DEFAULT_LIMIT;

View File

@ -259,6 +259,12 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) {
}
}
/* Check if we are forcing buffering, then use memory only. */
if (msr->txcfg->reqbody_buffering) {
msr->msc_reqbody_storage = MSC_REQBODY_MEMORY;
msr->msc_reqbody_spilltodisk = 0;
}
/* Initialise arguments */
msr->arguments = apr_table_make(msr->mp, 32);
if (msr->arguments == NULL) return -1;

View File

@ -362,6 +362,7 @@ struct directory_config {
int is_enabled;
int reqbody_access;
int reqbody_buffering;
long int reqbody_inmemory_limit;
long int reqbody_limit;
long int reqbody_no_files_limit;

View File

@ -309,6 +309,9 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
msr->msc_reqbody_processor);
return -1;
}
} else if (msr->txcfg->reqbody_buffering) {
/* Increase per-request data length counter if forcing buffering. */
msr->msc_reqbody_no_files_length += length;
}
/* Check that we are not over the request body no files limit. */
@ -334,7 +337,7 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
/**
*
*/
static apr_status_t modsecurity_request_body_end_urlencoded(modsec_rec *msr, char **error_msg) {
static apr_status_t modsecurity_request_body_end_raw(modsec_rec *msr, char **error_msg) {
msc_data_chunk **chunks, *one_chunk;
char *d;
int i, sofar;
@ -394,6 +397,22 @@ static apr_status_t modsecurity_request_body_end_urlencoded(modsec_rec *msr, cha
one_chunk->is_permanent = 1;
*(const msc_data_chunk **)apr_array_push(msr->msc_reqbody_chunks) = one_chunk;
return 1;
}
/**
*
*/
static apr_status_t modsecurity_request_body_end_urlencoded(modsec_rec *msr, char **error_msg) {
int invalid_count = 0;
*error_msg = NULL;
/* Create the raw buffer */
if (modsecurity_request_body_end_raw(msr, error_msg) != 1) {
return -1;
}
/* Parse URL-encoded arguments in the request body. */
if (parse_arguments(msr, msr->msc_reqbody_buffer, msr->msc_reqbody_length,
@ -458,6 +477,9 @@ apr_status_t modsecurity_request_body_end(modsec_rec *msr, char **error_msg) {
return -1;
}
}
} else if (msr->txcfg->reqbody_buffering) {
/* No processing if there is no processor and forcing buffering. */
return modsecurity_request_body_end_raw(msr, error_msg);
}
/* Note the request body no files length. */

View File

@ -458,6 +458,7 @@ static void init_msr() {
dcfg = (directory_config *)apr_pcalloc(g_mp, sizeof(directory_config));
dcfg->is_enabled = 0;
dcfg->reqbody_access = 0;
dcfg->reqbody_buffering = 0;
dcfg->reqbody_inmemory_limit = REQUEST_BODY_DEFAULT_INMEMORY_LIMIT;
dcfg->reqbody_limit = REQUEST_BODY_DEFAULT_LIMIT;
dcfg->reqbody_no_files_limit = REQUEST_BODY_NO_FILES_DEFAULT_LIMIT;

View File

@ -713,6 +713,13 @@ static char *msre_action_ctl_validate(msre_engine *engine, msre_action *action)
*/
return NULL;
} else
if (strcasecmp(name, "requestBodyBuffering") == 0) {
if (parse_boolean(value) == -1) {
return apr_psprintf(engine->mp, "Invalid setting for ctl name "
" requestBodyBuffering: %s", value);
}
return NULL;
} else
if (strcasecmp(name, "responseBodyAccess") == 0) {
if (parse_boolean(value) == -1) {
return apr_psprintf(engine->mp, "Invalid setting for ctl name "
@ -831,6 +838,16 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
return 1;
} else
if (strcasecmp(name, "requestBodyBuffering") == 0) {
int pv = parse_boolean(value);
if (pv == -1) return -1;
msr->txcfg->reqbody_buffering = pv;
msr->usercfg->reqbody_buffering = pv;
msr_log(msr, 4, "Ctl: Set requestBodyAccess to %d.", pv);
return 1;
} else
if (strcasecmp(name, "requestBodyProcessor") == 0) {
msr->msc_reqbody_processor = value;
msr_log(msr, 4, "Ctl: Set requestBodyProcessor to %s.", value);

View File

@ -4406,6 +4406,10 @@ SecRule REQUEST_CONTENT_TYPE ^text/xml nolog,pass,<emphasis>ctl:requestBodyProce
<para><literal moreinfo="none">requestBodyAccess</literal></para>
</listitem>
<listitem>
<para><literal moreinfo="none">requestBodyBuffering</literal></para>
</listitem>
<listitem>
<para><literal moreinfo="none">requestBodyLimit</literal></para>
</listitem>
@ -4428,7 +4432,8 @@ SecRule REQUEST_CONTENT_TYPE ^text/xml nolog,pass,<emphasis>ctl:requestBodyProce
</orderedlist>
<para>With the exception of<literal moreinfo="none">
requestBodyProcessor</literal>, each configuration option corresponds to
requestBodyProcessor</literal> and <literal moreinfo="none">
requestBodyBuffering</literal>, each configuration option corresponds to
one configuration directive and the usage is identical.</para>
<para>The requestBodyProcessor option allows you to configure the
@ -4450,6 +4455,10 @@ SecRule REQUEST_CONTENT_TYPE ^text/xml nolog,pass,<emphasis>ctl:requestBodyProce
should be inspected in the <literal
moreinfo="none">REQUEST_BODY</literal> phase and an appropriate action
taken.</para>
<para>The requestBodyBuffering option allows you to configure the
request body to be buffered (in memory) even if it is not parsed. This
allows inspection of REQUEST_BODY even when no parser is used.</para>
</section>
<section>