diff --git a/cmd/api/src/api/v2/file_uploads_integration_test.go b/cmd/api/src/api/v2/file_uploads_integration_test.go index bf2acb2959..6df73ae3ea 100644 --- a/cmd/api/src/api/v2/file_uploads_integration_test.go +++ b/cmd/api/src/api/v2/file_uploads_integration_test.go @@ -168,6 +168,7 @@ func Test_FileUploadWorkFlowVersion6(t *testing.T) { //Assert that we created stuff we expected testCtx.AssertIngest(fixtures.IngestAssertions) + testCtx.AssertIngest(fixtures.IngestAssertionsv6) } func Test_FileUploadVersion6AllOptionADCS(t *testing.T) { @@ -234,4 +235,5 @@ func Test_CompressedFileUploadWorkFlowVersion6(t *testing.T) { //Assert that we created stuff we expected testCtx.AssertIngest(fixtures.IngestAssertions) + testCtx.AssertIngest(fixtures.IngestAssertionsv6) } diff --git a/cmd/api/src/test/fixtures/fixtures/expected_ingest.go b/cmd/api/src/test/fixtures/fixtures/expected_ingest.go index 7b06ce0c1a..1324cf5a2a 100644 --- a/cmd/api/src/test/fixtures/fixtures/expected_ingest.go +++ b/cmd/api/src/test/fixtures/fixtures/expected_ingest.go @@ -245,6 +245,14 @@ var ( query.Equals(query.EndProperty(common.ObjectID.String()), "S-1-5-21-3130019616-2776909439-2417379446-2117"), query.Equals(query.RelationshipProperty(ad.LogonType.String()), 2)), } + v6ingestRelationshipAssertionCriteria = []graph.Criteria{ + query.And( + query.Kind(query.Start(), ad.Computer), + query.Equals(query.StartProperty(common.ObjectID.String()), "S-1-5-21-3130019616-2776909439-2417379446-1001"), + query.Kind(query.Relationship(), ad.DCFor), + query.Kind(query.End(), ad.Domain), + query.Equals(query.EndProperty(common.ObjectID.String()), "S-1-5-21-3130019616-2776909439-2417379446")), + } ) func FormatQueryComponent(criteria graph.Criteria) string { @@ -266,3 +274,10 @@ func IngestAssertions(testCtrl test.Controller, tx graph.Transaction) { require.Nilf(testCtrl, err, "Unable to find an expected relationship: %s", FormatQueryComponent(assertionCriteria)) } } + +func IngestAssertionsv6(testCtrl test.Controller, tx graph.Transaction) { + for _, assertionCriteria := range v6ingestRelationshipAssertionCriteria { + _, err := tx.Relationships().Filter(assertionCriteria).First() + require.Nilf(testCtrl, err, "Unable to find an expected relationship: %s", FormatQueryComponent(assertionCriteria)) + } +} diff --git a/cmd/api/src/test/fixtures/fixtures/v6/ingest/computers.json b/cmd/api/src/test/fixtures/fixtures/v6/ingest/computers.json index 4442c3c053..b4b455cbec 100644 --- a/cmd/api/src/test/fixtures/fixtures/v6/ingest/computers.json +++ b/cmd/api/src/test/fixtures/fixtures/v6/ingest/computers.json @@ -343,7 +343,9 @@ ], "ObjectIdentifier": "S-1-5-21-3130019616-2776909439-2417379446-1001", "IsDeleted": false, - "IsACLProtected": false + "IsACLProtected": false, + "IsDC": true, + "DomainSID": "S-1-5-21-3130019616-2776909439-2417379446" }, { "Properties": { diff --git a/packages/cue/bh/ad/ad.cue b/packages/cue/bh/ad/ad.cue index c6922385a3..aace277a96 100644 --- a/packages/cue/bh/ad/ad.cue +++ b/packages/cue/bh/ad/ad.cue @@ -1134,5 +1134,6 @@ PathfindingRelationships: [ ADCSESC4, ADCSESC5, ADCSESC6, - ADCSESC7 + ADCSESC7, + DCFor ] diff --git a/packages/go/analysis/ad/filters.go b/packages/go/analysis/ad/filters.go index 7465128e72..667c8c87c2 100644 --- a/packages/go/analysis/ad/filters.go +++ b/packages/go/analysis/ad/filters.go @@ -163,6 +163,9 @@ func SelectComputersCandidateFilter(node *graph.Node) bool { func SelectGPOTierZeroCandidateFilter(node *graph.Node) bool { if tags, err := node.Properties.Get(common.SystemTags.String()).String(); err != nil { return false + } else if node.Kinds.ContainsOneOf(ad.Group) { + // GPOs don’t apply to groups. + return false } else { return strings.Contains(tags, ad.AdminTierZero) } diff --git a/packages/go/analysis/ad/filters_test.go b/packages/go/analysis/ad/filters_test.go new file mode 100644 index 0000000000..340a7d634b --- /dev/null +++ b/packages/go/analysis/ad/filters_test.go @@ -0,0 +1,38 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +package ad_test + +import ( + ad2 "github.com/specterops/bloodhound/analysis/ad" + "github.com/specterops/bloodhound/dawgs/graph" + "github.com/specterops/bloodhound/graphschema/ad" + "github.com/specterops/bloodhound/graphschema/common" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSelectGPOContainerCandidateFilter(t *testing.T) { + var ( + computer = graph.NewNode(0, graph.NewProperties(), ad.Computer) + group = graph.NewNode(1, graph.NewProperties().Set(common.SystemTags.String(), ad.AdminTierZero), ad.Group) + user = graph.NewNode(2, graph.NewProperties().Set(common.SystemTags.String(), ad.AdminTierZero), ad.User) + ) + + assert.False(t, ad2.SelectGPOContainerCandidateFilter(computer)) + assert.False(t, ad2.SelectGPOTierZeroCandidateFilter(group)) + assert.True(t, ad2.SelectGPOTierZeroCandidateFilter(user)) +} diff --git a/packages/go/ein/ad.go b/packages/go/ein/ad.go index db6f927166..b0acf15437 100644 --- a/packages/go/ein/ad.go +++ b/packages/go/ein/ad.go @@ -256,7 +256,7 @@ func ParseDomainTrusts(domain Domain) ParsedDomainTrustData { return parsedData } -// ParseComputerMiscData parses AllowedToDelegate, AllowedToAct, HasSIDHistory,DumpSMSAPassword and Sessions +// ParseComputerMiscData parses AllowedToDelegate, AllowedToAct, HasSIDHistory,DumpSMSAPassword,DCFor and Sessions func ParseComputerMiscData(computer Computer) []IngestibleRelationship { relationships := make([]IngestibleRelationship, 0) for _, target := range computer.AllowedToDelegate { @@ -342,6 +342,17 @@ func ParseComputerMiscData(computer Computer) []IngestibleRelationship { } } + if computer.IsDC && computer.DomainSID != "" { + relationships = append(relationships, IngestibleRelationship{ + Source: computer.ObjectIdentifier, + SourceType: ad.Computer, + TargetType: ad.Domain, + Target: computer.DomainSID, + RelProps: map[string]any{"isacl": false}, + RelType: ad.DCFor, + }) + } + return relationships } diff --git a/packages/go/ein/incoming_models.go b/packages/go/ein/incoming_models.go index 1b55af1cef..c74ff29c89 100644 --- a/packages/go/ein/incoming_models.go +++ b/packages/go/ein/incoming_models.go @@ -259,6 +259,8 @@ type Computer struct { DCRegistryData DCRegistryData Status ComputerStatus HasSIDHistory []TypedPrincipal + IsDC bool + DomainSID string } type OU struct { diff --git a/packages/go/graphschema/ad/ad.go b/packages/go/graphschema/ad/ad.go index 031a147863..ccfe7bffc8 100644 --- a/packages/go/graphschema/ad/ad.go +++ b/packages/go/graphschema/ad/ad.go @@ -644,7 +644,7 @@ func ACLRelationships() []graph.Kind { return []graph.Kind{AllExtendedRights, ForceChangePassword, AddMember, AddAllowedToAct, GenericAll, WriteDACL, WriteOwner, GenericWrite, ReadLAPSPassword, ReadGMSAPassword, Owns, AddSelf, WriteSPN, AddKeyCredentialLink, GetChanges, GetChangesAll, GetChangesInFilteredSet, WriteAccountRestrictions, SyncLAPSPassword, DCSync, ManageCertificates, ManageCA, Enroll, WritePKIEnrollmentFlag, WritePKINameFlag} } func PathfindingRelationships() []graph.Kind { - return []graph.Kind{Owns, GenericAll, GenericWrite, WriteOwner, WriteDACL, MemberOf, ForceChangePassword, AllExtendedRights, AddMember, HasSession, Contains, GPLink, AllowedToDelegate, TrustedBy, AllowedToAct, AdminTo, CanPSRemote, CanRDP, ExecuteDCOM, HasSIDHistory, AddSelf, DCSync, ReadLAPSPassword, ReadGMSAPassword, DumpSMSAPassword, SQLAdmin, AddAllowedToAct, WriteSPN, AddKeyCredentialLink, SyncLAPSPassword, WriteAccountRestrictions, GoldenCert, ADCSESC1, ADCSESC3, ADCSESC4, ADCSESC5, ADCSESC6, ADCSESC7} + return []graph.Kind{Owns, GenericAll, GenericWrite, WriteOwner, WriteDACL, MemberOf, ForceChangePassword, AllExtendedRights, AddMember, HasSession, Contains, GPLink, AllowedToDelegate, TrustedBy, AllowedToAct, AdminTo, CanPSRemote, CanRDP, ExecuteDCOM, HasSIDHistory, AddSelf, DCSync, ReadLAPSPassword, ReadGMSAPassword, DumpSMSAPassword, SQLAdmin, AddAllowedToAct, WriteSPN, AddKeyCredentialLink, SyncLAPSPassword, WriteAccountRestrictions, GoldenCert, ADCSESC1, ADCSESC3, ADCSESC4, ADCSESC5, ADCSESC6, ADCSESC7, DCFor} } func IsACLKind(s graph.Kind) bool { for _, acl := range ACLRelationships() { diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/ADCSESC6a.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/ADCSESC6a.tsx new file mode 100644 index 0000000000..35d0f7205c --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/ADCSESC6a.tsx @@ -0,0 +1,31 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import General from './General'; +import WindowsAbuse from './WindowsAbuse'; +import LinuxAbuse from './LinuxAbuse'; +import Opsec from './Opsec'; +import References from './References'; + +const ADCSESC6a = { + general: General, + windowsAbuse: WindowsAbuse, + linuxAbuse: LinuxAbuse, + opsec: Opsec, + references: References, +}; + +export default ADCSESC6a; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/General.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/General.tsx new file mode 100644 index 0000000000..1fa2df4a11 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/General.tsx @@ -0,0 +1,44 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { groupSpecialFormat } from '../utils'; +import { EdgeInfoProps } from '../index'; +import { Typography } from '@mui/material'; + +const General: FC = ({ sourceName, sourceType, targetName }) => { + return ( + <> + + {groupSpecialFormat(sourceType, sourceName)} the privileges to perform the ADCS ESC6 Scenario A attack + against the target domain. + + + The principal has permission to enroll on one or more certificate templates allowing for authentication. + They also have enrollment permission for an enterprise CA with the necessary templates published. This + enterprise CA is trusted for NT authentication in the forest, and chains up to a root CA for the forest. + The enterprise CA is configured with the EDITF_ATTRIBUTESUBJECTALTNAME2 flag allowing enrollees to + specify a Subject Alternate Name (SAN) identifying another principal during certificate enrollment of + any published certificate template. This setup allow an attacker principal to obtain a malicious + certificate as another principal. There is an affected Domain Controller configured to allow weak + certificate binding enforcement, which enables the attacker principal to authenticate with the malicious + certificate and thereby impersonating any AD forest user or computer without their credentials. + + + ); +}; + +export default General; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/LinuxAbuse.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/LinuxAbuse.tsx new file mode 100644 index 0000000000..874627307e --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/LinuxAbuse.tsx @@ -0,0 +1,42 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const LinuxAbuse: FC = () => { + return ( + <> + An attacker may perform this attack in the following steps: + + Step 1: Use Certipy to request enrollment in the affected template, specifying the affected + enterprise CA and target principal to impersonate: + + + { + 'certipy req -u john@corp.local -p Passw0rd -ca corp-DC-CA -target ca.corp.local -template ESC6 -upn administrator@corp.local' + } + + + Step 2: Request a ticket granting ticket (TGT) from the domain, specifying the certificate + created in Step 1 and the IP of a domain controller: + + {'certipy auth -pfx administrator.pfx -dc-ip 172.16.126.128'} + + ); +}; + +export default LinuxAbuse; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/Opsec.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/Opsec.tsx new file mode 100644 index 0000000000..0200106041 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/Opsec.tsx @@ -0,0 +1,31 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const Opsec: FC = () => { + return ( + + When the affected certificate authority issues the certificate to the attacker, it will retain a local copy + of that certificate in its issued certificates store. Defenders may analyze those issued certificates to + identify illegitimately issued certificates and identify the principal that requested the certificate, as + well as the target identity the attacker is attempting to impersonate. + + ); +}; + +export default Opsec; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/References.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/References.tsx new file mode 100644 index 0000000000..ff137d162c --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/References.tsx @@ -0,0 +1,47 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Link, Box } from '@mui/material'; + +const References: FC = () => { + return ( + + + Certified Pre-Owned + +
+ + Certipy 4.0 + +
+ + Domain Escalation Edit Attributes + +
+ ); +}; + +export default References; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/WindowsAbuse.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/WindowsAbuse.tsx new file mode 100644 index 0000000000..12e36054d6 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/ADCSESC6a/WindowsAbuse.tsx @@ -0,0 +1,52 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const WindowsAbuse: FC = () => { + return ( + <> + An attacker may perform this attack in the following steps: + + Step 1: Use Certify to request enrollment in the affected template, specifying the affected + enterprise CA and target principal to impersonate: + + + { + '.\\Certify.exe request /ca:rootdomaindc.forestroot.com\\forestroot-RootDomainDC-CA /template:ESC6 /altname:forestroot\\ForestRootDA' + } + + + Step 2: Convert the emitted certificate to PFX format: + + {'certutil.exe -MergePFX .cert.pem .cert.pfx'} + + Step 3: Use Rubeus to request a ticket granting ticket (TGT) from the domain, specifying the + target identity to impersonate and the PFX-formatted certificate created in Step 2: + + + {'.\\Rubeus.exe asktgt /certificate:cert.pfx /user:”forestroot\\forestrootda” /password:asdf /ptt'} + + + Step 4: Optionally verify the TGT by listing it with the klist command: + + {'klist'} + + ); +}; + +export default WindowsAbuse; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/CanAbuseUPNCertMapping.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/CanAbuseUPNCertMapping.tsx new file mode 100644 index 0000000000..354fc850a9 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/CanAbuseUPNCertMapping.tsx @@ -0,0 +1,31 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import General from './General'; +import WindowsAbuse from './WindowsAbuse'; +import LinuxAbuse from './LinuxAbuse'; +import Opsec from './Opsec'; +import References from './References'; + +const CanAbuseUPNCertMapping = { + general: General, + windowsAbuse: WindowsAbuse, + linuxAbuse: LinuxAbuse, + opsec: Opsec, + references: References, +}; + +export default CanAbuseUPNCertMapping; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/General.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/General.tsx new file mode 100644 index 0000000000..26a2231d33 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/General.tsx @@ -0,0 +1,31 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { EdgeInfoProps } from '../index'; +import { Typography } from '@mui/material'; + +const General: FC = ({ sourceName, sourceType, targetName }) => { + return ( + + This edge is created when BloodHound identifies a domain controller with particular certificate mapping + methods configured in the registry. This edge alone is not enough to perform an abuse, but may be part of + several other node and edge configurations that create the conditions for abusable ADCS edges. + + ); +}; + +export default General; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/LinuxAbuse.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/LinuxAbuse.tsx new file mode 100644 index 0000000000..14266ff24a --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/LinuxAbuse.tsx @@ -0,0 +1,29 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const LinuxAbuse: FC = () => { + return ( + + An attacker may perform an ADCS ESC6 or ESC10 attack that relies on this relationship. This relationship + alone is not enough to escalate rights or impersonate other principals. + + ); +}; + +export default LinuxAbuse; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/Opsec.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/Opsec.tsx new file mode 100644 index 0000000000..0200106041 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/Opsec.tsx @@ -0,0 +1,31 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const Opsec: FC = () => { + return ( + + When the affected certificate authority issues the certificate to the attacker, it will retain a local copy + of that certificate in its issued certificates store. Defenders may analyze those issued certificates to + identify illegitimately issued certificates and identify the principal that requested the certificate, as + well as the target identity the attacker is attempting to impersonate. + + ); +}; + +export default Opsec; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/References.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/References.tsx new file mode 100644 index 0000000000..860e6a56d7 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/References.tsx @@ -0,0 +1,40 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Link, Box } from '@mui/material'; + +const References: FC = () => { + return ( + + + Certified Pre-Owned + +
+ + Certipy 4.0 + +
+ ); +}; + +export default References; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/WindowsAbuse.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/WindowsAbuse.tsx new file mode 100644 index 0000000000..8a2adb5f30 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseUPNCertMapping/WindowsAbuse.tsx @@ -0,0 +1,29 @@ +// Copyright 2024 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const WindowsAbuse: FC = () => { + return ( + + An attacker may perform an ADCS ESC6 or ESC10 attack that relies on this relationship. This relationship + alone is not enough to escalate rights or impersonate other principals. + + ); +}; + +export default WindowsAbuse; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/CanAbuseWeakCertBinding.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/CanAbuseWeakCertBinding.tsx new file mode 100644 index 0000000000..f83a3d4c75 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/CanAbuseWeakCertBinding.tsx @@ -0,0 +1,31 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import General from './General'; +import WindowsAbuse from './WindowsAbuse'; +import LinuxAbuse from './LinuxAbuse'; +import Opsec from './Opsec'; +import References from './References'; + +const ADCSESC1 = { + general: General, + windowsAbuse: WindowsAbuse, + linuxAbuse: LinuxAbuse, + opsec: Opsec, + references: References, +}; + +export default ADCSESC1; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/General.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/General.tsx new file mode 100644 index 0000000000..4e49c91cb5 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/General.tsx @@ -0,0 +1,31 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { EdgeInfoProps } from '../index'; +import { Typography } from '@mui/material'; + +const General: FC = ({ sourceName, sourceType, targetName }) => { + return ( + + This edge is created when BloodHound identifies a domain controller with a particular certificate binding + enforcement configuration in the registry. This edge alone is not enough to perform an abuse, but may be + part of several other node and edge configurations that create the conditions for abusable ADCS edges. + + ); +}; + +export default General; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/LinuxAbuse.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/LinuxAbuse.tsx new file mode 100644 index 0000000000..80c80eb16c --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/LinuxAbuse.tsx @@ -0,0 +1,29 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const LinuxAbuse: FC = () => { + return ( + + An attacker may perform an ADCS ESC6 or ESC9 attack that relies on this relationship. This relationship + alone is not enough to escalate rights or impersonate other principals. + + ); +}; + +export default LinuxAbuse; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/Opsec.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/Opsec.tsx new file mode 100644 index 0000000000..7a43445c57 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/Opsec.tsx @@ -0,0 +1,31 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const Opsec: FC = () => { + return ( + + When the affected certificate authority issues the certificate to the attacker, it will retain a local copy + of that certificate in its issued certificates store. Defenders may analyze those issued certificates to + identify illegitimately issued certificates and identify the principal that requested the certificate, as + well as the target identity the attacker is attempting to impersonate. + + ); +}; + +export default Opsec; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/References.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/References.tsx new file mode 100644 index 0000000000..d254bf2f6c --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/References.tsx @@ -0,0 +1,40 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Link, Box } from '@mui/material'; + +const References: FC = () => { + return ( + + + Certified Pre-Owned + +
+ + Certipy 4.0 + +
+ ); +}; + +export default References; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/WindowsAbuse.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/WindowsAbuse.tsx new file mode 100644 index 0000000000..f07b003205 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/CanAbuseWeakCertBinding/WindowsAbuse.tsx @@ -0,0 +1,29 @@ +// Copyright 2023 Specter Ops, Inc. +// +// Licensed under the Apache License, Version 2.0 +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +import { FC } from 'react'; +import { Typography } from '@mui/material'; + +const WindowsAbuse: FC = () => { + return ( + + An attacker may perform an ADCS ESC6 or ESC9 attack that relies on this relationship. This relationship + alone is not enough to escalate rights or impersonate other principals. + + ); +}; + +export default WindowsAbuse; diff --git a/packages/javascript/bh-shared-ui/src/components/HelpTexts/index.tsx b/packages/javascript/bh-shared-ui/src/components/HelpTexts/index.tsx index c898b7d475..f94169e206 100644 --- a/packages/javascript/bh-shared-ui/src/components/HelpTexts/index.tsx +++ b/packages/javascript/bh-shared-ui/src/components/HelpTexts/index.tsx @@ -1,4 +1,4 @@ -// Copyright 2023 Specter Ops, Inc. +// Copyright 2024 Specter Ops, Inc. // // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. @@ -64,6 +64,8 @@ import AdminTo from './AdminTo/AdminTo'; import AllExtendedRights from './AllExtendedRights/AllExtendedRights'; import AllowedToAct from './AllowedToAct/AllowedToAct'; import AllowedToDelegate from './AllowedToDelegate/AllowedToDelegate'; +import CanAbuseUPNCertMapping from './CanAbuseUPNCertMapping/CanAbuseUPNCertMapping'; +import CanAbuseWeakCertBinding from './CanAbuseWeakCertBinding/CanAbuseWeakCertBinding'; import CanPSRemote from './CanPSRemote/CanPSRemote'; import CanRDP from './CanRDP/CanRDP'; import Contains from './Contains/Contains'; @@ -107,6 +109,7 @@ import WritePKIEnrollmentFlag from './WritePKIEnrollmentFlag/WritePKIEnrollmentF import WritePKINameFlag from './WritePKINameFlag/WritePKINameFlag'; import WriteSPN from './WriteSPN/WriteSPN'; import ADCSESC1 from './ADCSESC1/ADCSESC1'; +import ADCSESC6a from './ADCSESC6a/ADCSESC6a'; import ADCSESC6b from './ADCSESC6b/ADCSESC6b'; export type EdgeInfoProps = { @@ -145,6 +148,8 @@ const EdgeInfoComponents = { ReadGMSAPassword: ReadGMSAPassword, HasSIDHistory: HasSIDHistory, TrustedBy: TrustedBy, + CanAbuseUPNCertMapping: CanAbuseUPNCertMapping, + CanAbuseWeakCertBinding: CanAbuseWeakCertBinding, CanPSRemote: CanPSRemote, AZAddMembers: AZAddMembers, AZAddSecret: AZAddSecret, @@ -208,6 +213,7 @@ const EdgeInfoComponents = { GoldenCert: GoldenCert, ADCSESC1: ADCSESC1, ADCSESC3: ADCSESC3, + ADCSESC6a: ADCSESC6a, ADCSESC6b: ADCSESC6b, ManageCA: ManageCA, ManageCertificates: ManageCertificates, diff --git a/packages/javascript/bh-shared-ui/src/graphSchema.ts b/packages/javascript/bh-shared-ui/src/graphSchema.ts index 04c748bcc2..05ddc0b561 100644 --- a/packages/javascript/bh-shared-ui/src/graphSchema.ts +++ b/packages/javascript/bh-shared-ui/src/graphSchema.ts @@ -520,6 +520,7 @@ export function ActiveDirectoryPathfindingEdges(): ActiveDirectoryRelationshipKi ActiveDirectoryRelationshipKind.ADCSESC5, ActiveDirectoryRelationshipKind.ADCSESC6, ActiveDirectoryRelationshipKind.ADCSESC7, + ActiveDirectoryRelationshipKind.DCFor, ]; } export enum AzureNodeKind {