Skip to content

OpenGraph Attack Path Analysis

WebbinRoot edited this page Nov 13, 2026 · 1 revision

OpenGraph - Attack-Path Analysis (Text-Based)

Table of Contents

If you are new to OCI, complete Getting Started before using this page.

Overview

process_og_attack_paths is a Process module that finds privilege-escalation paths directly from the exported OpenGraph JSON — no BloodHound required. It reads the oracle_cloud_hound.json produced by process_oracle_cloud_hound_data and walks the graph from every principal (user, group, dynamic group, instance, service) to every privilege-escalation destination, printing the shortest (or every) path as readable text.

It is the OCI analog of PMapper-style text pathfinding for AWS: load the graph, ask "who can reach manage all-resources / create a policy / mint a resource-principal token?", and get an answer in the terminal.

When To Use This Instead of BloodHound

  • Large tenancies. Graphs with tens of thousands of nodes/edges can be slow or unwieldy in the BloodHound UI. The text finder handles them in-process.
  • No BloodHound available. CI, a jump box, an air-gapped review — anywhere you only have the JSON and a terminal.
  • Scripting / triage. --json emits machine-readable paths you can diff, grep, or feed into a report.
  • Quick "who can own the tenancy?" answers without standing up a graph database.

BloodHound is still the better tool for interactive exploration and custom Cypher — this complements it, it does not replace it. See Common Use Cases for the BloodHound import path.

Prerequisites

Generate the graph first (see Common Use Cases):

modules run process_oracle_cloud_hound_data

That writes oracle_cloud_hound.json (or, for very large graphs, a directory of split-JSON parts) under the workspace export tree. The attack-path module reads either a single file or a split-parts directory via --graph-json.

Quick Start

# Default: one shortest path per reachable principal to any priv-esc destination
modules run process_og_attack_paths --graph-json /path/to/oracle_cloud_hound.json

# Only paths that reach an OCI_MANAGE destination
modules run process_og_attack_paths --graph-json /path/to/oracle_cloud_hound.json --to-manage

# Paths to every node of a kind
modules run process_og_attack_paths --graph-json /path/to/oracle_cloud_hound.json --to-kind OCIDynamicGroup

# Summary counts only, no per-path detail
modules run process_og_attack_paths --graph-json /path/to/oracle_cloud_hound.json --summary

--graph-json accepts a single JSON file or a directory containing the split-JSON parts emitted for very large graphs.

Search Modes

Mode Flag Behavior
Shortest (default) (none) One shortest path per reachable principal (BFS). Fast; best for "can X reach Y at all?".
All paths --all-paths Enumerate every simple path up to --max-paths (best-first). Thorough; shows alternative routes. Bounded by --max-expansions.

Target Selection

By default the module targets all privilege-escalation destinations (--to-priv). Narrow it with:

Flag Targets
--to-priv All priv-esc edge destinations (the default).
--to-manage All OCI_MANAGE destinations only.
--to-iam IAM-control destinations (create/update policy or group, add-self-to-group, create user).
--to-rpst RPST resource-creation destinations (create a workload → mint its resource-principal token).
--to-kind KIND Every node of this kind (e.g. OCIGroup, OCIDynamicGroup). Repeatable.
--to-node NODE_ID An exact node id. Repeatable.
--to-any Every capability-edge destination (very broad).
--list-targets List the nodes matched by the current selector, then exit (dry run).

What Counts as a Privilege-Escalation Edge

--to-priv (the default) is the union of four edge-kind families:

  • Manage: OCI_MANAGE (broad manage on critical resources).
  • IAM control: OCI_CAN_CREATE_POLICY, OCI_CREATE_POLICY, OCI_UPDATE_POLICY, OCI_UPDATE_GROUP, OCI_GROUP_UPDATE, OCI_INTERNAL_USER_UPDATE, OCI_INTERNAL_GROUP_UPDATE, OCI_ADD_SELF_TO_GROUP, OCI_POLICY_CAN_GRANT_ALL_RESOURCES, OCI_UPDATED_ACCESS_TO_ALL_RESOURCES, IDD_CREATE_USER.
  • RPST creation (create a workload that runs as a resource principal): OCI_CREATE_INSTANCE, OCI_CREATE_FN_FUNCTION, OCI_CREATE_CONTAINER_INSTANCE, OCI_CREATE_OKE_CLUSTER, OCI_CREATE_DS_NOTEBOOK_SESSION, OCI_CREATE_DS_MODEL_DEPLOYMENT, OCI_CREATE_GENAI_AGENT, and ~15 more OCI_CREATE_* service edges.
  • Execution on existing resources: OCI_RUN_COMMAND, OCI_CREATE_INSTANCE_AGENT_COMMAND, OCI_READ_RUN_INPUT, OCI_READ_RUN_OUTPUT.

