Initial release: offline NetScaler triage with Sigma rules and MIT license
This commit is contained in:
commit
711c42b270
52 files changed
+61222
No files matched your search
+190
@@ -0,0 +1,190 @@
|
||||
NETSCALER TRIAGE
|
||||
|
||||
Offline log triage for NetScaler ADC and Gateway.
|
||||
Give it a log folder or archive. It prepares the input, searches for suspicious
|
||||
patterns and public indicators, explains matching rules and decoded command text,
|
||||
finds update/version records, and links related events on the same appliance.
|
||||
Original files are not modified. Payloads are never executed or fetched.
|
||||
|
||||
INSTALL
|
||||
|
||||
Requires Python 3.14 or newer. From the unpacked source folder, on macOS/Linux:
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
Or on Windows PowerShell:
|
||||
py -m venv .venv
|
||||
.venv\Scripts\Activate.ps1
|
||||
|
||||
Then install the local project:
|
||||
python -m pip install .
|
||||
|
||||
A built wheel can instead be installed with python -m pip install PATH_TO_WHEEL.
|
||||
For a locked developer installation, use uv sync --locked with a suitable
|
||||
installed Python interpreter. The lockfile records exact dependency versions.
|
||||
Installation may need internet access; analysis itself runs offline.
|
||||
|
||||
START HERE
|
||||
|
||||
netscaler-triage logs.7z
|
||||
|
||||
Or use an unpacked folder:
|
||||
netscaler-triage ./logs
|
||||
|
||||
Or run inside the folder containing your logs:
|
||||
netscaler-triage
|
||||
|
||||
ZIP, TAR, TAR.GZ/TGZ, GZIP and 7z are detected automatically, including nested
|
||||
archives. Unsupported formats are reported. Several inputs can be combined:
|
||||
netscaler-triage ./appliance-a ./appliance-b another-export.zip
|
||||
|
||||
The result folder is created automatically and printed when the run finishes.
|
||||
--output PATH chooses a new result folder. Existing results are never overwritten.
|
||||
Appliance groups are inferred from folder structure; review the preparation
|
||||
manifest when a combined export has an unusual layout.
|
||||
|
||||
For an encrypted archive, request a hidden password prompt:
|
||||
netscaler-triage logs.7z --password
|
||||
|
||||
--password VALUE also works, but may expose the password in shell history or
|
||||
process listings. The same password is used for nested archives. 7z, ZipCrypto
|
||||
and AES-ZIP are supported. Passwords are not saved in results.
|
||||
|
||||
WHAT TO READ FIRST
|
||||
|
||||
summary.json tells you what was processed and whether anything was incomplete.
|
||||
findings.jsonl contains selected events, original source/line references, matching
|
||||
rule details, extracted indicators and safe decoding steps with explanations.
|
||||
Each line is a separate JSON object. Explanations describe what command text
|
||||
could do; they do not establish that it ran successfully.
|
||||
|
||||
IOCS.csv contains exact values for SIEM searches and a separate defanged display
|
||||
value. Observed values are candidates, not an automatic blocklist.
|
||||
updates.jsonl contains update/version evidence. An installer command is not by
|
||||
itself proof of a completed patch. correlations.jsonl contains temporal candidates
|
||||
between log files on the same appliance, not proof of causation.
|
||||
|
||||
Other outputs support verification:
|
||||
evidence.sqlite On-disk event index
|
||||
coverage.json Per-file coverage and read/matching errors
|
||||
input_manifest.json Original relative paths and SHA-256 checksums
|
||||
configuration.json Effective rules, references and time assumptions
|
||||
indicator_hits.csv Matches against configured reference indicators
|
||||
file_hash_hits.json Reference matches against original file SHA-256
|
||||
preparation_manifest.json Preparation actions, groups and exclusions
|
||||
inputs/ Prepared inputs when automatic preparation runs
|
||||
|
||||
URL/Base64 transformations retain the original value, transformation, parent
|
||||
step, decoded result or error, and checksum. Binary decoded content is displayed
|
||||
as hex and is not executed. Finding rule_details retain matching rule descriptions
|
||||
and source metadata; custom packs can provide their own explanations.
|
||||
|
||||
ADD YOUR OWN RULES OR IOCS
|
||||
|
||||
Bundled public references are loaded automatically. They are a dated, attributed
|
||||
collection, not a claim to cover every known attack. No private case addresses,
|
||||
appliance identities or environment-specific assumptions are included in defaults.
|
||||
References are not downloaded during a scan.
|
||||
|
||||
netscaler-triage ./logs --config examples/rules.yml
|
||||
netscaler-triage ./logs --ioc-file indicators.txt
|
||||
netscaler-triage ./logs --pattern "(?i)your_search_expression"
|
||||
|
||||
Repeat --config or --ioc-file to combine packs. An explicit --config directory
|
||||
loads supported packs recursively in sorted relative-path order; no private or
|
||||
customer directory is loaded unless you select it.
|
||||
|
||||
netscaler-triage ./logs --config ./my-rules
|
||||
Sigma YAML is the primary rule
|
||||
format, parsed with pySigma and evaluated locally with the supported subset in
|
||||
RULES.txt. Unsupported features are rejected explicitly. Defaults include 47
|
||||
Sigma rules and 246 deduplicated public reference indicators.
|
||||
THREAT_INTELLIGENCE.txt indexes all 52 sources, uses and limitations;
|
||||
config/threat_intel.json is the complete machine-readable inventory.
|
||||
|
||||
JSON, CSV and one reference per line in TXT remain supported. TXT infers clear
|
||||
IP addresses, SHA-256 hashes, HTTP(S) URLs and absolute Unix paths; other text
|
||||
stays literal. Explicit CSV/JSON types are unchanged. An exported IOCS.csv
|
||||
can be loaded again. Examples contain synthetic values, not real intelligence.
|
||||
Keep local case rules under private/, which is gitignored and excluded from
|
||||
release builds; load them explicitly with --config private/your_rules.yml.
|
||||
Private packs are never discovered or enabled automatically.
|
||||
Example files are included in the source release.
|
||||
Rule packs are data files. Python plugin code is not loaded from them.
|
||||
|
||||
TIME AND DEVICE IDENTITY
|
||||
|
||||
Explicit timestamps are retained. A missing year or timezone is not guessed.
|
||||
For known time settings and explicit appliance names on prepared folders:
|
||||
netscaler-triage scan --input ADC-A=./logs --year 2026 --timezone ADC-A=UTC
|
||||
|
||||
Use your actual device settings; UTC and the year above are examples only.
|
||||
Ambiguous daylight-saving times remain unresolved. Time assumptions and per-file
|
||||
year overrides can be supplied using --time-config; see examples/time.json.
|
||||
|
||||
LIMITS AND INCOMPLETE RESULTS
|
||||
|
||||
Exit 0 means the configured processing completed, not that the appliance is clean.
|
||||
Exit 2 means an error or incomplete processing; inspect summary.json.
|
||||
Invalid decoding candidates may be ordinary text, not malicious payloads.
|
||||
Unknown text formats remain searchable, even if no timestamp is parsed.
|
||||
Proprietary binary logs require an appropriate external decoder.
|
||||
|
||||
Unreadable files, damaged archives and regex timeouts are recorded while other
|
||||
valid inputs continue. Path traversal, unsafe links and exhausted archive quotas
|
||||
stop preparation. A controlled interruption preserves the processed database
|
||||
where possible. There is no automatic resume after interruption.
|
||||
|
||||
A single worker reads lines incrementally. SQLite stores events and large sorts
|
||||
on disk; small decoding caches are bounded. One CPU core can be busy. This is not
|
||||
a hard process-wide RAM or CPU quota: archive metadata, large rule lists and file
|
||||
inventories need additional memory. Allow disk space for preparation and results.
|
||||
|
||||
Defaults: 2 GiB preparation budget, 100,000 archive entries, nesting depth 3,
|
||||
1 MiB per line and 512 MiB expanded per log file. Limits never mean a silent
|
||||
successful scan. Advanced options can raise them for legitimate larger inputs.
|
||||
|
||||
HELP AND OPTIONAL COMMANDS
|
||||
|
||||
netscaler-triage --help
|
||||
netscaler-triage scan --help-all
|
||||
netscaler-triage extract logs.7z prepared
|
||||
netscaler-triage decode payload.txt
|
||||
netscaler-triage indicators text.txt
|
||||
netscaler-triage inventory ./logs
|
||||
|
||||
Short help shows common options. Advanced help includes resource limits, time
|
||||
assumptions and --no-default-patterns, which disables built-in rules and bundled
|
||||
public references; explicitly supplied packs still apply.
|
||||
|
||||
DEVELOPMENT AND RELEASE
|
||||
|
||||
uv run python -W error -m unittest discover -s tests
|
||||
uv run mypy
|
||||
uv run ruff check src tests typing_stubs
|
||||
uv run ruff format --check src tests typing_stubs
|
||||
uv build
|
||||
|
||||
Synthetic tests cover parsing, archive safety, decoding, matching, correlations
|
||||
and packaging hygiene. VALIDATION.txt records what was actually tested. Runtime
|
||||
environments and analysis outputs are not release files. Source distributions
|
||||
use an explicit allowlist to avoid bundling unrelated documents or case settings.
|
||||
|
||||
LICENSE
|
||||
|
||||
Project code is licensed under the MIT License; see LICENSE.txt.
|
||||
Third-party dependencies and referenced external materials retain their own
|
||||
licenses. The project does not relicense original external publications.
|
||||
|
||||
VALIDATE PACKS BEFORE A SCAN
|
||||
|
||||
netscaler-triage rules --config ./my-rules
|
||||
|
||||
This offline command loads and compiles the bundled defaults and selected packs,
|
||||
then prints the Sigma rule, regex rule and explicit active indicator counts. It
|
||||
does not prepare or scan logs, contact external services or create artifacts.
|
||||
Use --no-default-patterns to validate only the selected files; --json gives a
|
||||
machine-readable result. Invalid Sigma, unsupported rules and conflicting rule
|
||||
identifiers fail validation. Syntax validation does not prove detection quality.
|
||||
Directory discovery skips README.txt, LICENSE.txt and CHANGELOG.txt documents
|
||||
(case-insensitive); an explicitly named TXT file still loads as references using TXT type inference.
|
||||
Reference in new issue
Block a user