Introduction
For several years, one of the biggest pain-points with contributing to BloodHound has been in getting nodes and edges ingested and correctly displayed in the GUI. BloodHound OpenGraph changes that. Now it is easy for anyone to add nodes and edges into BloodHound through the easy-to-use/file-upload/
endpoint.
However, while the process of adding nodes and edges to the product is greatly simplified, the product will not function as expected without a well-designed attack graph model. This document seeks to educate users on attack graph model design theory, best-practices, and requirements.
An attack graph is a tool - a powerful force multiplier when wielded correctly, a frustrating and confusing hazard when not. This document aims to equip you with the knowledge and skills necessary to effectively wield this tool.
In the initial BloodHound 8.0 release, OpenGraph nodes and edges are not supported in the Search or Pathfinding tab, so the Cypher tab must be used to query the data manually.
Basic Attack Graph Vocabulary and Design Theory
Graphs are well-understood, well-studied mathematical constructs. You can find thousands of guides, tools, and academic papers that make use of graphs. This document will not replace a proper education or time spent working with graphs. But in this section we will touch on the most fundamental aspects of a graph you must understand in order to effectively get BloodHound to work with your nodes and edges. Every graph is constructed from two fundamental components: vertices (nodes) and edges (relationships):



- “User” and “Group” via the “MemberOf” edge
- “Group” and “Domain” via the “GenericAll” edge

- From the red (top left) to the pink (top right) node
- From the blue (bottom left) to the green (bottom right) node



BloodHound Attack Graph Model Requirements
The second habit of highly effective people is:Habit 2: Begin With the End in Mind means to start with a clear understanding of your destination. You need to know where you are going in order to better understand where you are now so that the steps you take are always in the right direction.You don’t want to pour your heart and soul into a data model only to find out that most BloodHound features don’t work with your model. Here are the non-negotiable requirements your model must comply with to work with BloodHound:
Requirement 1: Universally Unique Node Identifiers
Every node in a BloodHound database must have a universally unique identifier to distinguish it from every other node. You must identify the source and format of that identifier. We used to use UPN-formatted names for identifiers in BloodHound (e.g.: “DOMAIN ADMINS@CONTOSO.COM”). Surprise surprise, UPNs are not guaranteed to be universally unique. We now use SIDs instead for universally unique identifiers for most Active Directory principals. One of the best universally unique identifiers is a GUID. Does the entity you are modeling have a GUID? If so, great! If not, you’re going to need to find something else. Examples of bad identifiers:- Usernames
- Email addresses
- Hostnames
- IDs that start at “0” and increment from there
- GUIDs
- SIDs
- Certificate thumbprints
Requirement 2: Distinct Node and Edge Classes
If you are modeling a new system not currently modeled by BloodHound, your nodes and edges must have distinct classes that do not overlap with existing BloodHound node and edge classes. Sorry, but “MemberOf” is already taken, so you will need to use a different edge class when modeling group memberships in Okta, Zoho, AWS, or whatever else. Same with all the other existing node and edge classes which can be found here:Requirement 3: Your Model Must Connect Non-Adjacent Nodes with Paths
If your graph model does not create paths connecting non-adjacent nodes, you should be using a relational database, not a graph database. You are using the wrong tool for the job!This article is based on Andy’s blog Attack Graph Model Design Requirements and Examples that goes beyond what’s described here.