This commit is contained in:
ivanr 2007-12-17 11:22:47 +00:00
Родитель 9b0ce5ae67
Коммит b9a28882b2
7 изменённых файлов: 157 добавлений и 35 удалений

Просмотреть файл

@ -1,8 +1,14 @@
14 Dec 2007 - 2.5.0-rc1
17 Dec 2007 - 2.5.0-rc1
-----------------------
Changes since 2.5.0-dev2:
* Changed how allow works. Used on its own it now allows phases 1-4. Used
with parameter "phase" (e.g. SecAction allow:phase) it only affects
the current phase. Used with parameter "request" it allows phases
1-2.
* Fixed issue where only the first phase 5 rule would run when the
request was intercepted in an earlier phase.

Просмотреть файл

@ -595,7 +595,12 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, const char *
rule->actionset, 1);
/* Must NOT specify a disruptive action in logging phase. */
if ((rule->actionset != NULL) && (rule->actionset->phase == PHASE_LOGGING) && (rule->actionset->intercept_action != ACTION_ALLOW) && (rule->actionset->intercept_action != ACTION_NONE)) {
if ((rule->actionset != NULL)
&& (rule->actionset->phase == PHASE_LOGGING)
&& (rule->actionset->intercept_action != ACTION_ALLOW)
&& (rule->actionset->intercept_action != ACTION_ALLOW_REQUEST)
&& (rule->actionset->intercept_action != ACTION_NONE)
) {
return apr_psprintf(cmd->pool, "ModSecurity: Disruptive actions "
"cannot be specified in the logging phase.");
}

Просмотреть файл

@ -198,6 +198,21 @@ int perform_interception(modsec_rec *msr) {
status = DECLINED;
message = apr_psprintf(msr->mp, "Access allowed%s.", phase_text);
msr->was_intercepted = 0;
msr->allow_scope = ACTION_ALLOW;
break;
case ACTION_ALLOW_PHASE :
status = DECLINED;
message = apr_psprintf(msr->mp, "Access to phase allowed%s.", phase_text);
msr->was_intercepted = 0;
msr->allow_scope = ACTION_ALLOW_PHASE;
break;
case ACTION_ALLOW_REQUEST :
status = DECLINED;
message = apr_psprintf(msr->mp, "Access to request allowed%s.", phase_text);
msr->was_intercepted = 0;
msr->allow_scope = ACTION_ALLOW_REQUEST;
break;
default :

Просмотреть файл

@ -359,7 +359,12 @@ static apr_status_t modsecurity_process_phase_request_headers(modsec_rec *msr) {
*
*/
static apr_status_t modsecurity_process_phase_request_body(modsec_rec *msr) {
if ((msr->allow_scope == ACTION_ALLOW_REQUEST)||(msr->allow_scope == ACTION_ALLOW)) {
msr_log(msr, 4, "Skipping phase REQUEST_BODY (allow used).");
return 0;
} else {
msr_log(msr, 4, "Starting phase REQUEST_BODY.");
}
if (msr->txcfg->ruleset != NULL) {
return msre_ruleset_process_phase(msr->txcfg->ruleset, msr);
@ -372,7 +377,12 @@ static apr_status_t modsecurity_process_phase_request_body(modsec_rec *msr) {
*
*/
static apr_status_t modsecurity_process_phase_response_headers(modsec_rec *msr) {
if (msr->allow_scope == ACTION_ALLOW) {
msr_log(msr, 4, "Skipping phase RESPONSE_HEADERS (allow used).");
return 0;
} else {
msr_log(msr, 4, "Starting phase RESPONSE_HEADERS.");
}
if (msr->txcfg->ruleset != NULL) {
return msre_ruleset_process_phase(msr->txcfg->ruleset, msr);
@ -385,7 +395,12 @@ static apr_status_t modsecurity_process_phase_response_headers(modsec_rec *msr)
*
*/
static apr_status_t modsecurity_process_phase_response_body(modsec_rec *msr) {
if (msr->allow_scope == ACTION_ALLOW) {
msr_log(msr, 4, "Skipping phase RESPONSE_BODY (allow used).");
return 0;
} else {
msr_log(msr, 4, "Starting phase RESPONSE_BODY.");
}
if (msr->txcfg->ruleset != NULL) {
return msre_ruleset_process_phase(msr->txcfg->ruleset, msr);

Просмотреть файл

@ -172,6 +172,8 @@ extern DSOLOCAL const command_rec module_directives[];
#define ACTION_PROXY 3
#define ACTION_DROP 4
#define ACTION_ALLOW 5
#define ACTION_ALLOW_REQUEST 6
#define ACTION_ALLOW_PHASE 7
#define MODSEC_DISABLED 0
#define MODSEC_DETECTION_ONLY 1
@ -366,6 +368,14 @@ struct modsec_rec {
/* removed rules */
apr_array_header_t *removed_rules;
/* When "allow" is executed the variable below is
* updated to contain the scope of the allow action. Set
* at 0 by default, it will have ACTION_ALLOW if we are
* to allow phases 1-4 and ACTION_ALLOW_REQUEST if we
* are to allow phases 1-2 only.
*/
unsigned int allow_scope;
};
struct directory_config {

Просмотреть файл

@ -430,7 +430,8 @@ static char *msre_action_skipAfter_validate(msre_engine *engine, msre_action *ac
static apr_status_t msre_action_skipAfter_init(msre_engine *engine, msre_actionset *actionset,
msre_action *action)
{
// TODO: Need to keep track of skipAfter IDs so we can insert placeholders after we get to the real rule with that ID.
// TODO: Need to keep track of skipAfter IDs so we can insert placeholders after
// we get to the real rule with that ID.
actionset->skip_after = action->param;
return 1;
}
@ -441,9 +442,34 @@ static apr_status_t msre_action_allow_init(msre_engine *engine, msre_actionset *
msre_action *action)
{
actionset->intercept_action = ACTION_ALLOW;
if (action->param != NULL) {
if (strcasecmp(action->param, "phase") == 0) {
actionset->intercept_action = ACTION_ALLOW_PHASE;
} else
if (strcasecmp(action->param, "request") == 0) {
actionset->intercept_action = ACTION_ALLOW_REQUEST;
}
}
return 1;
}
static char *msre_action_allow_validate(msre_engine *engine, msre_action *action) {
if (action->param != NULL) {
if (strcasecmp(action->param, "phase") == 0) {
return NULL;
} else
if (strcasecmp(action->param, "request") == 0) {
return NULL;
} else {
return apr_psprintf("Invalid parameter for allow: %s", action->param);
}
}
return NULL;
}
/* phase */
static char *msre_action_phase_validate(msre_engine *engine, msre_action *action) {
@ -1699,10 +1725,10 @@ void msre_engine_register_default_actions(msre_engine *engine) {
msre_engine_action_register(engine,
"allow",
ACTION_DISRUPTIVE,
0, 0,
0, 1,
NO_PLUS_MINUS,
ACTION_CARDINALITY_ONE,
NULL,
msre_action_allow_validate,
msre_action_allow_init,
NULL
);

Просмотреть файл

@ -3,7 +3,7 @@
<title>ModSecurity Reference Manual</title>
<articleinfo>
<releaseinfo>Version 2.5.0-rc1/ (December 14, 2007)</releaseinfo>
<releaseinfo>Version 2.5.0-rc1/ (December 17, 2007)</releaseinfo>
<copyright>
<year>2004-2007</year>
@ -1963,28 +1963,26 @@ SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
<orderedlist continuation="restarts" inheritnum="ignore">
<listitem>
<para>Request headers</para>
<para>Request headers (REQUEST_HEADERS)</para>
</listitem>
<listitem>
<para>Request body</para>
<para>Request body (REQUEST_BODY)</para>
</listitem>
<listitem>
<para>Response headers</para>
<para>Response headers (RESPONSE_HEADERS)</para>
</listitem>
<listitem>
<para>Response body</para>
<para>Response body (RESPONSE_BODY)</para>
</listitem>
<listitem>
<para>Logging</para>
<para>Logging (LOGGING)</para>
</listitem>
</orderedlist>
<para><emphasis>ModSecurity Processing Phases Diagram</emphasis></para>
<para><emphasis> <emphasis>Below is a diagram of the standard Apache
Request Cycle. In the diagram, the 5 ModSecurity processing phases are
shown.</emphasis> </emphasis></para>
@ -1999,14 +1997,22 @@ SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
<programlisting format="linespecific">SecDefaultAction "log,pass,<emphasis>phase:2</emphasis>"
SecRule REQUEST_HEADERS:Host "!^$" "deny,<emphasis>phase:1</emphasis>"</programlisting>
<para><emphasis>Note on Rule and Phases</emphasis></para>
<note>
<para>Keep in mind that rules are executed according to phases, so even
if two rules are adjacent in a configuration file, but are set to
execute in different phases, they would not happen one after the other.
The order of rules in the configuration file is important only within
the rules of each phase. This is especially important when using the
<literal>skip</literal> and <literal>skipAfter</literal> actions.</para>
</note>
<para>Keep in mind that rules are executed according to phases, so even if
two rules are adjacent in a configuration file, but are set to execute in
different phases, they would not happen one after the other. The order of
rules in the configuration file is important only within the rules of each
phase. This is especially important when using the <literal>skip</literal>
and <literal>skipAfter</literal> actions.</para>
<note>
<para>The <literal>LOGGING</literal> phase is special. It is executed at
the end of each transaction no matter what happened in the previous
phases. This means it will be processed even if the request was
intercepted of the <literal>allow</literal> action was used to pass the
transaction through.</para>
</note>
<section>
<title>Phase Request Headers</title>
@ -2092,9 +2098,9 @@ SecRule REQUEST_HEADERS:Host "!^$" "deny,<emphasis>phase:1</emphasis>"</programl
This phase can be used to inspect the error messages logged by Apache.
You can not deny/block connections in this phase as it is too late. This
phase also allows for inspection of other response headers that weren't
available during phase:3 or phase:4. Note that you must be careful
not to inherit a disruptive action into a rule in this phase as this
is a configuration error in ModSecurity 2.5.0 and later versions.</para>
available during phase:3 or phase:4. Note that you must be careful not
to inherit a disruptive action into a rule in this phase as this is a
configuration error in ModSecurity 2.5.0 and later versions.</para>
</section>
</section>
@ -3552,8 +3558,8 @@ SecRule <emphasis>XML:/xq:employees/employee/name/text()</emphasis> Fred \
<section>
<title><literal>allow</literal></title>
<para><emphasis>Description:</emphasis> Stops processing on a successful
match and allows transaction to proceed.</para>
<para><emphasis>Description:</emphasis> Stops rule processing on a
successful match and allows the transaction to proceed.</para>
<para><emphasis>Action Group:</emphasis> Disruptive</para>
@ -3561,12 +3567,51 @@ SecRule <emphasis>XML:/xq:employees/employee/name/text()</emphasis> Fred \
<programlisting format="linespecific">SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,<emphasis>allow</emphasis></programlisting>
<para><emphasis>Note</emphasis></para>
<para>Prior to ModSecurity 2.5 the <literal>allow</literal> action would
only affect the current phase. An <literal>allow</literal> in phase 1
would skip processing the remaining rules in phase 1 but the rules from
phase 2 would execute. Starting with v2.5 <literal>allow</literal> was
enhanced to allow for fine-grained control of what is done. The
following rules now apply:</para>
<para>The allow action only applies to the current processing phase. If
your intent is to explicitly allow a request, then you should use the
"ctl" action to turn the ruleEngine off -<literal moreinfo="none">
ctl:ruleEngine=Off</literal>.</para>
<orderedlist>
<listitem>
<para>If used one its own, like in the example above,
<literal>allow</literal> will affect the entire transaction,
stopping processing of the current phase but also skipping over all
other phases apart from the logging phase. (The logging phase is
special; it is designed to always execute.)</para>
</listitem>
<listitem>
<para>If used with parameter "phase", <literal>allow</literal> will
cause the engine to stop processing the current phase. Other phases
will continue as normal.</para>
</listitem>
<listitem>
<para>If used with parameter "request", <literal>allow</literal>
will cause the engine to stop processing the current phase. The next
phase to be processed will be phase
<literal>RESPONSE_HEADERS</literal>.</para>
</listitem>
</orderedlist>
<para>Examples:</para>
<programlisting># Do not process request but process response.
SecAction phase:1,allow:request
# Do not process transaction (request and response).
SecAction phase:1,allow
</programlisting>
<para>If you want to allow a response through, put a rule in phase
<literal>RESPONSE_HEADERS</literal> and simply use
<literal>allow</literal> on its own:</para>
<programlisting># Allow response through.
SecAction phase:3,allow</programlisting>
</section>
<section>