Added SecWriteStateLimit for slow post DoS

This commit is contained in:
brenosilva 2011-05-05 17:01:57 +00:00
parent c78903e988
commit 5eaa1a7345
3 changed files with 50 additions and 3 deletions

View File

@ -1440,6 +1440,34 @@ static const char *cmd_conn_read_state_limit(cmd_parms *cmd, void *_dcfg,
return NULL;
}
/*
* \brief Add SecWriteStateLimit 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_write_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 SecWriteStateLimit: %s", p1);
}
conn_write_state_limit = limit;
return NULL;
}
static const char *cmd_request_body_inmemory_limit(cmd_parms *cmd, void *_dcfg,
const char *p1)
@ -2347,6 +2375,14 @@ const command_rec module_directives[] = {
"maximum number of threads in READ_BUSY state per ip address"
),
AP_INIT_TAKE1 (
"SecWriteStateLimit",
cmd_conn_write_state_limit,
NULL,
CMD_SCOPE_ANY,
"maximum number of threads in WRITE_BUSY state per ip address"
),
AP_INIT_TAKE1 (
"SecRequestBodyInMemoryLimit",
cmd_request_body_inmemory_limit,

View File

@ -57,6 +57,8 @@ unsigned long int DSOLOCAL msc_pcre_match_limit_recursion = 0;
unsigned long int DSOLOCAL conn_read_state_limit = 0;
unsigned long int DSOLOCAL conn_write_state_limit = 0;
static int server_limit, thread_limit;
typedef struct {
@ -1200,13 +1202,13 @@ static int hook_connection_early(conn_rec *conn)
{
sb_handle *sb = conn->sbh;
int i, j;
unsigned long int ip_count = 0;
unsigned long int ip_count = 0, ip_count_w = 0;
worker_score *ws_record = NULL;
#if APR_MAJOR_VERSION > 1
ap_sb_handle_t *sbh = NULL;
#endif
if(sb != NULL && conn_read_state_limit > 0) {
if(sb != NULL && (conn_read_state_limit > 0 || conn_write_state_limit > 0)) {
ws_record = &ap_scoreboard_image->servers[sb->child_num][sb->thread_num];
if(ws_record == NULL)
@ -1235,15 +1237,22 @@ static int hook_connection_early(conn_rec *conn)
if (strcmp(conn->remote_ip, ws_record->client) == 0)
ip_count++;
break;
case SERVER_BUSY_WRITE:
if (strcmp(conn->remote_ip, ws_record->client) == 0)
ip_count_w++;
break;
default:
break;
}
}
}
if (ip_count > conn_read_state_limit) {
if ((conn_read_state_limit > 0) && (ip_count > conn_read_state_limit)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, "ModSecurity: Access denied with code 400. Too many threads [%ld] of %ld allowed in READ state from %s - Possible DoS Consumption Attack [Rejected]", ip_count,conn_read_state_limit,conn->remote_ip);
return OK;
} else if ((conn_write_state_limit > 0) && (ip_count_w > conn_write_state_limit)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, "ModSecurity: Access denied with code 400. Too many threads [%ld] of %ld allowed in WRITE state from %s - Possible DoS Consumption Attack [Rejected]", ip_count_w,conn_write_state_limit,conn->remote_ip);
return OK;
} else {
return DECLINED;
}

View File

@ -134,6 +134,8 @@ extern DSOLOCAL unsigned long int msc_pcre_match_limit_recursion;
extern DSOLOCAL unsigned long int conn_read_state_limit;
extern DSOLOCAL unsigned long int conn_write_state_limit;
#define RESBODY_STATUS_NOT_READ 0 /* we were not configured to read the body */
#define RESBODY_STATUS_ERROR 1 /* error occured while we were reading the body */
#define RESBODY_STATUS_PARTIAL 2 /* partial body content available in the brigade */