mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-16 07:56:12 +03:00
Include data edition, sanitizematched and few fixes
This commit is contained in:
parent
37e8cba181
commit
7f52d86e4b
@ -104,6 +104,10 @@ void *create_directory_config(apr_pool_t *mp, char *path)
|
|||||||
/* Content injection. */
|
/* Content injection. */
|
||||||
dcfg->content_injection_enabled = NOT_SET;
|
dcfg->content_injection_enabled = NOT_SET;
|
||||||
|
|
||||||
|
/* Stream inspection */
|
||||||
|
dcfg->stream_inbody_inspection = NOT_SET;
|
||||||
|
dcfg->stream_outbody_inspection = NOT_SET;
|
||||||
|
|
||||||
/* Geo Lookups */
|
/* Geo Lookups */
|
||||||
dcfg->geo = NOT_SET_P;
|
dcfg->geo = NOT_SET_P;
|
||||||
|
|
||||||
@ -445,6 +449,12 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child)
|
|||||||
merged->content_injection_enabled = (child->content_injection_enabled == NOT_SET
|
merged->content_injection_enabled = (child->content_injection_enabled == NOT_SET
|
||||||
? parent->content_injection_enabled : child->content_injection_enabled);
|
? parent->content_injection_enabled : child->content_injection_enabled);
|
||||||
|
|
||||||
|
/* Stream inspection */
|
||||||
|
merged->stream_inbody_inspection = (child->stream_inbody_inspection == NOT_SET
|
||||||
|
? parent->stream_inbody_inspection : child->stream_inbody_inspection);
|
||||||
|
merged->stream_outbody_inspection = (child->stream_outbody_inspection == NOT_SET
|
||||||
|
? parent->stream_outbody_inspection : child->stream_outbody_inspection);
|
||||||
|
|
||||||
/* Geo Lookup */
|
/* Geo Lookup */
|
||||||
merged->geo = (child->geo == NOT_SET_P
|
merged->geo = (child->geo == NOT_SET_P
|
||||||
? parent->geo : child->geo);
|
? parent->geo : child->geo);
|
||||||
@ -543,6 +553,10 @@ void init_directory_config(directory_config *dcfg)
|
|||||||
/* Content injection. */
|
/* Content injection. */
|
||||||
if (dcfg->content_injection_enabled == NOT_SET) dcfg->content_injection_enabled = 0;
|
if (dcfg->content_injection_enabled == NOT_SET) dcfg->content_injection_enabled = 0;
|
||||||
|
|
||||||
|
/* Stream inspection */
|
||||||
|
if (dcfg->stream_inbody_inspection == NOT_SET) dcfg->stream_inbody_inspection = 0;
|
||||||
|
if (dcfg->stream_outbody_inspection == NOT_SET) dcfg->stream_outbody_inspection = 0;
|
||||||
|
|
||||||
/* Geo Lookup */
|
/* Geo Lookup */
|
||||||
if (dcfg->geo == NOT_SET_P) dcfg->geo = NULL;
|
if (dcfg->geo == NOT_SET_P) dcfg->geo = NULL;
|
||||||
|
|
||||||
@ -1334,6 +1348,72 @@ static const char *cmd_guardian_log(cmd_parms *cmd, void *_dcfg,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Add StreamInBodyInspection configuration option
|
||||||
|
*
|
||||||
|
* \param cmd Pointer to configuration data
|
||||||
|
* \param _dcfg Pointer to directory configuration
|
||||||
|
* \param p1 Pointer to configuration option
|
||||||
|
*
|
||||||
|
* \retval NULL On failure
|
||||||
|
* \retval apr_psprintf On Success
|
||||||
|
*/
|
||||||
|
static const char *cmd_stream_inbody_inspection(cmd_parms *cmd, void *_dcfg, int flag)
|
||||||
|
{
|
||||||
|
directory_config *dcfg = (directory_config *)_dcfg;
|
||||||
|
if (dcfg == NULL) return NULL;
|
||||||
|
dcfg->stream_inbody_inspection = flag;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Add StreamOutBodyInspection configuration option
|
||||||
|
*
|
||||||
|
* \param cmd Pointer to configuration data
|
||||||
|
* \param _dcfg Pointer to directory configuration
|
||||||
|
* \param p1 Pointer to configuration option
|
||||||
|
*
|
||||||
|
* \retval NULL On failure
|
||||||
|
* \retval apr_psprintf On Success
|
||||||
|
*/
|
||||||
|
static const char *cmd_stream_outbody_inspection(cmd_parms *cmd, void *_dcfg, int flag)
|
||||||
|
{
|
||||||
|
directory_config *dcfg = (directory_config *)_dcfg;
|
||||||
|
if (dcfg == NULL) return NULL;
|
||||||
|
dcfg->stream_outbody_inspection = flag;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Add SecReadStateLimit configuration option
|
||||||
|
*
|
||||||
|
* \param cmd Pointer to configuration data
|
||||||
|
* \param _dcfg Pointer to directory configuration
|
||||||
|
* \param p1 Pointer to configuration option
|
||||||
|
*
|
||||||
|
* \retval NULL On failure
|
||||||
|
* \retval apr_psprintf On Success
|
||||||
|
*/
|
||||||
|
static const char *cmd_conn_read_state_limit(cmd_parms *cmd, void *_dcfg,
|
||||||
|
const char *p1)
|
||||||
|
{
|
||||||
|
directory_config *dcfg = (directory_config *)_dcfg;
|
||||||
|
long int limit;
|
||||||
|
|
||||||
|
if (dcfg == NULL) return NULL;
|
||||||
|
|
||||||
|
limit = strtol(p1, NULL, 10);
|
||||||
|
if ((limit == LONG_MAX)||(limit == LONG_MIN)||(limit <= 0)) {
|
||||||
|
return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecReadStateLimit: %s", p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_read_state_limit = limit;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *cmd_request_body_inmemory_limit(cmd_parms *cmd, void *_dcfg,
|
static const char *cmd_request_body_inmemory_limit(cmd_parms *cmd, void *_dcfg,
|
||||||
const char *p1)
|
const char *p1)
|
||||||
{
|
{
|
||||||
@ -2029,6 +2109,22 @@ const command_rec module_directives[] = {
|
|||||||
"On or Off"
|
"On or Off"
|
||||||
),
|
),
|
||||||
|
|
||||||
|
AP_INIT_FLAG (
|
||||||
|
"StreamOutBodyInspection",
|
||||||
|
cmd_stream_outbody_inspection,
|
||||||
|
NULL,
|
||||||
|
CMD_SCOPE_ANY,
|
||||||
|
"On or Off"
|
||||||
|
),
|
||||||
|
|
||||||
|
AP_INIT_FLAG (
|
||||||
|
"StreamInBodyInspection",
|
||||||
|
cmd_stream_inbody_inspection,
|
||||||
|
NULL,
|
||||||
|
CMD_SCOPE_ANY,
|
||||||
|
"On or Off"
|
||||||
|
),
|
||||||
|
|
||||||
AP_INIT_TAKE1 (
|
AP_INIT_TAKE1 (
|
||||||
"SecCookieFormat",
|
"SecCookieFormat",
|
||||||
cmd_cookie_format,
|
cmd_cookie_format,
|
||||||
@ -2134,6 +2230,14 @@ const command_rec module_directives[] = {
|
|||||||
"On or Off"
|
"On or Off"
|
||||||
),
|
),
|
||||||
|
|
||||||
|
AP_INIT_TAKE1 (
|
||||||
|
"SecReadStateLimit",
|
||||||
|
cmd_conn_read_state_limit,
|
||||||
|
NULL,
|
||||||
|
CMD_SCOPE_ANY,
|
||||||
|
"maximum number of threads in READ_BUSY state per ip address"
|
||||||
|
),
|
||||||
|
|
||||||
AP_INIT_TAKE1 (
|
AP_INIT_TAKE1 (
|
||||||
"SecRequestBodyInMemoryLimit",
|
"SecRequestBodyInMemoryLimit",
|
||||||
cmd_request_body_inmemory_limit,
|
cmd_request_body_inmemory_limit,
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "modsecurity.h"
|
#include "modsecurity.h"
|
||||||
#include "apache2.h"
|
#include "apache2.h"
|
||||||
|
|
||||||
|
|
||||||
/* -- Input filter -- */
|
/* -- Input filter -- */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -89,7 +88,7 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
|||||||
return APR_EGENERAL;
|
return APR_EGENERAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunk) {
|
if (chunk && !msr->txcfg->stream_inbody_inspection) {
|
||||||
/* Copy the data we received in the chunk */
|
/* Copy the data we received in the chunk */
|
||||||
bucket = apr_bucket_heap_create(chunk->data, chunk->length, NULL,
|
bucket = apr_bucket_heap_create(chunk->data, chunk->length, NULL,
|
||||||
f->r->connection->bucket_alloc);
|
f->r->connection->bucket_alloc);
|
||||||
@ -117,6 +116,22 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
|||||||
if (msr->txcfg->debuglog_level >= 4) {
|
if (msr->txcfg->debuglog_level >= 4) {
|
||||||
msr_log(msr, 4, "Input filter: Forwarded %" APR_SIZE_T_FMT " bytes.", chunk->length);
|
msr_log(msr, 4, "Input filter: Forwarded %" APR_SIZE_T_FMT " bytes.", chunk->length);
|
||||||
}
|
}
|
||||||
|
} else if (msr->stream_input_data != NULL) {
|
||||||
|
|
||||||
|
bucket = apr_bucket_heap_create(msr->stream_input_data, msr->stream_input_length, NULL,
|
||||||
|
f->r->connection->bucket_alloc);
|
||||||
|
|
||||||
|
if (bucket == NULL) return APR_EGENERAL;
|
||||||
|
APR_BRIGADE_INSERT_TAIL(bb_out, bucket);
|
||||||
|
|
||||||
|
if (msr->txcfg->debuglog_level >= 4) {
|
||||||
|
msr_log(msr, 4, "Input stream filter: Forwarded %" APR_SIZE_T_FMT " bytes.", msr->msc_reqbody_disk_chunk->length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msr->txcfg->stream_inbody_inspection && msr->stream_input_data != NULL) {
|
||||||
|
free(msr->stream_input_data);
|
||||||
|
msr->stream_input_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
@ -259,7 +274,7 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
|
|||||||
|
|
||||||
if (msr->txcfg->debuglog_level >= 4) {
|
if (msr->txcfg->debuglog_level >= 4) {
|
||||||
msr_log(msr, 4, "Input filter: Completed receiving request body (length %" APR_SIZE_T_FMT ").",
|
msr_log(msr, 4, "Input filter: Completed receiving request body (length %" APR_SIZE_T_FMT ").",
|
||||||
msr->reqbody_length);
|
msr->reqbody_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
msr->if_status = IF_STATUS_WANTS_TO_RUN;
|
msr->if_status = IF_STATUS_WANTS_TO_RUN;
|
||||||
@ -409,9 +424,9 @@ static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
|
|||||||
rc = ap_pass_brigade(f->next, msr->of_brigade);
|
rc = ap_pass_brigade(f->next, msr->of_brigade);
|
||||||
if (rc != APR_SUCCESS) {
|
if (rc != APR_SUCCESS) {
|
||||||
/* TODO: These need to move to flags in 2.6. For now log them
|
/* TODO: These need to move to flags in 2.6. For now log them
|
||||||
* at level 3 so that they are not confusing users.
|
* at level 4 so that they are not confusing users.
|
||||||
*/
|
*/
|
||||||
int log_level = 3;
|
int log_level = 4;
|
||||||
|
|
||||||
if (msr->txcfg->debuglog_level >= log_level) {
|
if (msr->txcfg->debuglog_level >= log_level) {
|
||||||
switch(rc) {
|
switch(rc) {
|
||||||
@ -438,6 +453,34 @@ static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
|
|||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void inject_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
|
||||||
|
apr_bucket *b;
|
||||||
|
|
||||||
|
if (msr->txcfg->content_injection_enabled && msr->stream_output_data != NULL) {
|
||||||
|
apr_bucket *bucket_ci = NULL;
|
||||||
|
apr_bucket *bucket_eos = NULL;
|
||||||
|
|
||||||
|
bucket_ci = apr_bucket_heap_create(msr->stream_output_data,
|
||||||
|
msr->stream_output_length, NULL, f->r->connection->bucket_alloc);
|
||||||
|
|
||||||
|
for (b = APR_BRIGADE_FIRST(msr->of_brigade); b != APR_BRIGADE_SENTINEL(msr->of_brigade); b = APR_BUCKET_NEXT(b)) {
|
||||||
|
if(!APR_BUCKET_IS_METADATA(b))
|
||||||
|
apr_bucket_delete(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
APR_BRIGADE_INSERT_HEAD(msr->of_brigade, bucket_ci);
|
||||||
|
|
||||||
|
if (msr->txcfg->debuglog_level >= 9) {
|
||||||
|
msr_log(msr, 9, "Content Injection: Data reinjected bytes [%d]",msr->stream_output_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msr->stream_output_data != NULL) {
|
||||||
|
free(msr->stream_output_data);
|
||||||
|
msr->stream_output_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -486,6 +529,19 @@ static int flatten_response_body(modsec_rec *msr) {
|
|||||||
msr->resbody_data[msr->resbody_length] = '\0';
|
msr->resbody_data[msr->resbody_length] = '\0';
|
||||||
msr->resbody_status = RESBODY_STATUS_READ;
|
msr->resbody_status = RESBODY_STATUS_READ;
|
||||||
|
|
||||||
|
if (msr->txcfg->stream_outbody_inspection) {
|
||||||
|
msr->stream_output_data = (char *)malloc(msr->resbody_length+1);
|
||||||
|
msr->stream_output_length = msr->resbody_length+1;
|
||||||
|
|
||||||
|
if (msr->stream_output_data == NULL) {
|
||||||
|
msr_log(msr, 1, "Output filter: Stream Response body data memory allocation failed. Asked for: %" APR_SIZE_T_FMT,
|
||||||
|
msr->stream_output_length + 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
apr_cpystrn(msr->stream_output_data,msr->resbody_data,msr->stream_output_length);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,6 +857,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||||||
* (full-buffering only).
|
* (full-buffering only).
|
||||||
*/
|
*/
|
||||||
if ((msr->of_skipping == 0)&&(!msr->of_partial)) {
|
if ((msr->of_skipping == 0)&&(!msr->of_partial)) {
|
||||||
|
inject_content_to_of_brigade(msr,f);
|
||||||
prepend_content_to_of_brigade(msr, f);
|
prepend_content_to_of_brigade(msr, f);
|
||||||
|
|
||||||
/* Inject content into response (append & buffering). */
|
/* Inject content into response (append & buffering). */
|
||||||
|
@ -575,7 +575,6 @@ static int hook_post_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_t
|
|||||||
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
||||||
"%s configured.", MODSEC_MODULE_NAME_FULL);
|
"%s configured.", MODSEC_MODULE_NAME_FULL);
|
||||||
|
|
||||||
/* show libraries informations */
|
|
||||||
version(mp);
|
version(mp);
|
||||||
|
|
||||||
/* If we've changed the server signature make note of the original. */
|
/* If we've changed the server signature make note of the original. */
|
||||||
@ -802,6 +801,13 @@ static int hook_request_late(request_rec *r) {
|
|||||||
rc = perform_interception(msr);
|
rc = perform_interception(msr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(msr->txcfg->stream_inbody_inspection && msr->msc_reqbody_read) {
|
||||||
|
const char *clen = NULL;
|
||||||
|
clen = apr_psprintf(msr->mp,"%d",msr->stream_input_length);
|
||||||
|
if(clen)
|
||||||
|
apr_table_setn(r->headers_in, "Content-Length",clen);
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove the compression ability indications the client set,
|
/* Remove the compression ability indications the client set,
|
||||||
* but only if we need to disable backend compression.
|
* but only if we need to disable backend compression.
|
||||||
*/
|
*/
|
||||||
@ -1250,8 +1256,6 @@ static void register_hooks(apr_pool_t *mp) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Add the MODSEC_2.x compatibility defines */
|
/* Add the MODSEC_2.x compatibility defines */
|
||||||
*(char **)apr_array_push(ap_server_config_defines) = apr_pstrdup(mp, "MODSEC_2.5");
|
*(char **)apr_array_push(ap_server_config_defines) = apr_pstrdup(mp, "MODSEC_2.5");
|
||||||
|
|
||||||
@ -1311,8 +1315,10 @@ static void register_hooks(apr_pool_t *mp) {
|
|||||||
* mod_deflate = -1
|
* mod_deflate = -1
|
||||||
* mod_headers = 0
|
* mod_headers = 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ap_register_output_filter("MODSECURITY_OUT", output_filter,
|
ap_register_output_filter("MODSECURITY_OUT", output_filter,
|
||||||
NULL, AP_FTYPE_CONTENT_SET - 3);
|
NULL, AP_FTYPE_CONTENT_SET - 3);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Defined in apache2_config.c */
|
/* Defined in apache2_config.c */
|
||||||
|
@ -355,6 +355,8 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) {
|
|||||||
if (msr->request_headers_to_sanitize == NULL) return -1;
|
if (msr->request_headers_to_sanitize == NULL) return -1;
|
||||||
msr->response_headers_to_sanitize = apr_table_make(msr->mp, 16);
|
msr->response_headers_to_sanitize = apr_table_make(msr->mp, 16);
|
||||||
if (msr->response_headers_to_sanitize == NULL) return -1;
|
if (msr->response_headers_to_sanitize == NULL) return -1;
|
||||||
|
msr->pattern_to_sanitize = apr_table_make(msr->mp, 32);
|
||||||
|
if (msr->pattern_to_sanitize == NULL) return -1;
|
||||||
|
|
||||||
/* Initialise cookies */
|
/* Initialise cookies */
|
||||||
msr->request_cookies = apr_table_make(msr->mp, 16);
|
msr->request_cookies = apr_table_make(msr->mp, 16);
|
||||||
@ -543,6 +545,7 @@ static apr_status_t modsecurity_process_phase_response_body(modsec_rec *msr) {
|
|||||||
|
|
||||||
msr->time_phase4 = apr_time_now() - time_before;
|
msr->time_phase4 = apr_time_now() - time_before;
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ typedef struct msc_engine msc_engine;
|
|||||||
typedef struct msc_data_chunk msc_data_chunk;
|
typedef struct msc_data_chunk msc_data_chunk;
|
||||||
typedef struct msc_arg msc_arg;
|
typedef struct msc_arg msc_arg;
|
||||||
typedef struct msc_string msc_string;
|
typedef struct msc_string msc_string;
|
||||||
|
typedef struct msc_parm msc_parm;
|
||||||
|
|
||||||
#include "msc_release.h"
|
#include "msc_release.h"
|
||||||
#include "msc_logging.h"
|
#include "msc_logging.h"
|
||||||
@ -229,6 +230,11 @@ struct modsec_rec {
|
|||||||
char *resbody_data;
|
char *resbody_data;
|
||||||
unsigned int resbody_contains_html;
|
unsigned int resbody_contains_html;
|
||||||
|
|
||||||
|
apr_size_t stream_input_length;
|
||||||
|
char *stream_input_data;
|
||||||
|
apr_size_t stream_output_length;
|
||||||
|
char *stream_output_data;
|
||||||
|
|
||||||
apr_array_header_t *error_messages;
|
apr_array_header_t *error_messages;
|
||||||
apr_array_header_t *alerts;
|
apr_array_header_t *alerts;
|
||||||
|
|
||||||
@ -267,6 +273,7 @@ struct modsec_rec {
|
|||||||
apr_table_t *request_headers_to_sanitize;
|
apr_table_t *request_headers_to_sanitize;
|
||||||
apr_table_t *response_headers_to_sanitize;
|
apr_table_t *response_headers_to_sanitize;
|
||||||
apr_table_t *request_cookies;
|
apr_table_t *request_cookies;
|
||||||
|
apr_table_t *pattern_to_sanitize;
|
||||||
|
|
||||||
unsigned int urlencoded_error;
|
unsigned int urlencoded_error;
|
||||||
unsigned int inbound_error;
|
unsigned int inbound_error;
|
||||||
@ -473,6 +480,10 @@ struct directory_config {
|
|||||||
/* Content injection. */
|
/* Content injection. */
|
||||||
int content_injection_enabled;
|
int content_injection_enabled;
|
||||||
|
|
||||||
|
/* Stream Inspection */
|
||||||
|
int stream_inbody_inspection;
|
||||||
|
int stream_outbody_inspection;
|
||||||
|
|
||||||
/* Geo Lookup */
|
/* Geo Lookup */
|
||||||
geo_db *geo;
|
geo_db *geo;
|
||||||
|
|
||||||
@ -535,6 +546,11 @@ struct msc_string {
|
|||||||
unsigned int value_len;
|
unsigned int value_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct msc_parm {
|
||||||
|
char *value;
|
||||||
|
unsigned int pad_1;
|
||||||
|
unsigned int pad_2;
|
||||||
|
};
|
||||||
|
|
||||||
/* Engine functions */
|
/* Engine functions */
|
||||||
|
|
||||||
|
@ -343,15 +343,41 @@ int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **erro
|
|||||||
/* NOTE: This is hard-coded for size 3 records */
|
/* NOTE: This is hard-coded for size 3 records */
|
||||||
/* Left */
|
/* Left */
|
||||||
if ((ipnum & (1 << level)) == 0) {
|
if ((ipnum & (1 << level)) == 0) {
|
||||||
|
//rec_val = buf[0] +
|
||||||
|
// (buf[1] << 8) +
|
||||||
|
// (buf[2] << 16);
|
||||||
rec_val = (buf[3*0 + 0] << (0*8)) +
|
rec_val = (buf[3*0 + 0] << (0*8)) +
|
||||||
(buf[3*0 + 1] << (1*8)) +
|
(buf[3*0 + 1] << (1*8)) +
|
||||||
(buf[3*0 + 2] << (2*8));
|
(buf[3*0 + 2] << (2*8));
|
||||||
|
/*j = 3;
|
||||||
|
p = &buf[2*j];
|
||||||
|
x = 0;
|
||||||
|
do {
|
||||||
|
x <<= 8;
|
||||||
|
x += *(--p);
|
||||||
|
} while ( --j );
|
||||||
|
rec_val = x;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
/* Right */
|
/* Right */
|
||||||
else {
|
else {
|
||||||
|
//rec_val = buf[3] +
|
||||||
|
// (buf[4] << 8) +
|
||||||
|
// (buf[5] << 16);
|
||||||
rec_val = (buf[3*1 + 0] << (0*8)) +
|
rec_val = (buf[3*1 + 0] << (0*8)) +
|
||||||
(buf[3*1 + 1] << (1*8)) +
|
(buf[3*1 + 1] << (1*8)) +
|
||||||
(buf[3*1 + 2] << (2*8));
|
(buf[3*1 + 2] << (2*8));
|
||||||
|
|
||||||
|
/*j = 3;
|
||||||
|
p = &buf[1*j];
|
||||||
|
x = 0;
|
||||||
|
do {
|
||||||
|
x <<= 8;
|
||||||
|
x += *(--p);
|
||||||
|
} while ( --j );
|
||||||
|
|
||||||
|
rec_val = x;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are past the country offset, then we are done */
|
/* If we are past the country offset, then we are done */
|
||||||
|
@ -326,10 +326,16 @@ static char *create_auditlog_boundary(request_rec *r) {
|
|||||||
* that have been marked as sensitive.
|
* that have been marked as sensitive.
|
||||||
*/
|
*/
|
||||||
static void sanitize_request_line(modsec_rec *msr) {
|
static void sanitize_request_line(modsec_rec *msr) {
|
||||||
const apr_array_header_t *tarr;
|
const apr_array_header_t *tarr = NULL;
|
||||||
const apr_table_entry_t *telts;
|
const apr_table_entry_t *telts = NULL;
|
||||||
int i;
|
const apr_array_header_t *tarr_pattern = NULL;
|
||||||
|
const apr_table_entry_t *telts_pattern = NULL;
|
||||||
|
msc_parm *mparm = NULL;
|
||||||
|
int i, k;
|
||||||
char *qspos;
|
char *qspos;
|
||||||
|
char *buf = NULL;
|
||||||
|
int sanitized_partial = 0;
|
||||||
|
int sanitize_matched = 0;
|
||||||
|
|
||||||
/* Locate the query string. */
|
/* Locate the query string. */
|
||||||
qspos = strstr(msr->request_line, "?");
|
qspos = strstr(msr->request_line, "?");
|
||||||
@ -343,8 +349,9 @@ static void sanitize_request_line(modsec_rec *msr) {
|
|||||||
msc_arg *arg = (msc_arg *)telts[i].val;
|
msc_arg *arg = (msc_arg *)telts[i].val;
|
||||||
/* Only look at the parameters that appeared in the query string. */
|
/* Only look at the parameters that appeared in the query string. */
|
||||||
if (strcmp(arg->origin, "QUERY_STRING") == 0) {
|
if (strcmp(arg->origin, "QUERY_STRING") == 0) {
|
||||||
|
char *pat = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
int j;
|
int j, arg_min, arg_max;
|
||||||
|
|
||||||
/* Go to the beginning of the parameter. */
|
/* Go to the beginning of the parameter. */
|
||||||
p = qspos;
|
p = qspos;
|
||||||
@ -352,23 +359,65 @@ static void sanitize_request_line(modsec_rec *msr) {
|
|||||||
while((*p != '\0')&&(j--)) p++;
|
while((*p != '\0')&&(j--)) p++;
|
||||||
if (*p == '\0') {
|
if (*p == '\0') {
|
||||||
msr_log(msr, 1, "Unable to sanitize variable \"%s\" at offset %u of QUERY_STRING"
|
msr_log(msr, 1, "Unable to sanitize variable \"%s\" at offset %u of QUERY_STRING"
|
||||||
"because the request line is too short.",
|
"because the request line is too short.",
|
||||||
log_escape_ex(msr->mp, arg->name, arg->name_len),
|
log_escape_ex(msr->mp, arg->name, arg->name_len),
|
||||||
arg->value_origin_offset);
|
arg->value_origin_offset);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write over the value. */
|
tarr_pattern = apr_table_elts(msr->pattern_to_sanitize);
|
||||||
j = arg->value_origin_len;
|
telts_pattern = (const apr_table_entry_t*)tarr_pattern->elts;
|
||||||
while((*p != '\0')&&(j--)) {
|
|
||||||
*p++ = '*';
|
sanitized_partial = 0;
|
||||||
|
sanitize_matched = 0;
|
||||||
|
buf = apr_psprintf(msr->mp, "%s",p);
|
||||||
|
for ( k = 0; k < tarr_pattern->nelts; k++) {
|
||||||
|
if(strncmp(telts_pattern[k].key,arg->name,strlen(arg->name)) ==0 ) {
|
||||||
|
mparm = (msc_parm *)telts_pattern[k].val;
|
||||||
|
pat = strstr(buf,mparm->value);
|
||||||
|
if(mparm->pad_1 == -1)
|
||||||
|
sanitize_matched = 1;
|
||||||
|
|
||||||
|
if (pat != NULL) {
|
||||||
|
j = strlen(mparm->value);
|
||||||
|
arg_min = j;
|
||||||
|
arg_max = 1;
|
||||||
|
while((*pat != '\0')&&(j--)) {
|
||||||
|
if(arg_max > mparm->pad_2) {
|
||||||
|
int off = (strlen(mparm->value) - arg_max);
|
||||||
|
int pos = (mparm->pad_1-1);
|
||||||
|
if(off > pos) {
|
||||||
|
*pat = '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_max++;
|
||||||
|
arg_min--;
|
||||||
|
*pat++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sanitized_partial = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (*p == '\0') {
|
|
||||||
msr_log(msr, 1, "Unable to sanitize variable \"%s\" at offset %u (size %d) "
|
if(sanitized_partial == 1 && sanitize_matched == 0) {
|
||||||
"of QUERY_STRING because the request line is too short.",
|
while(*buf != '\0') {
|
||||||
log_escape_ex(msr->mp, arg->name, arg->name_len),
|
*p++ = *buf++;
|
||||||
arg->value_origin_offset, arg->value_origin_len);
|
}
|
||||||
continue;
|
continue;
|
||||||
|
} else {
|
||||||
|
/* Write over the value. */
|
||||||
|
j = arg->value_origin_len;
|
||||||
|
while((*p != '\0')&&(j--)) {
|
||||||
|
*p++ = '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '\0') {
|
||||||
|
msr_log(msr, 1, "Unable to sanitize variable \"%s\" at offset %u (size %d) "
|
||||||
|
"of QUERY_STRING because the request line is too short.",
|
||||||
|
log_escape_ex(msr->mp, arg->name, arg->name_len),
|
||||||
|
arg->value_origin_offset, arg->value_origin_len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,7 +500,7 @@ msre_rule *return_chained_rule(const msre_rule *current, modsec_rec *msr) {
|
|||||||
for (i = 0; i < arr->nelts; i++) {
|
for (i = 0; i < arr->nelts; i++) {
|
||||||
rule = rules[i];
|
rule = rules[i];
|
||||||
if (rule != NULL) {
|
if (rule != NULL) {
|
||||||
if (strcmp(current->unparsed,rule->unparsed) == 0) {
|
if (strncmp(current->unparsed,rule->unparsed,strlen(rule->unparsed)) == 0) {
|
||||||
if (i < arr->nelts -1) {
|
if (i < arr->nelts -1) {
|
||||||
next_rule = rules[i+1];
|
next_rule = rules[i+1];
|
||||||
} else {
|
} else {
|
||||||
@ -482,7 +531,7 @@ int chained_is_matched(modsec_rec *msr, const msre_rule *next_rule) {
|
|||||||
|
|
||||||
for (i = 0; i < msr->matched_rules->nelts; i++) {
|
for (i = 0; i < msr->matched_rules->nelts; i++) {
|
||||||
rule = ((msre_rule **)msr->matched_rules->elts)[i];
|
rule = ((msre_rule **)msr->matched_rules->elts)[i];
|
||||||
if (rule != NULL && (strcmp(rule->unparsed,next_rule->unparsed) == 0))
|
if (rule != NULL && (strncmp(rule->unparsed,next_rule->unparsed,strlen(next_rule->unparsed)) == 0))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,6 +544,8 @@ int chained_is_matched(modsec_rec *msr, const msre_rule *next_rule) {
|
|||||||
void sec_audit_logger(modsec_rec *msr) {
|
void sec_audit_logger(modsec_rec *msr) {
|
||||||
const apr_array_header_t *arr = NULL;
|
const apr_array_header_t *arr = NULL;
|
||||||
apr_table_entry_t *te = NULL;
|
apr_table_entry_t *te = NULL;
|
||||||
|
const apr_array_header_t *tarr_pattern = NULL;
|
||||||
|
const apr_table_entry_t *telts_pattern = NULL;
|
||||||
char *str1 = NULL, *str2 = NULL, *text = NULL;
|
char *str1 = NULL, *str2 = NULL, *text = NULL;
|
||||||
const msre_rule *rule = NULL, *next_rule = NULL;
|
const msre_rule *rule = NULL, *next_rule = NULL;
|
||||||
apr_size_t nbytes, nbytes_written;
|
apr_size_t nbytes, nbytes_written;
|
||||||
@ -504,7 +555,10 @@ void sec_audit_logger(modsec_rec *msr) {
|
|||||||
int wrote_response_body = 0;
|
int wrote_response_body = 0;
|
||||||
char *entry_filename, *entry_basename;
|
char *entry_filename, *entry_basename;
|
||||||
apr_status_t rc;
|
apr_status_t rc;
|
||||||
int i, limit;
|
int i, limit, k, sanitized_partial, j;
|
||||||
|
char *buf = NULL, *pat = NULL;
|
||||||
|
msc_parm *mparm = NULL;
|
||||||
|
int arg_min, arg_max, sanitize_matched;
|
||||||
|
|
||||||
/* the boundary is used by both audit log types */
|
/* the boundary is used by both audit log types */
|
||||||
msr->new_auditlog_boundary = create_auditlog_boundary(msr->r);
|
msr->new_auditlog_boundary = create_auditlog_boundary(msr->r);
|
||||||
@ -621,12 +675,49 @@ void sec_audit_logger(modsec_rec *msr) {
|
|||||||
|
|
||||||
arr = apr_table_elts(msr->request_headers);
|
arr = apr_table_elts(msr->request_headers);
|
||||||
te = (apr_table_entry_t *)arr->elts;
|
te = (apr_table_entry_t *)arr->elts;
|
||||||
|
|
||||||
|
tarr_pattern = apr_table_elts(msr->pattern_to_sanitize);
|
||||||
|
telts_pattern = (const apr_table_entry_t*)tarr_pattern->elts;
|
||||||
|
|
||||||
for (i = 0; i < arr->nelts; i++) {
|
for (i = 0; i < arr->nelts; i++) {
|
||||||
|
sanitized_partial = 0;
|
||||||
|
sanitize_matched = 0;
|
||||||
text = apr_psprintf(msr->mp, "%s: %s\n", te[i].key, te[i].val);
|
text = apr_psprintf(msr->mp, "%s: %s\n", te[i].key, te[i].val);
|
||||||
/* Do we need to sanitize this request header? */
|
|
||||||
if (apr_table_get(msr->request_headers_to_sanitize, te[i].key) != NULL) {
|
if (apr_table_get(msr->request_headers_to_sanitize, te[i].key) != NULL) {
|
||||||
/* Yes, sanitize it. */
|
buf = apr_psprintf(msr->mp, "%s",text+strlen(te[i].key)+2);
|
||||||
memset(text + strlen(te[i].key) + 2, '*', strlen(te[i].val));
|
|
||||||
|
for ( k = 0; k < tarr_pattern->nelts; k++) {
|
||||||
|
if(strncmp(telts_pattern[k].key,te[i].key,strlen(te[i].key)) ==0 ) {
|
||||||
|
mparm = (msc_parm *)telts_pattern[k].val;
|
||||||
|
if(mparm->pad_1 == -1)
|
||||||
|
sanitize_matched = 1;
|
||||||
|
pat = strstr(buf,mparm->value);
|
||||||
|
if (pat != NULL) {
|
||||||
|
j = strlen(mparm->value);
|
||||||
|
arg_min = j;
|
||||||
|
arg_max = 1;
|
||||||
|
while((*pat != '\0')&&(j--)) {
|
||||||
|
if(arg_max > mparm->pad_2) {
|
||||||
|
int off = strlen(mparm->value) - arg_max;
|
||||||
|
int pos = mparm->pad_1-1;
|
||||||
|
if(off > pos) {
|
||||||
|
*pat = '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_max++;
|
||||||
|
arg_min--;
|
||||||
|
*pat++;
|
||||||
|
}
|
||||||
|
sanitized_partial = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sanitized_partial == 1 && sanitize_matched == 0) {
|
||||||
|
text = apr_psprintf(msr->mp, "%s: %s\n", te[i].key, buf);
|
||||||
|
} else {
|
||||||
|
memset(text + strlen(te[i].key) + 2, '*', strlen(te[i].val));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sec_auditlog_write(msr, text, strlen(text));
|
sec_auditlog_write(msr, text, strlen(text));
|
||||||
}
|
}
|
||||||
@ -820,10 +911,10 @@ void sec_audit_logger(modsec_rec *msr) {
|
|||||||
if (msr->response_headers_sent) {
|
if (msr->response_headers_sent) {
|
||||||
if (msr->status_line != NULL) {
|
if (msr->status_line != NULL) {
|
||||||
text = apr_psprintf(msr->mp, "%s %s\n", msr->response_protocol,
|
text = apr_psprintf(msr->mp, "%s %s\n", msr->response_protocol,
|
||||||
msr->status_line);
|
msr->status_line);
|
||||||
} else {
|
} else {
|
||||||
text = apr_psprintf(msr->mp, "%s %u\n", msr->response_protocol,
|
text = apr_psprintf(msr->mp, "%s %u\n", msr->response_protocol,
|
||||||
msr->response_status);
|
msr->response_status);
|
||||||
}
|
}
|
||||||
sec_auditlog_write(msr, text, strlen(text));
|
sec_auditlog_write(msr, text, strlen(text));
|
||||||
|
|
||||||
@ -831,18 +922,57 @@ void sec_audit_logger(modsec_rec *msr) {
|
|||||||
|
|
||||||
arr = apr_table_elts(msr->response_headers);
|
arr = apr_table_elts(msr->response_headers);
|
||||||
te = (apr_table_entry_t *)arr->elts;
|
te = (apr_table_entry_t *)arr->elts;
|
||||||
|
|
||||||
|
tarr_pattern = apr_table_elts(msr->pattern_to_sanitize);
|
||||||
|
telts_pattern = (const apr_table_entry_t*)tarr_pattern->elts;
|
||||||
|
|
||||||
for (i = 0; i < arr->nelts; i++) {
|
for (i = 0; i < arr->nelts; i++) {
|
||||||
|
sanitized_partial = 0;
|
||||||
|
sanitize_matched = 0;
|
||||||
text = apr_psprintf(msr->mp, "%s: %s\n", te[i].key, te[i].val);
|
text = apr_psprintf(msr->mp, "%s: %s\n", te[i].key, te[i].val);
|
||||||
/* Do we need to sanitize this response header? */
|
|
||||||
if (apr_table_get(msr->response_headers_to_sanitize, te[i].key) != NULL) {
|
if (apr_table_get(msr->response_headers_to_sanitize, te[i].key) != NULL) {
|
||||||
/* Yes, sanitize it. */
|
buf = apr_psprintf(msr->mp, "%s",text+strlen(te[i].key)+2);
|
||||||
memset(text + strlen(te[i].key) + 2, '*', strlen(te[i].val));
|
|
||||||
|
for ( k = 0; k < tarr_pattern->nelts; k++) {
|
||||||
|
if(strncmp(telts_pattern[k].key,te[i].key,strlen(te[i].key)) ==0 ) {
|
||||||
|
mparm = (msc_parm *)telts_pattern[k].val;
|
||||||
|
if(mparm->pad_1 == -1)
|
||||||
|
sanitize_matched = 1;
|
||||||
|
pat = strstr(buf,mparm->value);
|
||||||
|
if (pat != NULL) {
|
||||||
|
j = strlen(mparm->value);
|
||||||
|
arg_min = j;
|
||||||
|
arg_max = 1;
|
||||||
|
while((*pat != '\0')&&(j--)) {
|
||||||
|
if(arg_max > mparm->pad_2) {
|
||||||
|
int off = strlen(mparm->value) - arg_max;
|
||||||
|
int pos = mparm->pad_1-1;
|
||||||
|
if(off > pos) {
|
||||||
|
*pat = '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_max++;
|
||||||
|
arg_min--;
|
||||||
|
*pat++;
|
||||||
|
}
|
||||||
|
sanitized_partial = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sanitized_partial == 1 && sanitize_matched == 0) {
|
||||||
|
text = apr_psprintf(msr->mp, "%s: %s\n", te[i].key, buf);
|
||||||
|
} else {
|
||||||
|
memset(text + strlen(te[i].key) + 2, '*', strlen(te[i].val));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sec_auditlog_write(msr, text, strlen(text));
|
sec_auditlog_write(msr, text, strlen(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apr_table_clear(msr->pattern_to_sanitize);
|
||||||
|
|
||||||
/* AUDITLOG_PART_RESPONSE_BODY */
|
/* AUDITLOG_PART_RESPONSE_BODY */
|
||||||
|
|
||||||
if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_RESPONSE_BODY) != NULL) {
|
if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_RESPONSE_BODY) != NULL) {
|
||||||
|
@ -308,7 +308,6 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
|
|||||||
msre_reqbody_processor_metadata *metadata =
|
msre_reqbody_processor_metadata *metadata =
|
||||||
(msre_reqbody_processor_metadata *)apr_table_get(msr->modsecurity->msre->reqbody_processors, msr->msc_reqbody_processor);
|
(msre_reqbody_processor_metadata *)apr_table_get(msr->modsecurity->msre->reqbody_processors, msr->msc_reqbody_processor);
|
||||||
|
|
||||||
|
|
||||||
if (metadata != NULL) {
|
if (metadata != NULL) {
|
||||||
if ( (metadata->process != NULL)
|
if ( (metadata->process != NULL)
|
||||||
&& (metadata->process(msr, data, length, &my_error_msg) < 0))
|
&& (metadata->process(msr, data, length, &my_error_msg) < 0))
|
||||||
@ -384,6 +383,51 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static apr_status_t modsecurity_request_body_to_stream(modsec_rec *msr, char **error_msg) {
|
||||||
|
msc_data_chunk **chunks;
|
||||||
|
char *d;
|
||||||
|
int i, sofar;
|
||||||
|
|
||||||
|
*error_msg = NULL;
|
||||||
|
|
||||||
|
/* Allocate a buffer large enough to hold the request body. */
|
||||||
|
|
||||||
|
if (msr->msc_reqbody_length + 1 == 0) {
|
||||||
|
*error_msg = apr_psprintf(msr->mp, "Internal error, request body length will overflow the stream buffer: %u",
|
||||||
|
msr->msc_reqbody_length);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msr->stream_input_length = msr->msc_reqbody_length;
|
||||||
|
|
||||||
|
msr->stream_input_data = malloc(msr->stream_input_length + 1);
|
||||||
|
if (msr->stream_input_data== NULL) {
|
||||||
|
*error_msg = apr_psprintf(msr->mp, "Unable to allocate memory to hold request body on stream. Asked for %u bytes.",
|
||||||
|
msr->stream_input_length + 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msr->stream_input_data[msr->stream_input_length] = '\0';
|
||||||
|
|
||||||
|
/* Copy the data we keep in chunks into the new buffer. */
|
||||||
|
|
||||||
|
sofar = 0;
|
||||||
|
d = msr->stream_input_data;
|
||||||
|
chunks = (msc_data_chunk **)msr->msc_reqbody_chunks->elts;
|
||||||
|
for(i = 0; i < msr->msc_reqbody_chunks->nelts; i++) {
|
||||||
|
if (sofar + chunks[i]->length <= msr->stream_input_length) {
|
||||||
|
memcpy(d, chunks[i]->data, chunks[i]->length);
|
||||||
|
d += chunks[i]->length;
|
||||||
|
sofar += chunks[i]->length;
|
||||||
|
} else {
|
||||||
|
*error_msg = apr_psprintf(msr->mp, "Internal error, request body buffer overflow.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace a bunch of chunks holding a request body with a single large chunk.
|
* Replace a bunch of chunks holding a request body with a single large chunk.
|
||||||
*/
|
*/
|
||||||
@ -498,13 +542,15 @@ apr_status_t modsecurity_request_body_end(modsec_rec *msr, char **error_msg) {
|
|||||||
/* Note that we've read the body. */
|
/* Note that we've read the body. */
|
||||||
msr->msc_reqbody_read = 1;
|
msr->msc_reqbody_read = 1;
|
||||||
|
|
||||||
|
if (msr->txcfg->stream_inbody_inspection)
|
||||||
|
modsecurity_request_body_to_stream(msr, error_msg);
|
||||||
|
|
||||||
/* Finalise body processing. */
|
/* Finalise body processing. */
|
||||||
if ((msr->msc_reqbody_processor != NULL) && (msr->msc_reqbody_error == 0)) {
|
if ((msr->msc_reqbody_processor != NULL) && (msr->msc_reqbody_error == 0)) {
|
||||||
char *my_error_msg = NULL;
|
char *my_error_msg = NULL;
|
||||||
msre_reqbody_processor_metadata *metadata =
|
msre_reqbody_processor_metadata *metadata =
|
||||||
(msre_reqbody_processor_metadata *)apr_table_get(msr->modsecurity->msre->reqbody_processors, msr->msc_reqbody_processor);
|
(msre_reqbody_processor_metadata *)apr_table_get(msr->modsecurity->msre->reqbody_processors, msr->msc_reqbody_processor);
|
||||||
|
|
||||||
|
|
||||||
if (metadata != NULL) {
|
if (metadata != NULL) {
|
||||||
if ( (metadata->complete != NULL)
|
if ( (metadata->complete != NULL)
|
||||||
&& (metadata->complete(msr, &my_error_msg) < 0))
|
&& (metadata->complete(msr, &my_error_msg) < 0))
|
||||||
|
@ -580,6 +580,8 @@ msre_actionset *msre_actionset_create(msre_engine *engine, const char *text,
|
|||||||
actionset->phase = NOT_SET;
|
actionset->phase = NOT_SET;
|
||||||
actionset->severity = -1;
|
actionset->severity = -1;
|
||||||
actionset->rule = NOT_SET_P;
|
actionset->rule = NOT_SET_P;
|
||||||
|
actionset->arg_max = -1;
|
||||||
|
actionset->arg_min = -1;
|
||||||
|
|
||||||
/* Flow */
|
/* Flow */
|
||||||
actionset->is_chained = NOT_SET;
|
actionset->is_chained = NOT_SET;
|
||||||
@ -660,6 +662,8 @@ msre_actionset *msre_actionset_merge(msre_engine *engine, msre_actionset *parent
|
|||||||
if (child->severity != NOT_SET) merged->severity = child->severity;
|
if (child->severity != NOT_SET) merged->severity = child->severity;
|
||||||
if (child->phase != NOT_SET) merged->phase = child->phase;
|
if (child->phase != NOT_SET) merged->phase = child->phase;
|
||||||
if (child->rule != NOT_SET_P) merged->rule = child->rule;
|
if (child->rule != NOT_SET_P) merged->rule = child->rule;
|
||||||
|
if (child->arg_min != NOT_SET) merged->arg_min = child->arg_min;
|
||||||
|
if (child->arg_max != NOT_SET) merged->arg_max = child->arg_max;
|
||||||
|
|
||||||
/* Flow */
|
/* Flow */
|
||||||
merged->is_chained = child->is_chained;
|
merged->is_chained = child->is_chained;
|
||||||
@ -714,6 +718,8 @@ void msre_actionset_set_defaults(msre_actionset *actionset) {
|
|||||||
if (actionset->phase == NOT_SET) actionset->phase = 2;
|
if (actionset->phase == NOT_SET) actionset->phase = 2;
|
||||||
if (actionset->severity == -1) {} /* leave at -1 */
|
if (actionset->severity == -1) {} /* leave at -1 */
|
||||||
if (actionset->rule == NOT_SET_P) actionset->rule = NULL;
|
if (actionset->rule == NOT_SET_P) actionset->rule = NULL;
|
||||||
|
if (actionset->arg_max == NOT_SET) actionset->arg_max = -1;
|
||||||
|
if (actionset->arg_min == NOT_SET) actionset->arg_min = -1;
|
||||||
|
|
||||||
/* Flow */
|
/* Flow */
|
||||||
if (actionset->is_chained == NOT_SET) actionset->is_chained = 0;
|
if (actionset->is_chained == NOT_SET) actionset->is_chained = 0;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
* directly using the email address support@trustwave.com.
|
* directly using the email address support@trustwave.com.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MSC_RE_H_
|
#ifndef _MSC_RE_H_
|
||||||
#define _MSC_RE_H_
|
#define _MSC_RE_H_
|
||||||
|
|
||||||
@ -174,6 +175,9 @@ struct msre_rule {
|
|||||||
/* Compiled Lua script. */
|
/* Compiled Lua script. */
|
||||||
msc_script *script;
|
msc_script *script;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ap_regex_t *sub_regex;
|
||||||
|
char *sub_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
char DSOLOCAL *msre_rule_generate_unparsed(apr_pool_t *pool, const msre_rule *rule, const char *targets, const char *args, const char *actions);
|
char DSOLOCAL *msre_rule_generate_unparsed(apr_pool_t *pool, const msre_rule *rule, const char *targets, const char *args, const char *actions);
|
||||||
@ -284,6 +288,8 @@ struct msre_actionset {
|
|||||||
int severity;
|
int severity;
|
||||||
int phase;
|
int phase;
|
||||||
msre_rule *rule;
|
msre_rule *rule;
|
||||||
|
int arg_min;
|
||||||
|
int arg_max;
|
||||||
|
|
||||||
/* Flow */
|
/* Flow */
|
||||||
int is_chained;
|
int is_chained;
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
#include "re.h"
|
#include "re.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "apr_lib.h"
|
||||||
|
#include "apr_strmatch.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register action with the engine.
|
* Register action with the engine.
|
||||||
@ -344,7 +347,6 @@ apr_status_t collection_original_setvar(modsec_rec *msr, const char *col_name, c
|
|||||||
msr_log(msr, 9, "Original collection variable: %s.%s = \"%s\"", col_name, var_name,
|
msr_log(msr, 9, "Original collection variable: %s.%s = \"%s\"", col_name, var_name,
|
||||||
log_escape_ex(msr->mp, orig_var->value, orig_var->value_len));
|
log_escape_ex(msr->mp, orig_var->value, orig_var->value_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,6 +408,34 @@ static apr_status_t msre_action_logdata_init(msre_engine *engine, msre_actionset
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SanitizeMatchedBytes init */
|
||||||
|
|
||||||
|
static apr_status_t msre_action_sanitizeMatchedBytes_init(msre_engine *engine,
|
||||||
|
msre_actionset *actionset, msre_action *action)
|
||||||
|
{
|
||||||
|
char *parse_parm = NULL;
|
||||||
|
char *ac_param = NULL;
|
||||||
|
char *savedptr = NULL;
|
||||||
|
int arg_min = 0;
|
||||||
|
int arg_max = 0;
|
||||||
|
|
||||||
|
if (action->param != NULL && strlen(action->param) == 3) {
|
||||||
|
|
||||||
|
ac_param = apr_pstrdup(engine->mp, action->param);
|
||||||
|
parse_parm = apr_strtok(ac_param,"/",&savedptr);
|
||||||
|
|
||||||
|
if(apr_isdigit(*parse_parm) && apr_isdigit(*savedptr)) {
|
||||||
|
arg_max = atoi(parse_parm);
|
||||||
|
arg_min = atoi(savedptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actionset->arg_min = arg_min;
|
||||||
|
actionset->arg_max = arg_max;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* severity */
|
/* severity */
|
||||||
|
|
||||||
static apr_status_t msre_action_severity_init(msre_engine *engine,
|
static apr_status_t msre_action_severity_init(msre_engine *engine,
|
||||||
@ -1053,7 +1083,9 @@ static apr_status_t msre_action_sanitizeMatched_execute(modsec_rec *msr, apr_poo
|
|||||||
const char *sargname = NULL;
|
const char *sargname = NULL;
|
||||||
const apr_array_header_t *tarr;
|
const apr_array_header_t *tarr;
|
||||||
const apr_table_entry_t *telts;
|
const apr_table_entry_t *telts;
|
||||||
int i, type = 0;
|
const apr_array_header_t *tarr_pattern;
|
||||||
|
const apr_table_entry_t *telts_pattern;
|
||||||
|
int i, type = 0, k;
|
||||||
msc_string *mvar = msr->matched_var;
|
msc_string *mvar = msr->matched_var;
|
||||||
|
|
||||||
if (mvar->name_len == 0) return 0;
|
if (mvar->name_len == 0) return 0;
|
||||||
@ -1090,7 +1122,6 @@ static apr_status_t msre_action_sanitizeMatched_execute(modsec_rec *msr, apr_poo
|
|||||||
msr_log(msr, 3, "sanitizeMatched: Don't know how to handle variable: %s",
|
msr_log(msr, 3, "sanitizeMatched: Don't know how to handle variable: %s",
|
||||||
mvar->name);
|
mvar->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2294,6 +2325,19 @@ void msre_engine_register_default_actions(msre_engine *engine) {
|
|||||||
msre_action_sanitizeArg_execute
|
msre_action_sanitizeArg_execute
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* sanitiseMatchedBytes */
|
||||||
|
msre_engine_action_register(engine,
|
||||||
|
"sanitizeMatchedBytes",
|
||||||
|
ACTION_NON_DISRUPTIVE,
|
||||||
|
0, 1,
|
||||||
|
NO_PLUS_MINUS,
|
||||||
|
ACTION_CARDINALITY_MANY,
|
||||||
|
ACTION_CGROUP_NONE,
|
||||||
|
NULL,
|
||||||
|
msre_action_sanitizeMatchedBytes_init,
|
||||||
|
msre_action_sanitizeMatched_execute
|
||||||
|
);
|
||||||
|
|
||||||
/* sanitizeArg */
|
/* sanitizeArg */
|
||||||
msre_engine_action_register(engine,
|
msre_engine_action_register(engine,
|
||||||
"sanitizeArg",
|
"sanitizeArg",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "apr_lib.h"
|
#include "apr_lib.h"
|
||||||
#include "apr_strmatch.h"
|
#include "apr_strmatch.h"
|
||||||
#include "acmp.h"
|
#include "acmp.h"
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -72,6 +73,162 @@ static int msre_op_nomatch_execute(modsec_rec *msr, msre_rule *rule,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rsub */
|
||||||
|
|
||||||
|
static int msre_op_rsub_param_init(msre_rule *rule, char **error_msg) {
|
||||||
|
const char *errptr = NULL;
|
||||||
|
int erroffset;
|
||||||
|
ap_regex_t *regex;
|
||||||
|
const char *pattern = NULL;
|
||||||
|
const char *line = NULL;
|
||||||
|
char *reg_pattern = NULL;
|
||||||
|
char *replace = NULL;
|
||||||
|
char *flags = NULL;
|
||||||
|
char *data;
|
||||||
|
char delim;
|
||||||
|
int ignore_case = 0;
|
||||||
|
|
||||||
|
line = rule->op_param;
|
||||||
|
|
||||||
|
if (apr_tolower(*line) != 's') {
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Error rsub operator format, must be s/// pattern",
|
||||||
|
erroffset, errptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = apr_pstrdup(rule->ruleset->mp, line);
|
||||||
|
delim = *++data;
|
||||||
|
if (delim)
|
||||||
|
reg_pattern = ++data;
|
||||||
|
if (reg_pattern) {
|
||||||
|
if (*data != delim) {
|
||||||
|
while (*++data && *data != delim);
|
||||||
|
}
|
||||||
|
if (*data) {
|
||||||
|
*data = '\0';
|
||||||
|
replace = ++data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (replace) {
|
||||||
|
if (*data != delim) {
|
||||||
|
while (*++data && *data != delim);
|
||||||
|
}
|
||||||
|
if (*data) {
|
||||||
|
*data = '\0';
|
||||||
|
flags = ++data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!delim || !reg_pattern || !*reg_pattern || !replace) {
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Error rsub operator format - must be s/regex/str/[flags]",
|
||||||
|
erroffset, errptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
while (*flags) {
|
||||||
|
delim = apr_tolower(*flags);
|
||||||
|
if (delim == 'i')
|
||||||
|
ignore_case = 1;
|
||||||
|
else
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Regex flag not supported",
|
||||||
|
erroffset, errptr);
|
||||||
|
flags++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_msg == NULL) return -1;
|
||||||
|
*error_msg = NULL;
|
||||||
|
|
||||||
|
pattern = apr_pstrdup(rule->ruleset->mp, reg_pattern);
|
||||||
|
rule->sub_str = apr_pstrdup(rule->ruleset->mp, replace);
|
||||||
|
|
||||||
|
regex = ap_pregcomp(rule->ruleset->mp, pattern, AP_REG_EXTENDED |
|
||||||
|
(ignore_case ? AP_REG_ICASE : 0));
|
||||||
|
|
||||||
|
rule->sub_regex = regex;
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msre_op_rsub_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
|
||||||
|
ap_regex_t *regex = rule->sub_regex;
|
||||||
|
char *offset = NULL;
|
||||||
|
int sub = 0, so = 0, p_len = 0;
|
||||||
|
char *replace = NULL;
|
||||||
|
char *data = NULL;
|
||||||
|
int size = var->value_len;
|
||||||
|
int output_body = 0, input_body = 0, count = 0;
|
||||||
|
ap_regmatch_t pmatch[AP_MAX_REG_MATCH];
|
||||||
|
|
||||||
|
|
||||||
|
if(strcmp(var->name,"STREAM_OUTPUT_BODY") == 0 ) {
|
||||||
|
output_body = 1;
|
||||||
|
} else if(strcmp(var->name,"STREAM_INPUT_BODY") == 0 ) {
|
||||||
|
input_body = 1;
|
||||||
|
} else {
|
||||||
|
msr_log(msr,9,"Operator rsub only works with STREAM_* variables");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace = apr_pstrdup(rule->ruleset->mp, rule->sub_str);;
|
||||||
|
data = apr_pcalloc(msr->mp, var->value_len+(AP_MAX_REG_MATCH*strlen(replace))+1);
|
||||||
|
|
||||||
|
if(replace == NULL || data == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(data,var->value,var->value_len);
|
||||||
|
size += (AP_MAX_REG_MATCH*strlen(replace)+2);
|
||||||
|
|
||||||
|
if (ap_regexec(rule->sub_regex, data ,AP_MAX_REG_MATCH, pmatch, 0)) return 0;
|
||||||
|
|
||||||
|
for (offset = replace; *offset; offset++)
|
||||||
|
if (*offset == '\\' && *(offset + 1) > '0' && *(offset + 1) <= '9') {
|
||||||
|
so = pmatch [*(offset + 1) - 48].rm_so;
|
||||||
|
p_len = pmatch [*(offset + 1) - 48].rm_eo - so;
|
||||||
|
if (so < 0 || strlen (replace) + p_len - 1 > size) return 0;
|
||||||
|
memmove (offset + p_len, offset + 2, strlen (offset) - 1);
|
||||||
|
memmove (offset, data + so, p_len);
|
||||||
|
offset = offset + p_len - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub = pmatch [1].rm_so;
|
||||||
|
|
||||||
|
for (offset = data; !ap_regexec(rule->sub_regex, offset, 1, pmatch, 0); ) {
|
||||||
|
p_len = pmatch [0].rm_eo - pmatch [0].rm_so;
|
||||||
|
count++;
|
||||||
|
offset += pmatch [0].rm_so;
|
||||||
|
if (var->value_len - p_len + strlen(replace) + 1 > size) return 0;
|
||||||
|
memmove (offset + strlen (replace), offset + p_len, strlen (offset) - p_len + 1);
|
||||||
|
memmove (offset, replace, strlen (replace));
|
||||||
|
offset += strlen (replace);
|
||||||
|
if (sub >= 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size -= ((AP_MAX_REG_MATCH - count)*(strlen(replace)) + ((strlen(replace) - p_len)*(count+AP_MAX_REG_MATCH) - (AP_MAX_REG_MATCH+4)));
|
||||||
|
|
||||||
|
if(msr->stream_output_data != NULL && output_body == 1) {
|
||||||
|
msr->stream_output_data = (char *)realloc(msr->stream_output_data,size);
|
||||||
|
msr->stream_output_length = size;
|
||||||
|
if (msr->stream_output_data != NULL) {
|
||||||
|
memset(msr->stream_output_data,0,size);
|
||||||
|
memcpy(msr->stream_output_data,data,size);
|
||||||
|
msr->stream_output_data[msr->stream_output_length] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msr->stream_input_data != NULL && input_body == 1) {
|
||||||
|
msr->stream_input_data = (char *)realloc(msr->stream_input_data,size);
|
||||||
|
msr->stream_input_length = size;
|
||||||
|
if (msr->stream_input_data != NULL) {
|
||||||
|
memset(msr->stream_input_data,0,size);
|
||||||
|
memcpy(msr->stream_input_data,data,size);
|
||||||
|
msr->stream_input_data[msr->stream_input_length] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* rx */
|
/* rx */
|
||||||
|
|
||||||
static int msre_op_rx_param_init(msre_rule *rule, char **error_msg) {
|
static int msre_op_rx_param_init(msre_rule *rule, char **error_msg) {
|
||||||
@ -103,7 +260,12 @@ static int msre_op_rx_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, c
|
|||||||
char *my_error_msg = NULL;
|
char *my_error_msg = NULL;
|
||||||
int ovector[33];
|
int ovector[33];
|
||||||
int capture = 0;
|
int capture = 0;
|
||||||
|
int matched_bytes = 0;
|
||||||
|
int matched = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
char *qspos = NULL;
|
||||||
|
const char *parm = NULL;
|
||||||
|
msc_parm *mparm = NULL;
|
||||||
|
|
||||||
if (error_msg == NULL) return -1;
|
if (error_msg == NULL) return -1;
|
||||||
*error_msg = NULL;
|
*error_msg = NULL;
|
||||||
@ -127,6 +289,8 @@ static int msre_op_rx_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, c
|
|||||||
|
|
||||||
/* Are we supposed to capture subexpressions? */
|
/* Are we supposed to capture subexpressions? */
|
||||||
capture = apr_table_get(rule->actionset->actions, "capture") ? 1 : 0;
|
capture = apr_table_get(rule->actionset->actions, "capture") ? 1 : 0;
|
||||||
|
matched_bytes = apr_table_get(rule->actionset->actions, "sanitizeMatchedBytes") ? 1 : 0;
|
||||||
|
matched = apr_table_get(rule->actionset->actions, "sanitizeMatched") ? 1 : 0;
|
||||||
|
|
||||||
/* Show when the regex captures but "capture" is not set */
|
/* Show when the regex captures but "capture" is not set */
|
||||||
if (msr->txcfg->debuglog_level >= 6) {
|
if (msr->txcfg->debuglog_level >= 6) {
|
||||||
@ -192,16 +356,39 @@ static int msre_op_rx_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, c
|
|||||||
for(i = 0; i < rc; i++) {
|
for(i = 0; i < rc; i++) {
|
||||||
msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
|
msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
|
||||||
if (s == NULL) return -1;
|
if (s == NULL) return -1;
|
||||||
|
|
||||||
s->name = apr_psprintf(msr->mp, "%d", i);
|
s->name = apr_psprintf(msr->mp, "%d", i);
|
||||||
s->name_len = strlen(s->name);
|
s->name_len = strlen(s->name);
|
||||||
s->value = apr_pstrmemdup(msr->mp,
|
s->value = apr_pstrmemdup(msr->mp,
|
||||||
target + ovector[2 * i], ovector[2 * i + 1] - ovector[2 * i]);
|
target + ovector[2 * i], ovector[2 * i + 1] - ovector[2 * i]);
|
||||||
|
|
||||||
s->value_len = (ovector[2 * i + 1] - ovector[2 * i]);
|
s->value_len = (ovector[2 * i + 1] - ovector[2 * i]);
|
||||||
if ((s->name == NULL)||(s->value == NULL)) return -1;
|
if ((s->name == NULL)||(s->value == NULL)) return -1;
|
||||||
|
|
||||||
apr_table_addn(msr->tx_vars, s->name, (void *)s);
|
apr_table_addn(msr->tx_vars, s->name, (void *)s);
|
||||||
|
|
||||||
|
if(((matched == 1) || (matched_bytes == 1)) && (var != NULL) && (var->name != NULL)) {
|
||||||
|
qspos = apr_psprintf(msr->mp, "%s", var->name);
|
||||||
|
parm = strstr(qspos, ":");
|
||||||
|
if (parm != NULL) {
|
||||||
|
parm++;
|
||||||
|
mparm = apr_palloc(msr->mp, sizeof(msc_parm));
|
||||||
|
if (mparm == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mparm->value = apr_pstrmemdup(msr->mp,s->value,s->value_len);
|
||||||
|
mparm->pad_1 = rule->actionset->arg_min;
|
||||||
|
mparm->pad_2 = rule->actionset->arg_max;
|
||||||
|
apr_table_addn(msr->pattern_to_sanitize, parm, (void *)mparm);
|
||||||
|
} else {
|
||||||
|
mparm = apr_palloc(msr->mp, sizeof(msc_parm));
|
||||||
|
if (mparm == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mparm->value = apr_pstrmemdup(msr->mp,s->value,s->value_len);
|
||||||
|
apr_table_addn(msr->pattern_to_sanitize, qspos, (void *)mparm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (msr->txcfg->debuglog_level >= 9) {
|
if (msr->txcfg->debuglog_level >= 9) {
|
||||||
msr_log(msr, 9, "Added regex subexpression to TX.%d: %s", i,
|
msr_log(msr, 9, "Added regex subexpression to TX.%d: %s", i,
|
||||||
log_escape_nq_ex(msr->mp, s->value, s->value_len));
|
log_escape_nq_ex(msr->mp, s->value, s->value_len));
|
||||||
@ -2290,6 +2477,13 @@ void msre_engine_register_default_operators(msre_engine *engine) {
|
|||||||
msre_op_nomatch_execute
|
msre_op_nomatch_execute
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* rsub */
|
||||||
|
msre_engine_op_register(engine,
|
||||||
|
"rsub",
|
||||||
|
msre_op_rsub_param_init,
|
||||||
|
msre_op_rsub_execute
|
||||||
|
);
|
||||||
|
|
||||||
/* rx */
|
/* rx */
|
||||||
msre_engine_op_register(engine,
|
msre_engine_op_register(engine,
|
||||||
"rx",
|
"rx",
|
||||||
|
@ -2149,6 +2149,32 @@ static int var_path_info_generate(modsec_rec *msr, msre_var *var, msre_rule *rul
|
|||||||
return var_simple_generate(var, vartab, mptmp, value);
|
return var_simple_generate(var, vartab, mptmp, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* STREAM_OUTPUT_BODY */
|
||||||
|
|
||||||
|
static int var_stream_output_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||||
|
apr_table_t *vartab, apr_pool_t *mptmp)
|
||||||
|
{
|
||||||
|
if (msr->stream_output_data != NULL) {
|
||||||
|
return var_simple_generate_ex(var, vartab, mptmp,
|
||||||
|
msr->stream_output_data, msr->stream_output_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STREAM_INPUT_BODY */
|
||||||
|
|
||||||
|
static int var_stream_input_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||||
|
apr_table_t *vartab, apr_pool_t *mptmp)
|
||||||
|
{
|
||||||
|
if (msr->stream_input_data != NULL) {
|
||||||
|
return var_simple_generate_ex(var, vartab, mptmp,
|
||||||
|
msr->stream_input_data, msr->stream_input_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* RESPONSE_BODY */
|
/* RESPONSE_BODY */
|
||||||
|
|
||||||
static int var_response_body_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
static int var_response_body_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||||
@ -3012,6 +3038,29 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||||||
PHASE_REQUEST_HEADERS
|
PHASE_REQUEST_HEADERS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* STREAM_OUTPUT_BODY */
|
||||||
|
msre_engine_variable_register(engine,
|
||||||
|
"STREAM_OUTPUT_BODY",
|
||||||
|
VAR_SIMPLE,
|
||||||
|
0, 0,
|
||||||
|
NULL,
|
||||||
|
var_stream_output_generate,
|
||||||
|
VAR_CACHE,
|
||||||
|
PHASE_RESPONSE_BODY
|
||||||
|
);
|
||||||
|
|
||||||
|
/* STREAM_INPUT_BODY */
|
||||||
|
msre_engine_variable_register(engine,
|
||||||
|
"STREAM_INPUT_BODY",
|
||||||
|
VAR_SIMPLE,
|
||||||
|
0, 0,
|
||||||
|
NULL,
|
||||||
|
var_stream_input_generate,
|
||||||
|
VAR_CACHE,
|
||||||
|
PHASE_FIRST
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/* RESPONSE_BODY */
|
/* RESPONSE_BODY */
|
||||||
msre_engine_variable_register(engine,
|
msre_engine_variable_register(engine,
|
||||||
"RESPONSE_BODY",
|
"RESPONSE_BODY",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user