SecRequestBodyAccess off skips the phase:2 rules
Describe the bug
If the SecRequestBodyAccess is off, then the engine skips all rules which has phase:2 action.
To Reproduce
Here you can find a regression test case.
In the debug log you can see this line:
[nnnnnn] [/?q=evil] [4] Request body processing is disabled
Expected behavior
As you can see, the request contains an XML payload (CT doesn't count...), and only one (relevant) rule with id:1. The rule has two variable: REQUEST_URI and REQUEST_BODY. First one available in phase 1, but the second one only in phase 2, so the rule set to phase 2. The request was constructed that both variable matches, but the test returns with 200.
The expected behavior is 403, because the config disables only the processing of request body, not the whole phase 2.
If you replace the phase:2 by phase:1 in rule 1, then the request will blocked as it expected.
Server (please complete the following information):
- ModSecurity version (and connector): libmodsecurity3.0.4, current master afefda
Additional context
There are two another issues related to this wrong behavior: #1940 - CRS issue - this helped me to describe this behavior #2273 - ModSecurity - SecRequestBodyAccess Off doesn't fully disable request body processing
I checked the source, and found a very strange solution to handle the SecRequestBodyAccess - looks like the appendBody() allocates a buffer even thought the variable set it to off. In addition, the chosen body processor also woke up, and the payload will parsed. Checking the body access is comes only at this point, that's why the #2273 exists. I assume that users disable the body access to save CPU/memory (as reporter also wrote there), but in this isn't fulfilled.
The another strange behavior is if the SecRequestBodyAccess is off, then whole phase 2 will ignored (in line 895-911), because the evaluation called later, in L938.
Note: I didn't checked, but I suppose the ctl:requestBodyAccess=off would give same result.
Sorry to say, but same behavior in case of SecResponseBodyAccess - if it's off, then whole phase:4 ignored.
Test case here. Problem is similar: the function returns by true if the body access is off, the evaluation won't called.
Hmm. I guess I can understand why it was coded that way (and some might even challenge whether it's a bug at all).
Given that phase:2 occurs at 'request body has been received', and one does not want to access the request body, it's not immediately obvious why one would write a rule to occur at phase:2. I.e. if your rule is checking request headers, why not make it a phase:1 rule? For example, this would seem to be the case with the cited rule 913100.
On the other hand, I can see at least some cases where this would be a problem -- particularly with generic rule sets.
For example, suppose a generic rule is intended to perform some detection against ARGS (both query args and post args), and so it is set up as a phase:2 rule. But a particular administrator is not interested in examining the request body and so sets SecResponseBodyAccess to off. In this case use of the rule will have been inadvertently turned off for query args as well.
You hit the nail on the head with your reasoning why most rules are written in phase 2. A quick peek at the Trustwave rule set tells me that it's over 99% of the rules. The ratio is better with CRS, but this is a serious problem and I hope you can fix this soon.
Thanks for quick response - I just followed the mod_security2 behavior.
While it works as I wrote that expected, I assume the v3 should follow that way - or make a separated documentation, how the new version works.
Anyway, using of phase action is just one thing - the another is the #2273: if the SecRequestBodyAccess is off, why does engine start to parse that?
if your rule is checking request headers, why not make it a phase:1 rule? Several reasons:
- with "configure --enable-request-early", phase 1 rules cannot be embedded in Location
- some header rules may depend on request body (for instance the body size)
- etc.
Not executing the rules seems to be a little too radical for my taste. On the other hand, I understand the value of not running it for performance reasons and other points cited below. Furthermore, it is easy to maintain the rules by having the execute-ever approach, given that it will allow cross-phases variables in a single Rule.
The cross-phase variables is controversial. Although it facilitates the development of the rules, oftentimes it leads to circumstances where:
- Too late to block: Blocking content from the request_headers during the request_body phase. Modern web servers deliver the headers to the end application before receiving the request body.
- Too late to take Action: Response headers are already delivered to the client, giving no chance to ModSecurity except to drop the request. Despite treating the request gracefully.
Those points aren't issues on Apache, at least last time I checked, but they are issues on Nginx. Owing to it treats the request on this streaming fashion.
The too late to block is the factor that drives me to think towards a situation that ModSecurity should be warning the user that the rule may not be doing what the user hopes for, at least, not in the time that he expects. Together with the effort to support intermediate phases, this could give us a good ground for new features.
Version 2 has some counterpoints on when to execute the phase:1 via the --enable-request-early but I don't think it is related to that particular discussion.
Another use case: when the variable is a collection name, eg. TX.
#
# -=[ Anomaly Mode: Overall Transaction Anomaly Score ]=-
#
SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \
"id:949110,\
phase:2,\
deny,\
t:none,\
msg:'Inbound Anomaly Score Exceeded (Total Score: %{TX.ANOMALY_SCORE})',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-generic',\
ver:'OWASP_CRS/3.3.0',\
severity:'CRITICAL',\
setvar:'tx.inbound_anomaly_score=%{tx.anomaly_score}'"
https://github.com/coreruleset/coreruleset/blob/af619744cbf25bca1d25c3bb27749951a4a4fb4f/rules/REQUEST-949-BLOCKING-EVALUATION.conf#L76-L91
I think this is justified, because the rule counts scores in the REQUEST phases, and it must to wait the end of these phases.
@zimmerle: I think there is nothing wrong with giving the user a way to skip phases completely. It just should not be implicit and undocumented. If the option exists, it should be via a dedicated directive. I also like the idea of ModSecurity warning about rules not doing what people expect. The traditional phase:1 rule with ARGS_POST is silently ignored and that is very taxing on newbies. Personally, I would not mind a 500 in such a situation as the rule is simply broken, but that's a question of taste.
What is not clear to me following your response: How do you intend to handle this? With SecRequestBodyAccess off skipping phase:2, ModSec3 is effectively disabling almost the entire SLR and CRS rule sets.
justified, because the rule counts scores in the REQUEST phases, and it must to wait the end of these phases.
The last rule in a phase does not necessarily be the first rule of the subsequent phase. It could be the last in the current phase.
I. SecRule "..." "phase:1,..."
II. SecRule "..." "phase:1,..."
III. SecRule "..." "phase:1,actionB..."
Order-wise this is equivalent -
I. SecRule "..." "phase:1,..."
II. SecRule "..." "phase:1,..."
III. SecRule "..." "phase:2,actionA..."
Notice that in the former you are taking an action when the headers may be already delivered to the end application. In other words: actionB happens a phase before actionA.
Some facts were somewhat related to that issue -
The recommended configuration file, with the description of why we think it is quintessential to have Request Body Inspection On:
https://github.com/SpiderLabs/ModSecurity/blob/afefda53c69bb17e2ec16d24dd6fbc2c8fd7d063/modsecurity.conf-recommended#L12-L16
One that may be writing the rules is reading the logs that state - https://github.com/SpiderLabs/ModSecurity/blob/afefda53c69bb17e2ec16d24dd6fbc2c8fd7d063/src/transaction.cc#L897
The commit which makes the behavior different from v2: 379f37009598b39cf46645b68486d7fb70bacdd7
The issue that propelled the change in question #1531
Reverting 379f37009598b39cf46645b68486d7fb70bacdd7 will make the behavior works is a similar fashion of v2. Not yet recommended.
As a long term plan, we aim to remove those configurations. We could leave for the engine to fill the variables based on the utilization. If not used, there will be automatically disabled.
I do not think you should remove configuration options. But that's for a long term discussion.
Near term: Will you revert 379f370 or how do you plan to fix this until the long term solution pans out?
Any news on this front or a plan to share?
Infos from CRS: We merged a PR (-> 1941) that shifts all the CRS rules that can run in phase:1 into phase:1. This allows ModSecurity v3 users to mitigate this security vulnerability by running the development version of CRS (v3.4/dev) and edit the rule 949110 to run in phase 1. We are now preparing a minor release (likely 3.3.1) that will allow blocking in phase 1 as a configuration option.
Nothing substantial to report yet. This matter is currently under active discussion.
Could we be part of the discussion, please? This issue affects our users, so we would like to chime in too. @zimmerle told us several times to report issues here on github so things could be discussed in public. If you discuss this behind closed doors now, this would be a contraction.
Update from the OWASP ModSecurity Core Rule Set project:
- We have shifted all rules that can run in phase 1 into phase 1 for the v3.4/dev branch
- We have introduced a new configuration option "Early Blocking" that allows you to block at the end of phase 1. See crs-setup.conf. (Again for the 3.4/dev branch)
https://github.com/coreruleset/coreruleset
With these two changes, we provide you with a workaround for this libModSecurity3 security issue that will let every attacker bypass your WAF when you have disabled request body access.
We plan to backport and release CRS 3.3.1 in the coming days. Please check https://coreruleset.org, the CRS mailinglist or back here for infos when this happened.
I have not heard any information about the Trustwave Spiderlabs ModSecurity rules (SLR). My estimation is that disabling request body access leads to a bypass of almost all the SLR rules. So a fix is due. In the meantime, try and enable request body access if you are affected from the vulnerability.
Sec[Request|Response]BodyAccess is no longer necessary. Back in the day, it was essential to save computational resources. With progress, ModSecurity managed to have the parser smart enough to figure with any variable that uses request|response body is in use; if so, turn on the processing automatically. :heart_eyes:
Considering how smart the parser is nowadays, it is natural to deprecate those outdated configuration flags. Moreover, mitigating the doubt on the semantic of the configuration. Namely: this issue, #1531, #1886, #2273, #2467, SpiderLabs/ModSecurity-nginx#124, 379f37009598b39cf46645b68486d7fb70bacdd7, #1643, 42a472adbda21e6ecc4711fd37d704cdb3d98fbb, SpiderLabs/ModSecurity-nginx#84, and SpiderLabs/ModSecurity-nginx#104.
One may argue in favor of having a configuration SecForce[Request|Response]BodyAccess Off. Particularly to address not-so-elegant rules that make unnecessary usage of variables that do not intend :upside_down_face:. Undoubtedly a fair point.
The phase will be processed as long as there is a rule to be addressed in that particular phase. Nonetheless, on the occasion of SecForce[Request|Response]BodyAccess development, we may want to raise this subject again.
The PoC with Sec[Request|Response]BodyAccess marked as deprecated is already implemented and under test here: ae128ad94d3e031178274f8262d3418f069e5370
As usual, this is open for appraisal. I will be delighted to discuss the technical matter.
Back in the day, it was essential to save computational resources.
Do you think this isn't necessary in these days? Or why do you classify this as an argument?
ModSecurity managed to have the parser smart enough to figure with any variable that uses request|response body is in use; if so, turn on the processing automatically.
The point is here the automatically. I'm not sure this is a good idea (I mean to deprive users of the right to decide).
Considering how smart the parser is nowadays, it is natural to deprecate those outdated configuration flags.
Sorry, I don't share your opinion. It definitely isn't natural for most users (just see the mentioned issues in initial comment). These "flags" (like Sec[Request|Response]BodyAccess) allows to users to make more flexible the engine. I mean if these "flags" will disappear, and a user wants to check the performance of the built WAF (eg. turn off the body inspect), the only chance is to turn off the affected rules (which are on phase:2/phase4) - or am I wrong?
The PoC with Sec[Request|Response]BodyAccess marked as deprecated is already implemented and under test here: ae128ad
Okay, I see you've committed the modifications which marked as deprecated. The other part of this idea (automatically processing based on the used variables) is already done? Or is there any plan?
Back in the day, it was essential to save computational resources.
Do you think this isn't necessary in these days? Or why do you classify this as an argument?
I am afraid I did not paraphrase this. Maybe, however, disable SecRequestBodyAccess is not essential to many users.
ModSecurity managed to have the parser smart enough to figure with any variable that uses request|response body is in use; if so, turn on the processing automatically.
The point is here the automatically. I'm not sure this is a good idea (I mean to deprive users of the right to decide).
Perhaps I did not make myself clear. I am saying that the engine will enable such configuration as long as the user demands it.
Looking at the illustration below, because the user has used REQUEST_BODY, the engine recognizes that he/she wants to examine the request body; therefore, the engine enables the body processing.
Before the purposed change
SecRequestBodyAccess On
SecRule REQUEST_BODY "^(([a-z])+.)+[A-Z]([a-z])+$" "pass,msg:'OWASP CRS'"
After
SecRule REQUEST_BODY ".* ...." "pass ..."
Considering how smart the parser is nowadays, it is natural to deprecate those outdated configuration flags.
Sorry, I don't share your opinion. It definitely isn't natural for most users (just see the mentioned issues in initial comment). These "flags" (like Sec[Request|Response]BodyAccess) allows to users to make more flexible the engine. I mean if these "flags" will disappear, and a user wants to check the performance of the built WAF (eg. turn off the body inspect), the only chance is to turn off the affected rules (which are on phase:2/phase4) - or am I wrong?
I am sorry to say, but you are not right. There are other manners for not proceed with the inspection of the request body, for instance:
Straight from the modsecurity.conf-recommended file - https://github.com/SpiderLabs/ModSecurity/blob/f18595f42830f2f0ac27362a8b31120e3dfb850c/modsecurity.conf-recommended#L32-L46
Regardless, considering a smoother alternative, we have already suggested the existence of SecForce[Request|Response]BodyAccess Off.
For clearness, you may want to expatiate why the enable/disable of the request body weighs a performance test. What is the subject of such a test, performance of what?
The PoC with Sec[Request|Response]BodyAccess marked as deprecated is already implemented and under test here: ae128ad
Okay, I see you've committed the modifications which marked as deprecated. The other part of this idea (automatically processing based on the used variables) is already done? Or is there any plan?
I am not sure what is your understanding by done; The PoC is implemented and published in the link I have shared. I am sure there is space for embellishment and improvements in the code.
Scrutiny is always welcomed.
Hello, @zimmerle I just want to check that I clearly understood how using of request body can be disabled after removing of Sec[Request/Responce]BodyAccess. Seems like there is a two way:
- Use SecForce[Request|Response]BodyAccess just like Sec[Request/Responce]BodyAccess was used before. But I need to be ready that this going to disable full phase 2, 4.
- Use construction with SecRequestBodyLimit and SecRequestBodyLimitAction like:
SecRequestBodyLimit 0
SecRequestBodyLimitAction ProcessPartial
Does this normal way to use it? As far as I understand this construction just disable processing of any rule that checks request body. But other rules on phase 2 going to be works fine?
My humble opinion, if you interested (from user point of view, as I hope). Sometimes I want to disable all rules that process request body, but without big changes of pre-installed rules.
ModSecurity managed to have the parser smart enough to figure with any variable that uses request|response body is in use; if so, turn on the processing automatically.
Looking at the illustration below, because the user has used REQUEST_BODY, the engine recognizes that he/she wants to examine the request body; therefore, the engine enables the body processing.
I think this a great. But seems like mostly can be used by ruleset developers, because they decide use REQUEST_BODY or not. This is good to have ways to disable request/response body processing in my little custom part of modsecurity configuration. A usual user can install ruleset and add this small configuration file nearby.
You already provided them early. So this part mostly about why this question is shown up.
Looking at the illustration below, because the user has used REQUEST_BODY, the engine recognizes that he/she wants to examine the request body; therefore, the engine enables the body processing. Before the purposed change ... After
I'm afraid we moved a little away from the original issue.
First, please help me to clarify your terminology. From your point of view, body processing == whole phase:2?
Then take a look to this rule:
SecRule REQUEST_URI|ARGS "\/assets\/file:\x2f\x2f" \
"id:248260,msg:'...',phase:2,deny
This is a non-commercial rule from Comodo, especially for ModSecurity-nginx combo. There are tons of like this, also like in other commercial and/or non-commercial rule sets (I mean: mixed variables from phase:1/2, and rule triggered in phase:2).
Based on your example below, the new workflow will realize that the rule contains the ARGS, which derives from the REQUEST BODY, so the engine will process that without SecRequestBodyAccess on settings. It's a good idea, agree that.
But what can a user does if he/she wants to disable the processing of request body? Important: disable the processing of request body, not the whole phase:2!
Why users want to disable the processing of req body? Please read the mentioned issues:
disable SecRequestBodyAccess is not essential to many users.
How do you know this? What about the users who wants to disable it?
Regardless, considering a smoother alternative, we have already suggested the existence of
SecForce[Request|Response]BodyAccess Off.
Yes, I saw this, but could you help me to clarify, what's the difference between the new and old "flags"?
Just one note - please take a look to this regression test:
No SecRequestBodyAccess directive regression test
As you can see, in the configuration section there isn't SecRequestBodyAccess - it's completely missing.
Now see the output (the expected result is 200, because the request body processing isn't enabled, and rule processed in phase:2).
[1609240212] [/] [9] Appending request body: 10 bytes. Limit set to: 0.000000
[1609240212] [/] [4] Starting phase REQUEST_BODY. (SecRules 2)
[1609240212] [/] [4] Adding request argument (POST): name "evil", value "evil
"
[1609240212] [/] [9] This phase consists of 1 rule(s).
[1609240212] [/] [4] (Rule: 1) Executing operator "Rx" with param "evil" against ARGS.
[1609240212] [/] [9] Target value: "evil\x0a" (Variable: ARGS:evil)
[1609240212] [/] [9] Matched vars updated.
[1609240212] [/] [4] Rule returned 1.
[1609240212] [/] [4] Running (disruptive) action: deny.
[1609240212] [/] [8] Running action deny
Hmmm... this definitely looks like if the SecRequestBodyAccess directive is missing, the engine interprets it as On.
(You can change the variable by REQUEST_BODY, or any relevant var...)
I've checked this behavior on my Nginx instance, with same result.
(Could you check and confirm that libmodsecurity3 has a default value with on for SecRequestBodyAccess directive?)
I don't know what's the expected behavior, the mod_security2 follows the opposite way: if the variable is not set explicit as On, then the body processing isn't enabled (also checked on a live instance).
But if this is the libmodsecurity3 expected behavior, then I don't see the point why you want to remove the directive in the next versions, and why do you wants to add a new one with same behavior.
@zimmerle I get the feeling the proposed change / solution for this regression is trying to do things in an intransparent way, kind of outsmarting the user. That usually leads to a disruption of existing use cases.
I prefer an engine to have an explicit way to configure it. Even more an engine that has ambiguous variables like ARGS that can be stuffed in phase 1 but also in phase 2.
Under the line I do not see much benefit in the proposed change, but new problems.
The directives SecRequestBodyAccess and SecResponseBodyAccess are useful the way they are. They are used in niche use cases obviously. But they also come in handy in more complex debugging situations. Removing them makes ModSecurity less useful. Replacing them with Force... options could be a workaround for problems that the proposed change introduces.
@SandakovMM
I just want to check that I clearly understood how using of request body can be disabled after removing of Sec[Request/Responce]BodyAccess. Seems like there is a two way:
- Use SecForce[Request|Response]BodyAccess just like Sec[Request/Responce]BodyAccess was used before. But I need to be ready that this going to disable full phase 2, 4.
- Use construction with SecRequestBodyLimit and SecRequestBodyLimitAction like:
SecRequestBodyLimit 0 SecRequestBodyLimitAction ProcessPartialDoes this normal way to use it? As far as I understand this construction just disable processing of any rule that checks request body. But other rules on phase 2 going to be works fine?
SecRequestBodyLimit allows ModSecurity to verify the request body size. If the size is above a threshold, SecRequestBodyLimitAction will be taken. I don't recommend SecRequestBodyLimit as a replacement for SecRequestBodyAccess.
The behavior of SecForce[Request|Response]BodyAccess is a discussion to be held be on the occasion of its development, as mentioned here: [1].
My humble opinion, if you interested (from user point of view, as I hope). Sometimes I want to disable all rules that process request body, but without big changes of pre-installed rules.
Your opinion really matters. I would like to understand why the proposed SecForce[Request|Response]BodyAccess does not address that behavior.
I think this a great. But seems like mostly can be used by ruleset developers, because they decide use REQUEST_BODY or not. This is good to have ways to disable request/response body processing in my little custom part of modsecurity configuration. A usual user can install ruleset and add this small configuration file nearby.
You already provided them early. So this part mostly about why this question is shown up.
REQUEST_BODY was a merely example of a variable that makes usage of the request body. Together with REQUEST_BODY, we have others variables that depends on the request body such as:
- ARGS
- ARGS_COMBINED_SIZE
- ARGS_NAMES
- ARGS_POST
- ARGS_POST_NAMES
- FILES
- FILES_COMBINED_SIZE
- FILES_NAMES
- FULL_REQUEST
- FULL_REQUEST_LENGTH
- FILES_SIZES
- FILES_TMPNAMES
- FILES_TMP_CONTENT
- INBOUND_DATA_ERROR
- MULTIPART_CRLF_LF_LINES
- MULTIPART_FILENAME
- MULTIPART_NAME
- MULTIPART_STRICT_ERROR
- MULTIPART_UNMATCHED_BOUNDARY
- REQBODY_ERROR
- REQBODY_ERROR_MSG
- REQBODY_PROCESSOR
- REQUEST_BODY_LENGTH
All those variable depends on the request body to have its value filled. If any of those variables are in use, then request body inspection comes naturally enabled. Otherwise, disable by SecForceRequestBodyAccess Off.
In practice, we are not removing functionality but adding the capability of not processing the request body if it is not in use by a rule; That wasn't possible before that proposal. That change is good for usability and performance.
@airween
Based on your example below, the new workflow will realize that the rule contains the
ARGS, which derives from the REQUEST BODY, so the engine will process that withoutSecRequestBodyAccess onsettings. It's a good idea, agree that.
In essence, this may be related to the use case of the user who loaded a set of rules and later decides to disable those rules due to having SecRequestBodyAccess to Off. I raise that use case scenario here: [1]. To address that niche use, I also have suggested the existence of SecForceRequestBodyAccess. Did you had considered using SecForceRequestBodyAccess in such a case?
Performance-wise I would recommend you have a separate file for the rules that depends on the request body; only load this file whenever you have the intention to use it, as oppose to load and disable.
Did you had considered using SecForceRequestBodyAccess in such a case?
Actually (as I wrote in my next comment, the SecRequestBodyAccess is default On, if there isn't present in config file) I don't see the difference between the suggested SecForceRequestBodyAccess and the current one.
@dune73
The directives
SecRequestBodyAccessandSecResponseBodyAccessare useful the way they are. They are used in niche use cases obviously. But they also come in handy in more complex debugging situations. Removing them makes ModSecurity less useful. Replacing them withForce...options could be a workaround for problems that the proposed change introduces.
I prefer to stick with the technical facts and concrete examples; this proposal suggests configuration labels/semantic a bit more consistent for the end-user. Let's exemplify using use case scenarios -
Before this proposal (The use case A)
Request Body Processed
SecRequestBodyAccess On
SecRule REQUEST_BODY ".*" "..."
Request Body Processed
SecRequestBodyAcess On
SecRule RESPONSE_HEADERS ".*" "..."
Request Body Processed (or not, up to the branch in question. see [3])
SecRule RESPONSE_HEADERS ".*" "..."
Request Body NOT Processed
SecRequestBodyAccess Off
SecRule REQUEST_BODY ".*" "..."
After this proposal (The use case B)
Request Body Processed
SecRule REQUEST_BODY ".*" "..."
Request Body NOT Processed
SecRule RESPONSE_HEADERS ".*" "..."
Request Body NOT Processed
SecForceRequestBodyAccess Off (or SecDisableRequestBody On)
SecRule REQUEST_BODY ".*" "..."
Perhaps the example would help to show the benefit clearly.
There were some concerns about possible limitations introduced by the deliberation of the use case B made at [2], specifically on explicit-ability, debugging limitations and possible new issues.
@dune73, Do you mind describing a bit why do you think those will be an issue? Even better if you could illustrate via examples.
Did you had considered using SecForceRequestBodyAccess in such a case?
Actually (as I wrote in my next comment, the SecRequestBodyAccess is default On, if there isn't present in config file) I don't see the difference between the suggested SecForceRequestBodyAccess and the current one.
I am afraid that this is not accurate. You may want to have a look at the illustration on [4], specifically on the Item 2 of the use case B.
I am afraid that this is not accurate.
First I just want to clear the SecRequestBodyAccess. The behavior of this variable is totally different than SecResponseBodyAccess.
Have you checked my regression test?
Can you confirm that if SecRequestBodyAccess isn't in the config, the engine assumes it's On?
Just to clarify only the last question ...
In the case where SecRequestBodyAccess has not been specified at all in the configuration files, (and ctl:requestBodyAccess has not been used):
In v2.9.3 this is the same as if one had specified 'SecRequestBodyAccess Off'.
In v3 this is the same as if one had specified 'SecRequestBodyAccess On'
In v3 this is the same as if one had specified 'SecRequestBodyAccess On'
That's what I wrote above.
And therefore IMHO there isn't any difference between the two scenarios (except the case with RESPONSE_HEADERS variable, which is clear).