Files
NetScaler_forensik/tests/test_review.py
T

86 lines
3.2 KiB
Python
Raw Normal View History

"""Regression checks for independent review findings; synthetic evidence only."""
import base64
import csv
import tempfile
import unittest
from pathlib import Path
from netscaler_triage.engine import scan
from netscaler_triage.matching import Matcher
class ReviewTests(unittest.TestCase):
def test_ipv4_with_port_and_embedded_address_boundary(self) -> None:
matcher = Matcher(
[{"indicators": [{"type": "ipv4", "value": "192.0.2.1"}]}],
defaults=False,
)
self.assertTrue(matcher.search("http://192.0.2.1:443/a")[1])
self.assertFalse(matcher.search("192.0.2.10:443")[1])
self.assertFalse(matcher.search("1192.0.2.1")[1])
def test_base64_query_without_percent_encoding(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary).resolve()
source = root / "logs"
source.mkdir()
(source / "access.log").write_text(
"192.0.2.1 - - [01/Oct/2026:12:00:00 +0000] "
'"GET /test?x=aWQ= HTTP/1.1" 403 0 "-" "ordinary"\n',
encoding="utf-8",
)
result = scan(
[("appliance", source)],
root / "out",
[{"patterns": [{"id": "decoded_id", "pattern": "^id$"}]}],
defaults=False,
)
self.assertEqual(result["counts"].get("findings", 0), 1)
def test_authorized_status_survives_ioc_export(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary).resolve()
source = root / "logs"
source.mkdir()
(source / "access.log").write_text(
"192.0.2.1 - - [01/Oct/2026:12:00:00 +0000] "
'"GET /test HTTP/1.1" 403 0 "-" "ordinary"\n',
encoding="utf-8",
)
scan(
[("appliance", source)],
root / "out",
[
{
"indicators": [
{"type": "ipv4", "value": "192.0.2.1", "status": "authorized_test"}
]
}
],
defaults=False,
)
with (root / "out/IOCS.csv").open(encoding="utf-8", newline="") as handle:
rows = list(csv.DictReader(handle))
match = next(row for row in rows if row["value"] == "192.0.2.1")
self.assertIn("authorized_test", match["status"])
def test_incomplete_decoding_marks_partial_analysis(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary).resolve()
source = root / "logs"
source.mkdir()
payload = "x:" + base64.b64encode(b"hostname " * 50).decode() + "%20"
(source / "payload.log").write_text(payload + "\n", encoding="utf-8")
result = scan(
[("appliance", source)],
root / "out",
[{"patterns": [{"id": "candidate", "pattern": "^x:"}]}],
defaults=False,
max_line_bytes=1024,
)
self.assertEqual(result["status"], "partial")
if __name__ == "__main__":
unittest.main()