Do You Own Your Permissions, or Do Your Permissions Own You?
tl;dr: Less FPs for Owns/WriteOwner and new Owns/WriteOwnerLimitedRights edges
Before we get started, if you’d prefer to listen to a 10-minute presentation instead of or to supplement reading this post, please check out the recording of our most recent BloodHound Release Recap webinar. You can also sign up for future webinars here.
Back in August, a BloodHound Enterprise (BHE) customer told us that they had implemented an Active Directory (AD) setting called BlockOwnerImplicitRights to help address some attack paths related to object ownership (e.g., Owns, WriteOwner), but the findings were still present in their graph.
Until this point, I had assumed that the owner of an AD object was always implicitly granted permissions to modify that object’s security descriptor to compromise the underlying computer/user (WriteDacl). This is the logic the Owns and WriteOwner edges were built upon. What was this setting I’d never heard of?
The first thing our team did was review the Microsoft documentation to estimate the work effort in removing these false positives.
Turns out, Microsoft introduced BlockOwnerImplicitRights as the 29th bit in a forest’s dSHeuristics attribute to prevent a vaguely-worded vulnerability where a user with permission to create computer-derived AD objects could modify security descriptors and sensitive attributes to elevate privileges in certain scenarios.
According to Microsoft, “The Owner of a security descriptor is implicitly granted READ_CONTROL and WRITE_DAC rights by default… these implicit rights are blocked when the following are TRUE:
- The BlockOwnerImplicitRights dsHeuristic is set to 1.
- The requester is a member of neither the Domain Administrators or the Enterprise Administrators group.
- The objectClass being added or modified is either of type computer or is derived from type computer.”
Next, we read Jim Sykora’s excellent Owner or Pwned whitepaper, which dives into a lot more technical detail on which principal becomes the owner when objects are created, what owner permissions are abusable in different scenarios, and proactive and reactive considerations for implementing preventative controls. I highly recommend reading it to dive further into these concepts.
Now things were starting to make sense. If I understood correctly, enforcing the BlockOwnerImplicitRights bit of the dSHeuristics attribute could prevent certain scenarios we have exploited in real customer environments during offensive operations.
Consider this example:
An organization’s server team uses a specific account to programmatically join new systems to the domain, for example using Microsoft Configuration Manager (formerly SCCM — I physically can’t write a post without mentioning it) or a PowerShell script.
Remember, the account that joins a computer to the domain becomes the owner of the created object in many scenarios (detailed further in Jim’s whitepaper).
Years later, a computer joined to the domain by this account is promoted to a domain controller or is added to tier zero and is now susceptible to WriteDacl abuse via the owner’s implicit rights if the account that joined the system to the domain is compromised.
We have encountered many scenarios where ancient domain join credentials are exposed in a script on a file share or user’s desktop or can be decrypted from the SCCM operating system deployment task sequence, allowing us to compromise every computer they joined to the domain via their implicit WriteDacl permission.
Enter the BlockOwnerImplicitRights attribute.
If implicit ownership rights are blocked for these computer objects, the account that joined a computer to the domain cannot easily compromise the underlying machine via implicit WriteDacl abuse, unless they are already a member of Domain Admins/Enterprise Admins.
Implicit owner rights are also blocked when an ACE explicitly grants a permission to the OWNER RIGHTS SID (S-1–3–4). In this case, the owner is only granted the specific permissions in these ACEs. Here is another reference explaining use cases for this SID.
To fully understand the mechanics of these settings and how they impacted BloodHound, Matt Creel (@Tw1sm) got to work redesigning the Owns edge to eliminate false positives and accurately depict where these security features were enabled.
First, we needed to create a new edge called OwnsLimitedRights to identify any specific permissions granted to the object owner when an ACE is defined for the OWNER RIGHTS SID.
To summarize, implicit ownership rights are blocked if either of the following conditions are true:
- The OWNER RIGHTS SID (S-1–3–4) is explicitly granted a permission
OR
- BlockOwnerImplicitRights (29th bit of dSHeuristics ) is set to 1
- The owner is not a member of Domain Admins or Enterprise Admins
- The owned object is a computer or derived type
We landed on this design for the Owns and OwnsLimitedRights edges that were updated/introduced in BloodHound v7.1.0.
How are WriteOwner permissions impacted by these changes?
Matt found that this was a bit more complex because ACEs defining permissions for the OWNER RIGHTS SID that are not inherited (i.e., are explicitly defined) are removed from objects when their owner changes.
As a result, we needed to check whether any ACE granted rights to the OWNER RIGHTS SID (S-1–3–4), whether such an ACE was inherited or explicitly defined, and whether it granted abusable permissions in order to correctly depict the WriteOwner edge. We also created a new edge called WriteOwnerLimitedRights that identifies specific abusable permissions granted to the OWNER RIGHTS SID.
We landed on this design for the WriteOwner and WriteOwnerLimitedRights edges, which are also in BloodHound since v7.1.0:
I picked up where Matt left off to implement these changes with a ton of help from Rohan Varzarkar (@CptJesus) and John Hopper, our Director of Engineering.
To process the outcome of each of these scenarios, we needed to compare the forest’s dSHeuristics attribute value to the ACEs on each domain object. Since we don’t know what order data will be uploaded to BloodHound in or whether it’s complete (e.g., only the computers.json or domains.json file is uploaded), that meant we had to add portions of the logic to post-processing, which is the phase that occurs after ingestion of all data during a single upload.
Other portions of the logic could be created during the ingestion phase itself, such as creating edges when the OWNER RIGHTS SID is explicitly granted abusable permissions, in which case we never need to look at the dSHeuristics attribute since implicit owner rights are never granted.
To make the change backwards-compatible with previous SharpHound and third-party collector versions and as lightweight as possible, we wanted to avoid collecting every single ACE (as opposed to only abusable ACEs like SharpHound had always done), but we also needed to know whether any non-abusable permissions were granted to the OWNER RIGHTS SID and whether any such permissions were inherited. As a result, we created two new boolean properties for each object, DoesAnyAceGrantOwnerRights and DoesAnyInheritedAceGrantOwnerRights.
While coding and wiring everything together, we had to account for several other complex scenarios. For example, when both explicitly defined, abusable permissions and inherited, non-abusable permissions are granted to the OWNER RIGHTS SID, the explicitly defined permissions are deleted on ownership change but the inherited ones are not, so the Owns ACE is abusable but WriteOwner ACEs are not. In other cases where explicitly defined, non-abusable permissions are granted to the OWNER RIGHTS SID, the Owns ACE is not abusable. However, those explicitly defined permissions are deleted on owner change, so WriteOwner ACEs could be abusable if the forest’s BlockOwnerImplicitRights attribute is not set or if it is set but the object is not a computer-derived type.
The good news is, BloodHound does all of this processing for you now!
These changes resulted in the following PRs:
- https://github.com/SpecterOps/BloodHound/pull/993
- https://github.com/SpecterOps/SharpHound/pull/124
- https://github.com/SpecterOps/SharpHoundCommon/pull/176
As well as an update to BHE.
The majority of the ingest and post-processing logic is implemented in these files:
- https://github.com/SpecterOps/BloodHound/blob/4dcd8074870c7b3e14fc1da220fe080acc2cce60/packages/go/ein/ad.go#L268
- https://github.com/SpecterOps/BloodHound/blob/main/packages/go/analysis/ad/owns.go
We learned that implementing these changes eliminated a ton of false positives from the graph for BloodHound users who block owner implicit rights. Users also get the OwnsLimitedRights and WriteOwnerLimitedRights edges “for free”, regardless of what collector they use, because these edges do not depend on collection of dSHeuristics or non-abusable OWNER RIGHTS ACEs.
In the diagrams below:
- Red edges are now recalculated and removed as false positives when using the new SharpHound collector and BloodHound release
- Green edges are reclassified as OwnsLimitedRights/WriteOwnerLimitedRights
- Blue edges are unchanged
BlockOwnerImplicitRights = 1:

BlockOwnerImplicitRights = 0:

Thanks for reading! If you have any questions or feedback for this post, please reach out to me (@_Mayyhem) on Twitter or in the BloodHound Slack (@Mayyhem)!
Do You Own Your Permissions, or Do Your Permissions Own You? was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.
The post Do You Own Your Permissions, or Do Your Permissions Own You? appeared first on Security Boulevard.
>>More