test(redos): the lexicon-script-tag row denied the literal but not the bound
The unit fix alone ("<script>" -> "<script ") wasn't sufficient: at the
shared _REDOS_N=100_000, the now-fixed [^><] pattern's vulnerable
predecessor ([^>]) only measures ~1.2-1.4s, under the 2.0s assert -- so
the row passed under both the safe and the vulnerable form and proved
nothing. Gave this row its own N=200_000, where the unsafe form
measures ~3.7s (fails) and the shipped form ~0.8s (passes). Verified
both directions by temporarily reverting the lexicon pattern and
restoring it.
This commit is contained in:
parent
6bcb898632
commit
ee73062864
1 changed files with 13 additions and 9 deletions
|
|
@ -394,27 +394,31 @@ _REDOS_PAYLOADS = [
|
|||
("active-html-tag-attrs", scan_active_content, "<a"),
|
||||
# 0.6.0 put a value parser behind the URL-attribute presence test. Its one run
|
||||
# is the `\s*` in front of the required `=`, so the unit has to DENY the `=`:
|
||||
# a unit that supplies it matches immediately and never exercises the run. The
|
||||
# lexicon's `script-tag` row is the cautionary case — its `<script>` unit hands
|
||||
# the pattern the `>` it needs, so that row stayed green under a form measured
|
||||
# at ~84s on the input this gate accepts.
|
||||
# a unit that supplies it matches immediately and never exercises the run.
|
||||
("active-url-attr-value", scan_active_content, "<a href >"),
|
||||
# The lexicon is on the output path too, and it had the same defect in the
|
||||
# JSON pattern table -- found only because the composed-gate test below
|
||||
# stayed red after every scanner above was already linear. `<a:` drove the
|
||||
# six html-obfuscation `<[^>]+style...` patterns to 204s at 80_000 chars.
|
||||
("lexicon-html-obfuscation", scan_lexicon, "<a:"),
|
||||
("lexicon-script-tag", scan_lexicon, "<script>"),
|
||||
# A denying unit alone isn't enough here: at the shared _REDOS_N, the
|
||||
# now-fixed `[^>]` form measures ~1.2-1.4s -- under the 2.0s bound, so the
|
||||
# row would pass under the vulnerable form too and prove nothing. Measured
|
||||
# this row's own N: `[^>]` crosses the bound between 100k and 200k chars
|
||||
# (~3.7s at 200k) while the shipped `[^><]` form stays at ~0.8s. 200_000
|
||||
# is this row's own override, not the shared _REDOS_N.
|
||||
("lexicon-script-tag", scan_lexicon, "<script ", 200_000),
|
||||
("lexicon-iframe-src", scan_lexicon, "<iframe "),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"scanner,unit", [(s, u) for _, s, u in _REDOS_PAYLOADS],
|
||||
ids=[i for i, _, _ in _REDOS_PAYLOADS],
|
||||
"scanner,unit,n",
|
||||
[(row[1], row[2], row[3] if len(row) > 3 else _REDOS_N) for row in _REDOS_PAYLOADS],
|
||||
ids=[row[0] for row in _REDOS_PAYLOADS],
|
||||
)
|
||||
def test_crafted_redos_payload_stays_bounded(scanner, unit):
|
||||
payload = (unit * (_REDOS_N // len(unit) + 1))[:_REDOS_N]
|
||||
def test_crafted_redos_payload_stays_bounded(scanner, unit, n):
|
||||
payload = (unit * (n // len(unit) + 1))[:n]
|
||||
start = time.monotonic()
|
||||
scanner(payload)
|
||||
assert time.monotonic() - start < 2.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue