Streamline hardening helpers and expand coverage

This commit is contained in:
udo
2026-05-21 10:12:11 +00:00
parent 0d8b74930c
commit 41e9ca219f
14 changed files with 158 additions and 70 deletions
+35 -2
View File
@@ -14,6 +14,19 @@ def _direct_http_request(path, headers=None):
connection.close()
def _frontend_http_request(path, headers=None):
request_headers = {"Host": "uce.openfu.com"}
request_headers.update(headers or {})
connection = http.client.HTTPConnection("127.0.0.1", 80, timeout=5.0)
try:
connection.request("GET", path, headers=request_headers)
response = connection.getresponse()
body = response.read().decode("utf-8", errors="replace")
return response.status, response.getheaders(), body
finally:
connection.close()
def register(registry):
def direct_http_rejects_dotdot(context):
status, headers, body = _direct_http_request("/../site/demo/hello.uce")
@@ -32,13 +45,33 @@ def register(registry):
def response_headers_are_sanitized(context):
response = context.request("/tests/security_headers.uce")
if "X-UCE-Injected" in response.headers or "X-UCE-Redirect-Injected" in response.headers:
raise TestFailure("CRLF header injection produced an extra response header")
injected_headers = [
"X-UCE-Injected",
"X-UCE-Injected-Name",
"X-UCE-Cookie-Injected",
"X-UCE-Redirect-Injected",
"X-UCE-Status-Injected",
]
for header in injected_headers:
if header in response.headers:
raise TestFailure("CRLF header injection produced extra response header %s" % header)
location = response.headers.get("Location", "")
if "\r" in location or "\n" in location:
raise TestFailure("Location header contains raw CR/LF")
return "CRLF response header injection was sanitized"
def unknown_session_id_is_not_adopted(context):
attacker_id = "a" * 64
status, headers, body = _frontend_http_request("/tests/http.uce", headers={"Cookie": "uce-site-tests=" + attacker_id})
set_cookies = [value for name, value in headers if name.lower() == "set-cookie"]
session_cookies = [value for value in set_cookies if value.startswith("uce-site-tests=")]
if any(("uce-site-tests=" + attacker_id) in value for value in session_cookies):
raise TestFailure("session_start adopted caller supplied unknown session id")
if not session_cookies or not any("HttpOnly" in value and "SameSite=Lax" in value for value in session_cookies):
raise TestFailure("session_start did not issue a hardened replacement session cookie")
return "unknown caller-supplied session id was replaced"
registry.case("direct HTTP rejects dot-dot script traversal", direct_http_rejects_dotdot, tags=["security", "http", "internal"])
registry.case("direct HTTP ignores Script-Filename header", direct_http_ignores_script_filename_header, tags=["security", "http", "internal"])
registry.case("response headers sanitize CRLF", response_headers_are_sanitized, tags=["security", "http", "internal"])
registry.case("unknown session ids are not adopted", unknown_session_id_is_not_adopted, tags=["security", "http", "internal"])
+3 -1
View File
@@ -32,8 +32,10 @@ def register(registry):
for marker in ERROR_MARKERS:
if marker in body_lower:
raise Exception("response body contained error marker %r for %s" % (marker, page_path))
if '<div class="tests-summary">' in body_lower and ('>fail</span>' in body_lower or '>failed 0<' not in body_lower):
raise Exception("site suite reported failed cases for %s" % page_path)
return "HTTP 200 with suite page marker for %s" % page_path
return "HTTP 200 with suite page marker and no failed cases for %s" % page_path
return run