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

Appearance settings

feat(921300): Query delimiter confusion#4571

Open
touchweb-vincent wants to merge 7 commits intocoreruleset:maincoreruleset/coreruleset:mainfrom
touchweb-vincent:patch-10touchweb-vincent/coreruleset:patch-10Copy head branch name to clipboard
Open

feat(921300): Query delimiter confusion#4571
touchweb-vincent wants to merge 7 commits intocoreruleset:maincoreruleset/coreruleset:mainfrom
touchweb-vincent:patch-10touchweb-vincent/coreruleset:patch-10Copy head branch name to clipboard

Conversation

@touchweb-vincent
Copy link
Copy Markdown
Contributor

@touchweb-vincent touchweb-vincent commented Mar 26, 2026

Proposed changes

This PR introduces a new detection rule targeting a parsing ambiguity where an ampersand (&) appears in the URI path before the beginning of a valid query string (?).

While this pattern is not compliant with standard URI syntax, it is observed in real-world deployments where backend rewrite rules (e.g. ?url=$1) may reinterpret path segments as query parameters. In such cases, characters like & embedded in the path can be promoted to query delimiters after rewriting.

More concretely, if an .htaccess or vhost contains the following rule:

^api(?:/(.*))?$ index.php?url=$1

Then, if the following request is sent:

GET /api/test&payload=my_payload

The WAF does not interpret payload as a parameter.

However, since the rewrite rule transforms the URI into:

GET /index.php?url=api/test&payload=my_payload

The backend application does receive the payload parameter with the value my_payload.

This also introduces additional side effects - including the neutralization of potential sanitiseMatched instructions, effectively exposing parameters that should be obfuscated in clear text within the frontend access logs.


This behavior creates a discrepancy between how the WAF (CRS) and the backend application interpret the request. Since CRS relies on normalized query parsing to populate ARGS collections, parameters injected via the path are not analyzed during rule evaluation. As a result, this can effectively neutralize detection logic relying on ARGS and enable parameter smuggling.

You will likely point out that most rules do not only analyze ARGS but also inspect REQUEST_URI, which mitigates the severity of this bypass; however, it still seems important to take this behavior into account.

The proposed rule detects any occurrence of & in the URI before a ?, which is a strong indicator of such ambiguity and a potential bypass vector.

This rule will inherently generate false positives, as the & character can be a perfectly legitimate character in filenames or path segments depending on the application context. For this reason, it has been placed at Paranoia Level 3 (PL3), although placement at PL4 could also be considered.

This addition strengthens CRS coverage against parser confusion and rewrite-assisted parameter smuggling techniques, which are currently not explicitly addressed.

What do you think ?

P.S. PrestaShop is very likely not the only application affected by this kind of behavior in .htaccess rewrite rules.

PR Checklist

  • I have read the CONTRIBUTING doc
  • I have added positive tests proving my fix/feature works as intended.
  • I have added negative tests that prove my fix/feature considers common cases that might end in false positives
  • In case you changed a regular expression, you are not adding a ReDOS for pcre. You can check this using regexploit
  • My test use the comment field to write the expected behavior
  • I have added documentation for the rule or change (when appropriate)

Further comments

For the reviewer

  • Positive and negative tests were added
  • Tests cover the intended fix/feature properly
  • No usage of dangerous constructs like ctl:requestBodyAccess=Off were used in the rule
  • In case a regular expression was changed, there is no ReDOS
  • Documentation is clear for the rule/change

@HackingRepo
Copy link
Copy Markdown
Contributor

but how, the example works? Give me an example how can be exploited @touchweb-vincent?

@HackingRepo
Copy link
Copy Markdown
Contributor

HackingRepo commented Mar 26, 2026

ah!!! yes, that is i already i want to report it /shop&id=1'+or+1=1+#, and not blocked some backends or apps treat & at the beeigneing as valid, in sandbox CRS and i ignore it because i do'nt known is valid or not but PrestaShop api treat as valid

@touchweb-vincent touchweb-vincent changed the title add(921300): Path delimiter confusion (PrestaShop API WAF Evasion) feat(921300): Path delimiter confusion (PrestaShop API WAF Evasion) Mar 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 26, 2026

📊 Quantitative test results for language: eng, year: 2023, size: 10K, paranoia level: 1:
🚀 Quantitative testing did not detect new false positives

@touchweb-vincent touchweb-vincent changed the title feat(921300): Path delimiter confusion (PrestaShop API WAF Evasion) feat(921300): Path delimiter confusion Mar 26, 2026
@fzipi fzipi added the ⚠️ do not merge Additional work or discussion is needed despite passing tests label Mar 26, 2026
@touchweb-vincent touchweb-vincent changed the title feat(921300): Path delimiter confusion feat(921300): Query delimiter confusion Mar 27, 2026
@fzipi fzipi removed the ⚠️ do not merge Additional work or discussion is needed despite passing tests label Mar 28, 2026
@fzipi
Copy link
Copy Markdown
Member

fzipi commented Apr 8, 2026

Problems

  1. Regex ^/[^\?]*?& — lazy quantifier (*?) not needed, and \? inside character class doesn't need escaping. Should be ^/[^?]*&

  2. Severity CRITICAL too high — you admit inherent FPs. PL3 + CRITICAL = big anomaly score for something that might be legit (/friend&family.png). Should be WARNING or at most ERROR

  3. Wrong score variable — uses tx.http_violation_score which is not standard CRS anomaly scoring. Should use only tx.inbound_anomaly_score_pl3 (which it does, but double-scoring with http_violation_score is wrong)

  4. Test 2 labeled "Known false positive" but expects rule to fire (expect_ids) — if it's a known FP, should be no_expect_ids to document the weakness, or removed

  5. capture action useless — no %{TX.0} used in logdata, and @rx match has no capture groups

  6. Missing negative tests — needs tests for normal URLs with ? query strings, URLs without & in path

  7. Missing .ra file — simple regex, but convention says create one

  8. Rule ID 921300 — needs verification that it's unused

Added a new test case for common call with parameters and updated description for an existing test case.
@touchweb-vincent
Copy link
Copy Markdown
Contributor Author

Hi @fzipi ,

Thanks a lot for your detailed feedback, much appreciated.

  1. The regex has been adjusted accordingly. That said, I do notice similar patterns using lazy quantifiers in native OWASP CRS rules. There might be a subtlety I’m missing despite years of usage. For example:
    https://github.com/coreruleset/coreruleset/blob/main/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf#L248

([^0-9A-Z_a-z]*?)

There are quite a few of these in the 941 ruleset, likely for good reasons. Any clarification on when/why lazy quantifiers are actually beneficial in these contexts would be very helpful for me.

  1. Regarding severity: I intentionally set it to CRITICAL because this rule targets an evasion technique that can completely bypass argument analysis. I don’t feel comfortable lowering the score.

That said, feel free to adjust it if needed, but it wouldn’t be my initiative.

  1. Concerning tx.http_violation_score: this variable is currently used across all rules in the 921 set. Should I understand that it needs to be removed consistently from the entire ruleset for coherence, if it is to be removed from this specific rule?

  2. About the “known false positive” test: if I switch it to no_expect_ids, the test will fail by design, since it is a known blocking behavior that requires manual handling by users willing to enable this rule.
    Do you still want me to mark it as no_expect_ids, even if it means the unit tests will fail?

  3. The capture action has been removed.

  4. A negative test has been added.

  5. I’m not entirely sure what is expected in the .ra file. Could you please provide the expected format or sequence?

  6. The rule ID is currently unused.

Thanks again for your help and guidance.

Vincent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.