Scroll to top

Case Study: Slipping Past 159 WAF Rules With One XML Attribute

I’m Joe. This one is a research write-up rather than a client engagement: two bypasses I found in the OWASP Core Rule Set, reported to the maintainers and published as CVE-2026-62971 and CVE-2026-33691. Both are fixed. I am writing them up because the method that found them — asking what the engine never parses — transfers to any filtering technology you own, not just this one.

  1. A WAF Is a Filter, Not a Fence

    Almost every organisation I test runs a web application firewall, and almost every one of them describes it the same way: “we are covered.” A WAF inspects the parts of a request it knows how to parse and matches them against patterns. Everything it does not parse is, by definition, invisible to it. So the interesting question is never “which rules are enabled” — it is “which parts of my request does the engine never look at?” That question is what produced both of the CVEs in this write-up.

  2. The Blind Spot: XML Attribute Values

    The OWASP Core Rule Set is the most widely deployed rule set in the world; if you run ModSecurity, Coraza or a managed WAF, there is a good chance CRS is underneath it. When it processed XML bodies it inspected element text but not attribute values. So a payload placed in an attribute — a javascript: URI, for instance — went straight through while the identical payload in element text was blocked. The rules were working exactly as written; they were simply never shown the data.

  3. Measuring It Properly Before Reporting

    A bypass is a footnote until you can say how much it covers. I built a harness that fired the same payload set at both positions — element text and attribute value — across every paranoia level, then diffed which rules fired. The answer was roughly 159 rules across nine rule families, at every paranoia level, including the injection and cross-site scripting families people rely on most. That number is what turned the report from “an edge case” into CVE-2026-62971 with a 7.2 CVSS.

  4. The Second One Was a Single Space

    The same mindset produced a second finding in the file-upload rules. CRS blocks dangerous extensions by matching the end of a filename, but it was not normalising whitespace before that check. A filename written as “shell. php” — with a space between the dot and the extension — failed the pattern match and sailed through, while plenty of downstream stacks happily trim it back into an executable name. One character, filed as CVE-2026-33691, fixed in CRS 3.3.9 and 4.25.0.

  5. Fixing It Upstream Instead of Locally

    I could have written a custom rule for one client and moved on. Reporting it upstream to the CRS maintainers instead meant every deployment of the rule set got the fix, not just the organisation that hired me. The maintainers were fast and professional, the patches landed in tagged releases, and the advisories went out with clear affected-version ranges. That is what open-source security work should look like, and it is why I keep contributing findings back rather than hoarding them.

  6. What This Means for Your WAF

    Three practical takeaways. First, pin and track your rule-set version the way you track application dependencies — a WAF two years behind is running rules with known bypasses. Second, test the WAF the way an attacker would: same payload, many encodings and many positions, and record which ones actually fire. Third, never let the WAF be the only control. Both of these bypasses are harmless against an application that validates its own input; they are catastrophic against one that outsourced the job.

Cybersecurity case study

Comments (5)

  1. waf_admin_priya 2 days ago Reply
    We were four minor versions behind on CRS and had no process for updating it. This post started that conversation internally.
    1. joecybertech 2 days ago Reply
      That is the most common finding of all. Rule sets get installed once and then treated as infrastructure rather than as a dependency.
  2. pentester_alex 2 days ago Reply
    The "same payload, many positions" harness idea is underrated. Most people vary the encoding and forget the location entirely.
  3. devsecops_mika 2 days ago Reply
    Reporting upstream instead of writing a local rule deserves more credit than it gets. Thank you for doing it that way.
    1. crs_user_2019 2 days ago Reply
      Agreed. We got the fix for free because someone else did the work properly.

Leave a Comment

Please check your email
Please check your message
Thank you. Your message has been sent.
Error, email not sent