Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb9fdc4f

Browse files
author
Felipe Zimmerle
committed
Adds support to suspicious and whitelist to Read and Write limits
The operators @ipMatch, @ipMatchF and @ipMatchFromFile wereadded to the functions: SecReadStateLimit and SecReadStateLimit,by using them it is possible to declare a suspicious list. Whena suspicious list is given, the {Read|Write}StateLimit will beapplied just to the IPs that belongs to that restricted list.Note that the negative of those operators (e.g. !@ipMatch) can beused to place a whitelist. The {Read|Write}StateLimitrestrictions will not be applied to those in the whitelist.This current version the Sec{Read|Write}StateLimit can be usedvarios times to add elements to both lists, however, thelast informed limit will be applied for the entire group. Thisfeature is experimental, and suggestions on how to improve itare very welcome. For further discussion use the issue:owasp-modsecurity#353.
1 parent8ff3de5 commitb9fdc4f

File tree

7 files changed

+518
-241
lines changed

7 files changed

+518
-241
lines changed

‎apache2/apache2_config.c‎

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,29 +1670,101 @@ static const char *cmd_rule_perf_time(cmd_parms *cmd, void *_dcfg,
16701670
returnNULL;
16711671
}
16721672

1673+
char*parser_conn_limits_operator(apr_pool_t*mp,constchar*p2,
1674+
TreeRoot**whitelist,msre_ipmatch**whitelist_param,
1675+
TreeRoot**suspicious_list,msre_ipmatch**suspicious_list_param,
1676+
constchar*filename)
1677+
{
1678+
intres=0;
1679+
char*config_orig_path;
1680+
char*param=strchr(p2,' ');
1681+
char*file=NULL;
1682+
char*error_msg=NULL;
1683+
param++;
1684+
1685+
config_orig_path=apr_pstrndup(mp,filename,
1686+
strlen(filename)-strlen(apr_filepath_name_get(filename)));
1687+
1688+
apr_filepath_merge(&file,config_orig_path,param,APR_FILEPATH_TRUENAME,
1689+
mp);
1690+
1691+
if ((strncasecmp(p2,"!@ipMatchFromFile",strlen("!@ipMatchFromFile"))==0)||
1692+
(strncasecmp(p2,"!@ipMatchF",strlen("!@ipMatchF"))==0)) {
1693+
1694+
res=ip_tree_from_file(whitelist,
1695+
file,mp,NULL);
1696+
}
1697+
elseif (strncasecmp(p2,"!@ipMatch",strlen("!@ipMatch"))==0) {
1698+
res=ip_list_from_param(mp,param,
1699+
whitelist_param,&error_msg);
1700+
}
1701+
elseif ((strncasecmp(p2,"@ipMatchFromFile",strlen("@ipMatchFromFile"))==0)||
1702+
(strncasecmp(p2,"@ipMatchF",strlen("@ipMatchF"))==0)) {
1703+
1704+
res=ip_tree_from_file(suspicious_list,
1705+
file,mp,NULL);
1706+
}
1707+
elseif (strncasecmp(p2,"@ipMatch",strlen("@ipMatch"))==0) {
1708+
res=ip_list_from_param(mp,param,
1709+
suspicious_list_param,&error_msg);
1710+
}
1711+
else {
1712+
returnapr_psprintf(mp,"ModSecurity: Invalid operator for " \
1713+
"SecReadStateLimit: %s, expected operators: @ipMatch, @ipMatchF " \
1714+
"or @ipMatchFromFile with or without !",p2);
1715+
}
1716+
1717+
if (res) {
1718+
char*error;
1719+
error=apr_psprintf(mp,"ModSecurity: failed to load IPs " \
1720+
"from: %s",param);
1721+
1722+
if (*error_msg) {
1723+
error=apr_psprintf(mp,"%s %s",error,error_msg);
1724+
}
1725+
1726+
returnerror;
1727+
}
1728+
1729+
returnNULL;
1730+
}
1731+
1732+
16731733
/**
16741734
* \brief Add SecReadStateLimit configuration option
16751735
*
16761736
* \param cmd Pointer to configuration data
16771737
* \param _dcfg Pointer to directory configuration
16781738
* \param p1 Pointer to configuration option
1739+
* \param p2 Pointer to configuration option
16791740
*
16801741
* \retval NULL On failure
16811742
* \retval apr_psprintf On Success
16821743
*/
16831744
staticconstchar*cmd_conn_read_state_limit(cmd_parms*cmd,void*_dcfg,
1684-
constchar*p1)
1745+
constchar*p1,constchar*p2)
16851746
{
16861747
directory_config*dcfg= (directory_config*)_dcfg;
16871748
longintlimit;
16881749

16891750
if (dcfg==NULL)returnNULL;
16901751

16911752
limit=strtol(p1,NULL,10);
1692-
if ((limit==LONG_MAX)||(limit==LONG_MIN)||(limit <=0)) {
1693-
returnapr_psprintf(cmd->pool,"ModSecurity: Invalid value for SecReadStateLimit: %s",p1);
1753+
if ((limit==LONG_MAX)|| (limit==LONG_MIN)|| (limit <=0)) {
1754+
returnapr_psprintf(cmd->pool,"ModSecurity: Invalid value for " \
1755+
"SecReadStateLimit: %s",p1);
16941756
}
16951757

1758+
if (p2!=NULL) {
1759+
char*param=parser_conn_limits_operator(cmd->pool,p2,
1760+
&conn_read_state_whitelist,&conn_read_state_whitelist_param,
1761+
&conn_read_state_suspicious_list,
1762+
&conn_read_state_suspicious_list_param,cmd->directive->filename);
1763+
1764+
if (param)
1765+
returnparam;
1766+
}
1767+
16961768
conn_read_state_limit=limit;
16971769

16981770
returnNULL;
@@ -1704,21 +1776,33 @@ static const char *cmd_conn_read_state_limit(cmd_parms *cmd, void *_dcfg,
17041776
* \param cmd Pointer to configuration data
17051777
* \param _dcfg Pointer to directory configuration
17061778
* \param p1 Pointer to configuration option
1779+
* \param p2 Pointer to configuration option
17071780
*
17081781
* \retval NULL On failure
17091782
* \retval apr_psprintf On Success
17101783
*/
17111784
staticconstchar*cmd_conn_write_state_limit(cmd_parms*cmd,void*_dcfg,
1712-
constchar*p1)
1785+
constchar*p1,constchar*p2)
17131786
{
17141787
directory_config*dcfg= (directory_config*)_dcfg;
17151788
longintlimit;
17161789

17171790
if (dcfg==NULL)returnNULL;
17181791

17191792
limit=strtol(p1,NULL,10);
1720-
if ((limit==LONG_MAX)||(limit==LONG_MIN)||(limit <=0)) {
1721-
returnapr_psprintf(cmd->pool,"ModSecurity: Invalid value for SecWriteStateLimit: %s",p1);
1793+
if ((limit==LONG_MAX)|| (limit==LONG_MIN)|| (limit <=0)) {
1794+
returnapr_psprintf(cmd->pool,"ModSecurity: Invalid value for " \
1795+
"SecWriteStateLimit: %s",p1);
1796+
}
1797+
1798+
if (p2!=NULL) {
1799+
char*param=parser_conn_limits_operator(cmd->pool,p2,
1800+
&conn_write_state_whitelist,&conn_write_state_whitelist_param,
1801+
&conn_write_state_suspicious_list,
1802+
&conn_write_state_suspicious_list_param,cmd->directive->filename);
1803+
1804+
if (param)
1805+
returnparam;
17221806
}
17231807

17241808
conn_write_state_limit=limit;
@@ -3192,15 +3276,15 @@ const command_rec module_directives[] = {
31923276
"Threshold to log slow rules in usecs."
31933277
),
31943278

3195-
AP_INIT_TAKE1 (
3279+
AP_INIT_TAKE12 (
31963280
"SecReadStateLimit",
31973281
cmd_conn_read_state_limit,
31983282
NULL,
31993283
CMD_SCOPE_ANY,
32003284
"maximum number of threads in READ_BUSY state per ip address"
32013285
),
32023286

3203-
AP_INIT_TAKE1 (
3287+
AP_INIT_TAKE12 (
32043288
"SecWriteStateLimit",
32053289
cmd_conn_write_state_limit,
32063290
NULL,

‎apache2/mod_security2.c‎

Lines changed: 95 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ unsigned long int DSOLOCAL msc_pcre_match_limit_recursion = 0;
6464
intDSOLOCALstatus_engine_state=STATUS_ENGINE_DISABLED;
6565

6666
unsigned longintDSOLOCALconn_read_state_limit=0;
67+
TreeRootDSOLOCAL*conn_read_state_whitelist=0;
68+
TreeRootDSOLOCAL*conn_read_state_suspicious_list=0;
69+
msre_ipmatchDSOLOCAL*conn_read_state_whitelist_param=0;
70+
msre_ipmatchDSOLOCAL*conn_read_state_suspicious_list_param=0;
71+
72+
TreeRootDSOLOCAL*conn_write_state_whitelist=0;
73+
TreeRootDSOLOCAL*conn_write_state_suspicious_list=0;
74+
msre_ipmatchDSOLOCAL*conn_write_state_whitelist_param=0;
75+
msre_ipmatchDSOLOCAL*conn_write_state_suspicious_list_param=0;
6776

6877
unsigned longintDSOLOCALconn_write_state_limit=0;
6978

@@ -1363,29 +1372,30 @@ static int hook_connection_early(conn_rec *conn)
13631372
{
13641373
sb_handle*sb=conn->sbh;
13651374
inti,j;
1366-
unsigned longintip_count=0,ip_count_w=0;
1375+
unsigned longintip_count_r=0,ip_count_w=0;
1376+
char*error_msg;
13671377
worker_score*ws_record=NULL;
13681378
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
13691379
ap_sb_handle_t*sbh=NULL;
1380+
char*client_ip=conn->client_ip;
1381+
#else
1382+
char*client_ip=conn->remote_ip;
13701383
#endif
13711384

1372-
if(sb!=NULL&& (conn_read_state_limit>0||conn_write_state_limit>0)) {
1385+
if(sb!=NULL&& (conn_read_state_limit>0||conn_write_state_limit>0)) {
13731386

13741387
ws_record=&ap_scoreboard_image->servers[sb->child_num][sb->thread_num];
1375-
if(ws_record==NULL)
1388+
if(ws_record==NULL)
13761389
returnDECLINED;
13771390

1378-
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
1379-
apr_cpystrn(ws_record->client,conn->client_ip,sizeof(ws_record->client));
1380-
#else
1381-
apr_cpystrn(ws_record->client,conn->remote_ip,sizeof(ws_record->client));
1382-
#endif
1391+
apr_cpystrn(ws_record->client,client_ip,sizeof(ws_record->client));
1392+
13831393
for (i=0;i<server_limit;++i) {
13841394
for (j=0;j<thread_limit;++j) {
13851395

13861396
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
13871397
sbh=conn->sbh;
1388-
if (sbh==NULL){
1398+
if (sbh==NULL) {
13891399
returnDECLINED;
13901400
}
13911401

@@ -1394,50 +1404,96 @@ static int hook_connection_early(conn_rec *conn)
13941404
ws_record=ap_get_scoreboard_worker(i,j);
13951405
#endif
13961406

1397-
if(ws_record==NULL)
1407+
if(ws_record==NULL)
13981408
returnDECLINED;
13991409

14001410
switch (ws_record->status) {
14011411
caseSERVER_BUSY_READ:
1402-
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
1403-
if (strcmp(conn->client_ip,ws_record->client)==0)
1404-
ip_count++;
1405-
#else
1406-
if (strcmp(conn->remote_ip,ws_record->client)==0)
1407-
ip_count++;
1408-
#endif
1412+
if (strcmp(client_ip,ws_record->client)==0)
1413+
ip_count_r++;
14091414
break;
1415+
14101416
caseSERVER_BUSY_WRITE:
1411-
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
1412-
if (strcmp(conn->client_ip,ws_record->client)==0)
1413-
ip_count_w++;
1414-
#else
1415-
if (strcmp(conn->remote_ip,ws_record->client)==0)
1417+
if (strcmp(client_ip,ws_record->client)==0)
14161418
ip_count_w++;
1417-
#endif
1419+
14181420
break;
14191421
default:
14201422
break;
14211423
}
14221424
}
14231425
}
14241426

1425-
if ((conn_read_state_limit>0)&& (ip_count>conn_read_state_limit)) {
1426-
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
1427-
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->client_ip);
1428-
#else
1429-
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);
1430-
#endif
1431-
returnOK;
1432-
}elseif ((conn_write_state_limit>0)&& (ip_count_w>conn_write_state_limit)) {
1433-
#ifAP_SERVER_MAJORVERSION_NUMBER>1&&AP_SERVER_MINORVERSION_NUMBER>2
1434-
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->client_ip);
1435-
#else
1436-
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);
1437-
#endif
1438-
returnOK;
1439-
}else {
1440-
returnDECLINED;
1427+
1428+
if (conn_read_state_limit>0&&ip_count_r>conn_read_state_limit)
1429+
{
1430+
if (conn_read_state_suspicious_list&&
1431+
(!((tree_contains_ip(conn->pool,
1432+
conn_read_state_suspicious_list,client_ip,NULL,&error_msg) <=0)||
1433+
(list_contains_ip(conn->pool,
1434+
conn_read_state_suspicious_list_param,client_ip,&error_msg) <=0))))
1435+
{
1436+
ap_log_error(APLOG_MARK,APLOG_WARNING,0,NULL,
1437+
"ModSecurity: Too many threads [%ld] of %ld allowed in " \
1438+
"READ state from %s - There is a suspission list but " \
1439+
"that IP is not part of it, access granted",ip_count_r,
1440+
conn_read_state_limit,client_ip);
1441+
}
1442+
1443+
elseif ((tree_contains_ip(conn->pool,
1444+
conn_read_state_whitelist,client_ip,NULL,&error_msg)>0)||
1445+
(list_contains_ip(conn->pool,
1446+
conn_read_state_whitelist_param,client_ip,&error_msg)>0))
1447+
{
1448+
ap_log_error(APLOG_MARK,APLOG_WARNING,0,NULL,
1449+
"ModSecurity: Too many threads [%ld] of %ld allowed in " \
1450+
"READ state from %s - Ip is on whitelist, access granted",
1451+
ip_count_r,conn_read_state_limit,client_ip);
1452+
}
1453+
else
1454+
{
1455+
ap_log_error(APLOG_MARK,APLOG_WARNING,0,NULL,
1456+
"ModSecurity: Access denied with code 400. Too many " \
1457+
"threads [%ld] of %ld allowed in READ state from %s - " \
1458+
"Possible DoS Consumption Attack [Rejected]",ip_count_r,
1459+
conn_read_state_limit,client_ip);
1460+
returnOK;
1461+
}
1462+
}
1463+
1464+
if (conn_write_state_limit>0&&ip_count_w>conn_write_state_limit)
1465+
{
1466+
if (conn_write_state_suspicious_list&&
1467+
(!((tree_contains_ip(conn->pool,
1468+
conn_write_state_suspicious_list,client_ip,NULL,&error_msg) <=0)||
1469+
(list_contains_ip(conn->pool,
1470+
conn_write_state_suspicious_list_param,client_ip,&error_msg) <=0))))
1471+
{
1472+
ap_log_error(APLOG_MARK,APLOG_WARNING,0,NULL,
1473+
"ModSecurity: Too many threads [%ld] of %ld allowed in " \
1474+
"WRITE state from %s - There is a suspission list but " \
1475+
"that IP is not part of it, access granted",ip_count_w,
1476+
conn_read_state_limit,client_ip);
1477+
}
1478+
elseif ((tree_contains_ip(conn->pool,
1479+
conn_write_state_whitelist,client_ip,NULL,&error_msg)>0)||
1480+
(list_contains_ip(conn->pool,
1481+
conn_write_state_whitelist_param,client_ip,&error_msg)>0))
1482+
{
1483+
ap_log_error(APLOG_MARK,APLOG_WARNING,0,NULL,
1484+
"ModSecurity: Too many threads [%ld] of %ld allowed in " \
1485+
"WRITE state from %s - Ip is on whitelist, access granted",
1486+
ip_count_w,conn_read_state_limit,client_ip);
1487+
}
1488+
else
1489+
{
1490+
ap_log_error(APLOG_MARK,APLOG_WARNING,0,NULL,
1491+
"ModSecurity: Access denied with code 400. Too many " \
1492+
"threads [%ld] of %ld allowed in WRITE state from %s - " \
1493+
"Possible DoS Consumption Attack [Rejected]",ip_count_w,
1494+
conn_write_state_limit,client_ip);
1495+
returnOK;
1496+
}
14411497
}
14421498
}
14431499

‎apache2/modsecurity.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct msc_parm msc_parm;
4040
#include"msc_util.h"
4141
#include"msc_json.h"
4242
#include"msc_xml.h"
43+
#include"msc_tree.h"
4344
#include"msc_geo.h"
4445
#include"msc_gsb.h"
4546
#include"msc_unicode.h"
@@ -145,8 +146,16 @@ extern DSOLOCAL unsigned long int msc_pcre_match_limit_recursion;
145146
externDSOLOCALintstatus_engine_state;
146147

147148
externDSOLOCAL unsigned longintconn_read_state_limit;
149+
externDSOLOCALTreeRoot*conn_read_state_whitelist;
150+
externDSOLOCALTreeRoot*conn_read_state_suspicious_list;
151+
externDSOLOCALmsre_ipmatch*conn_read_state_whitelist_param;
152+
externDSOLOCALmsre_ipmatch*conn_read_state_suspicious_list_param;
148153

149154
externDSOLOCAL unsigned longintconn_write_state_limit;
155+
externDSOLOCALTreeRoot*conn_write_state_whitelist;
156+
externDSOLOCALTreeRoot*conn_write_state_suspicious_list;
157+
externDSOLOCALmsre_ipmatch*conn_write_state_whitelist_param;
158+
externDSOLOCALmsre_ipmatch*conn_write_state_suspicious_list_param;
150159

151160
externDSOLOCAL unsigned longintunicode_codepage;
152161

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp