mirror of
https://github.com/usestrix/strix.git
synced 2026-10-07 02:58:26 +00:00
fix(proxy): recompute Content-Length when repeat_request replaces the body
build_raw_request only sets Content-Length when absent, so a repeat_request that replaces the body kept the original request's stale Content-Length and sent a wrong body length — truncating the modified/injected payload (which defeats parameter-tampering and injection replays). apply_modifications now drops a carried-over Content-Length (case-insensitively) on body replacement so it is recomputed, unless the caller explicitly set Content-Length in the same call. Adds tests.
This commit is contained in:
parent
777005a42b
commit
587dc8b275
2 changed files with 67 additions and 0 deletions
|
|
@ -261,6 +261,14 @@ def apply_modifications(
|
|||
headers.update(modifications["headers"])
|
||||
if "body" in modifications:
|
||||
body = modifications["body"]
|
||||
# Replacing the body invalidates any carried-over Content-Length.
|
||||
# Drop it (case-insensitively) so build_raw_request recomputes the
|
||||
# correct length for the new body — unless the caller deliberately
|
||||
# set Content-Length in this call's header modifications.
|
||||
explicit_cl = {k.title() for k in modifications.get("headers", {})}
|
||||
if "Content-Length" not in explicit_cl:
|
||||
for key in [k for k in headers if k.title() == "Content-Length"]:
|
||||
del headers[key]
|
||||
if "cookies" in modifications:
|
||||
cookies: dict[str, str] = {}
|
||||
if headers.get("Cookie"):
|
||||
|
|
|
|||
59
tests/test_proxy_caido_api.py
Normal file
59
tests/test_proxy_caido_api.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
"""Tests for raw-request building in the Caido proxy helper."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from strix.tools.proxy.caido_api import apply_modifications, build_raw_request
|
||||
|
||||
|
||||
def _content_length(raw: bytes) -> str | None:
|
||||
for line in raw.decode("utf-8").split("\r\n"):
|
||||
if line.lower().startswith("content-length:"):
|
||||
return line.split(":", 1)[1].strip()
|
||||
return None
|
||||
|
||||
|
||||
def test_body_replacement_recomputes_content_length() -> None:
|
||||
components = {
|
||||
"method": "POST",
|
||||
"headers": {"Host": "x.test", "Content-Length": "3"},
|
||||
"body": "old",
|
||||
}
|
||||
new_body = "this is the new and much longer body!"
|
||||
result = apply_modifications(components, {"body": new_body}, "http://x.test/submit")
|
||||
_conn, raw = build_raw_request(
|
||||
method=result["method"],
|
||||
url=result["url"],
|
||||
headers=result["headers"],
|
||||
body=result["body"],
|
||||
)
|
||||
assert _content_length(raw) == str(len(new_body.encode("utf-8")))
|
||||
|
||||
|
||||
def test_explicit_content_length_override_is_preserved() -> None:
|
||||
components = {
|
||||
"method": "POST",
|
||||
"headers": {"Host": "x.test", "Content-Length": "3"},
|
||||
"body": "old",
|
||||
}
|
||||
result = apply_modifications(
|
||||
components,
|
||||
{"body": "new body", "headers": {"Content-Length": "999"}},
|
||||
"http://x.test/",
|
||||
)
|
||||
_conn, raw = build_raw_request(
|
||||
method=result["method"],
|
||||
url=result["url"],
|
||||
headers=result["headers"],
|
||||
body=result["body"],
|
||||
)
|
||||
assert _content_length(raw) == "999"
|
||||
|
||||
|
||||
def test_no_body_modification_keeps_content_length() -> None:
|
||||
components = {
|
||||
"method": "POST",
|
||||
"headers": {"Host": "x.test", "Content-Length": "3"},
|
||||
"body": "old",
|
||||
}
|
||||
result = apply_modifications(components, {"headers": {"X-Test": "1"}}, "http://x.test/")
|
||||
assert result["headers"].get("Content-Length") == "3"
|
||||
Loading…
Add table
Reference in a new issue