For the abuse/defense context behind each edge, see OpenGraph - Default Priv Escalation Mode.

Source Filtering

Flag Effect
--from SUBSTR Only start paths at principals whose id/name contains SUBSTR. Repeatable.
--exclude-service-agents Drop OCI service-agent principals as path sources.
--no-direct Hide trivial paths where the principal already holds the target edge directly.
--exclude-node SUBSTR Drop any path that passes through a node matching SUBSTR. Repeatable.

Search Tuning

Flag Default Effect
--max-depth N 10 (shortest) / 7 (all-paths) Maximum path length in hops.
--max-paths N 500 Max paths returned in --all-paths mode.
--max-expansions N 400,000 Search budget (heap pops) in --all-paths mode.
--include-containment off Also follow scope/containment edges (OCI_SCOPE_MEMBER_OF, FAMILY_INCLUDES, …).
--exclude-conditional off Skip edges that require conditions to be satisfied.

Output Formats

Flag Output
(default) Human-readable report: each path rendered as principal --[verb on resource in scope]--> resource, with policy intermediaries collapsed.
--expanded Show every raw node/edge (do not collapse OCIPolicyStatement nodes).
--summary Only the summary table (counts), no individual paths.
--json Machine-readable JSON to stdout.
--output FILE Write the report to FILE instead of stdout.
--stats Print an edge-kind histogram for the graph, then exit.
-v / --debug Verbose diagnostics.

Full Flag Reference

--graph-json PATH          Path to oracle_cloud_hound.json or a split-JSON directory (required)

Target selection (default: all priv-esc destinations)
  --to-priv                All privilege-escalation edge destinations (default)
  --to-manage              All OCI_MANAGE destinations
  --to-iam                 All IAM-control destinations
  --to-rpst                All RPST resource-creation destinations
  --to-kind KIND           All nodes of this kind (repeatable)
  --to-node NODE_ID        Exact node id (repeatable)
  --to-any                 Every capability-edge destination (very broad)
  --list-targets           List matched target nodes, then exit

Search options
  --from SUBSTR            Only start at principals matching SUBSTR (repeatable)
  --all-paths              Enumerate all simple paths (not just shortest per principal)
  --max-depth N           Max path length in hops (default 10 shortest / 7 all-paths)
  --max-paths N           Max paths in --all-paths mode (default 500)
  --max-expansions N      Search budget for --all-paths (default 400,000)
  --include-containment   Follow scope/containment edges
  --exclude-conditional   Skip condition-gated edges
  --exclude-service-agents Exclude OCI service-agent principals as sources
  --no-direct             Exclude trivial direct-edge paths
  --exclude-node SUBSTR   Exclude paths through matching nodes (repeatable)

Output
  --expanded              Show raw nodes/edges (no policy-node collapsing)
  --summary               Summary counts only
  --json                  Machine-readable JSON
  --output FILE           Write report to FILE
  --stats                 Edge-kind histogram, then exit
  -v, --debug             Verbose

Example Output

Paths are collapsed so policy-statement intermediaries read as a single verb hop (--expanded shows the raw nodes). Identifiers below are placeholders.

[Path] OCIUser user:alice@EXAMPLE  (2 hops)
  OCIUser user:alice@EXAMPLE
    └─[OCI_GROUP_MEMBER]─> OCIGroup group:AdminsLite@EXAMPLE
    └─[OCI_MANAGE]─> OCIResource all-resources
        (manage all-resources in tenancy EXAMPLE)

End-to-End Workflow

# 1. Enumerate across every service, recursing compartments (see Operator Runbook)
modules run enum_all --comp --get

# 2. Build the OpenGraph JSON
modules run process_oracle_cloud_hound_data

# 3. Text-based attack paths — who can reach manage/IAM-control/RPST?
modules run process_og_attack_paths --graph-json <export>/oracle_cloud_hound.json

# 4. Narrow + export for a report
modules run process_og_attack_paths --graph-json <export>/oracle_cloud_hound.json \
    --to-manage --exclude-service-agents --no-direct --json --output manage_paths.json

Then triage each path against the abuse/defense notes in OpenGraph - Default Priv Escalation Mode.

Clone this wiki locally