
Exploit for CVE-2022-26134, an OGNL injection vulnerability in Atlassian Confluence Server and Data Center, enabling unauthenticated remote code execution.
Reproducible local analysis of request-URI evidence and mitigation records for the Atlassian Confluence OGNL injection vulnerability.
The repository preserves the original academic research artifact and adds Python tools for log analysis, case handling, and mitigation-evidence review. These workflows use local fixtures. They do not send exploit requests or scan hosts.
| Goal | Entry point |
|---|---|
| Read the original case study | Research overview |
| Read the technical paper | Original paper |
| View the presentation | Original slides |
| Run defensive tools | Detection and evidence guide |
| Review the request flow | Analysis notes |
Use Python 3.11 or newer. This quickstart needs only the standard library. Run from the repository root:
python -m detection.report_reader_cli \
CVE-2022-26134-OGNL-Injection/tests/fixtures/report-v1.golden.json
The report summarizes two parsed lines, one matched request, one emitted finding,
and candidate technique T1190. A matching URI is detection evidence, not proof
that an attacker executed code.
python -m detection.mitigation_evidence_cli tests/fixtures/mitigation-evidence-v1.json
The synthetic deployment returns review_required with urgent priority. One node
claims a fixed version; another records a temporary workaround. This deliberately
does not label the whole cluster fixed. Local file-set matches are also labeled
unverified because file presence cannot establish service restart or mitigation success.
Turn a local access-log fixture into a stored analyst case, rather than starting from a prebuilt report:
python -m detection.log_case_cli tests/fixtures/local-case-access.log --scope synthetic \
--created-at 2026-10-19T00:01:00Z --output /tmp/confluence-log-case.sqlite
python -m detection.case_store_verify_cli /tmp/confluence-log-case.sqlite
Use a fresh output path on POSIX. Expect two parsed requests, one matched request,
one emitted finding, and queue application-security. The stored case binds its
summary to the input SHA-256 and claimed scope, without copying raw request URIs or
the machine-local log path. Keep the original log separately and private. A
no_findings result creates no case or database and does not prove a deployment safe.
See the log-to-case limits.
Read the actual stored case back for analyst review, not just verification counts:
python -m detection.case_export_cli /tmp/confluence-log-case.sqlite \
--output /tmp/confluence-case-review.json
Expect report_type: case-document-export, verification.case_count: 1, and one
entry in cases containing the complete case document, its sequence, and payload
digest. Inspect its queue, review steps, and source summary before taking action.
Use a closed database with no pending WAL or journal writes and a fresh output path
on POSIX. The export contract
explains snapshot, privacy, and source-verification limits.
Reproduce that stored case from its retained source in a separate process:
python -m detection.log_case_verify /tmp/confluence-log-case.sqlite \
tests/fixtures/local-case-access.log --scope synthetic
Expect status: reproduced. This rechecks the database, original bytes, detection
summary, routing, and full case document. It is stronger than checking only the
stored payload hash, but does not authenticate the source or creation timestamp.
For the documented Apache combined-log subset, add --log-format combined to both
commands and use tests/fixtures/combined-access.log. It produces the same two-request,
one-finding review without requiring a lab-format rewrite. The default remains lab;
there is no format guessing. See the combined-log contract
for accepted fields and unsupported custom formats.
Try cluster-evidence authentication without preparing reports or key files:
python -m detection.cluster_demo
This builds two fabricated node reports in memory, aggregates them, and verifies a
manifest with an ephemeral random HMAC key. The summary shows review_required,
unchanged_manifest: verified, and rejected checks for a changed node, a different
deployment, and a stale observation. Freshness uses a fixed demonstration clock.
No key, MAC, host data, or file is emitted or retained. No Confluence host is contacted.
A verified manifest does not make the synthetic cluster mitigated or establish
that a source's claims are true.
To retain those synthetic reports for verification in another process, use
cluster_demo --output-dir NEW_DIRECTORY --key-file PRIVATE_EXTERNAL_KEY.
The detection guide includes
key preparation, verification commands, and the fixed-clock limitation. The key is
never copied into the evidence directory.
Run the full synthetic report-to-case path in one command:
python -m detection.demo
It reads the golden report, selects the application-security queue, builds a case,
stores it in temporary SQLite, retries the same insert, and verifies stored integrity.
The summary reports one stored case and status: verified; the retry creates no
duplicate row. Temporary files are removed after the run. This is local case-store
verification, not proof that a real incident or Confluence deployment is secure.
To retain reviewable evidence instead of deleting it, choose a new output directory:
python -m detection.demo --output-dir /tmp/confluence-synthetic-review
python -m detection.case_store_verify_cli /tmp/confluence-synthetic-review/cases.sqlite
python -m detection.bundle_verify /tmp/confluence-synthetic-review
The directory contains case.json, cases.sqlite, summary.json, and
checksums.json with SHA-256 hashes for the other three files. Existing paths are
never overwritten; the parent directory must already exist. The directory is private
on POSIX before copying begins. The checksums detect accidental
changes, not malicious replacement or signer identity. Keep retained data outside Git.
An interrupted copy can leave an incomplete directory; inspect it and choose a fresh
path before retrying. Only a successful exit confirms the complete bundle was copied.