Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/CommonLib/Enums/CollectionMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ public enum CollectionMethod {
WebClientService = 1 << 21,
SmbInfo = 1 << 22,
NTLMRegistry = 1 << 23,
Site = 1 << 24,
//TODO: Re-introduce this when we're ready for Event Log collection
//EventLogs = 1 << 23,
LocalGroups = DCOM | RDP | LocalAdmin | PSRemote,
ComputerOnly = LocalGroups | Session | UserRights | CARegistry | DCRegistry | WebClientService | SmbInfo | NTLMRegistry,
DCOnly = ACL | Container | Group | ObjectProps | Trusts | GPOLocalGroup | CertServices,

Default = Group | Session | Trusts | ACL | ObjectProps | LocalGroups | SPNTargets | Container | CertServices |
LdapServices | SmbInfo | WebClientService,
LdapServices | SmbInfo | WebClientService | Site,

All = Default | LoggedOn | GPOLocalGroup | UserRights | CARegistry | DCRegistry | WebClientService |
LdapServices | NTLMRegistry
Expand Down
3 changes: 3 additions & 0 deletions src/CommonLib/Enums/DataType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ public static class DataType
public const string EnterpriseCAs = "enterprisecas";
public const string CertTemplates = "certtemplates";
public const string IssuancePolicies = "issuancepolicies";
public const string Sites = "sites";
public const string SiteServers = "siteservers";
public const string SiteSubnets = "sitesubnets";
}
}
2 changes: 2 additions & 0 deletions src/CommonLib/Enums/LDAPProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,7 @@ public static class LDAPProperties
public const string LockOutObservationWindow = "lockoutobservationwindow";
public const string PrincipalName = "msds-principalname";
public const string GroupType = "grouptype";
public const string ServerReference = "serverreference";
public const string SiteObject = "siteobject";
}
}
5 changes: 4 additions & 1 deletion src/CommonLib/Enums/Labels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public enum Label
AIACA,
EnterpriseCA,
NTAuthStore,
IssuancePolicy
IssuancePolicy,
Site,
SiteServer,
SiteSubnet
}
}
3 changes: 3 additions & 0 deletions src/CommonLib/Enums/ObjectClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ public static class ObjectClass {
public const string OIDContainerClass = "msPKI-Enterprise-Oid";
public const string GMSAClass = "msds-groupmanagedserviceaccount";
public const string MSAClass = "msds-managedserviceaccount";
public const string SiteClass = "site";
public const string SiteServerClass = "server";
public const string SiteSubnetClass = "subnet";
}
12 changes: 10 additions & 2 deletions src/CommonLib/LdapProducerQueryGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ public static GeneratedLdapParameters GenerateConfigurationPartitionParameters(C
properties.AddRange(CommonProperties.TypeResolutionProps);

if (methods.HasFlag(CollectionMethod.ACL) || methods.HasFlag(CollectionMethod.ObjectProps) ||
methods.HasFlag(CollectionMethod.Container) || methods.HasFlag(CollectionMethod.CertServices)) {
methods.HasFlag(CollectionMethod.Container) || methods.HasFlag(CollectionMethod.CertServices) ||
methods.HasFlag(CollectionMethod.Site)) {
filter = filter.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities()
.AddEnterpriseCertificationAuthorities().AddIssuancePolicies();
.AddEnterpriseCertificationAuthorities().AddIssuancePolicies().AddSites().AddSiteServers().AddSiteSubnets();

if (methods.HasFlag(CollectionMethod.ObjectProps)) {
properties.AddRange(CommonProperties.ObjectPropsProps);
Expand All @@ -131,6 +132,13 @@ public static GeneratedLdapParameters GenerateConfigurationPartitionParameters(C
properties.AddRange(CommonProperties.CertAbuseProps);
}

if (methods.HasFlag(CollectionMethod.Site))
{
properties.AddRange(CommonProperties.SiteProps);
properties.AddRange(CommonProperties.SiteServerProps);
properties.AddRange(CommonProperties.SiteSubnetProps);
}

return new GeneratedLdapParameters {
Filter = filter,
Attributes = properties.Distinct().ToArray()
Expand Down
18 changes: 18 additions & 0 deletions src/CommonLib/LdapQueries/CommonProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,23 @@ public static class CommonProperties
public static readonly string[] StealthProperties = {
LDAPProperties.HomeDirectory, LDAPProperties.ScriptPath, LDAPProperties.ProfilePath
};

public static readonly string[] SiteProps =
{
LDAPProperties.DisplayName, LDAPProperties.Name, LDAPProperties.ObjectGUID, LDAPProperties.GPLink,
LDAPProperties.GroupPolicyOptions, LDAPProperties.ObjectClass
};

public static readonly string[] SiteServerProps =
{
LDAPProperties.DisplayName, LDAPProperties.Name, LDAPProperties.ObjectGUID, LDAPProperties.ObjectClass, LDAPProperties.DNSHostName,
LDAPProperties.ServerReference
};

public static readonly string[] SiteSubnetProps =
{
LDAPProperties.DisplayName, LDAPProperties.Name, LDAPProperties.CanonicalName, LDAPProperties.ObjectGUID, LDAPProperties.ObjectClass,
LDAPProperties.SiteObject
};
}
}
39 changes: 39 additions & 0 deletions src/CommonLib/LdapQueries/LdapFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,45 @@ public LdapFilter AddComputersNoMSAs(params string[] conditions) {
return this;
}

/// <summary>
/// Add a filter that will match Active Directory sites
/// </summary>
/// <param name="conditions"></param>
/// <returns></returns>
public LdapFilter AddSites(params string[] conditions)
{
_filterParts.Add(BuildString(
"(objectClass=site)",
conditions));
return this;
}

/// <summary>
/// Add a filter that will match Active Directory site servers
/// </summary>
/// <param name="conditions"></param>
/// <returns></returns>
public LdapFilter AddSiteServers(params string[] conditions)
{
_filterParts.Add(BuildString(
"(objectClass=server)",
conditions));
return this;
}

/// <summary>
/// Add a filter that will match Active Directory site subnets
/// </summary>
/// <param name="conditions"></param>
/// <returns></returns>
public LdapFilter AddSiteSubnets(params string[] conditions)
{
_filterParts.Add(BuildString(
"(objectClass=subnet)",
conditions));
return this;
}

/// <summary>
/// Adds a generic user specified filter
/// </summary>
Expand Down
54 changes: 51 additions & 3 deletions src/CommonLib/LdapUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,18 @@ internal static bool ResolveLabel(string objectIdentifier, string distinguishedN
type = Label.IssuancePolicy;
}
}
else if (objectClasses.Contains(ObjectClass.SiteClass, StringComparer.OrdinalIgnoreCase))
{
type = Label.Site;
}
else if (objectClasses.Contains(ObjectClass.SiteServerClass, StringComparer.OrdinalIgnoreCase))
{
type = Label.SiteServer;
}
else if (objectClasses.Contains(ObjectClass.SiteSubnetClass, StringComparer.OrdinalIgnoreCase))
{
type = Label.SiteSubnet;
}

return type != Label.Base;
}
Expand All @@ -1214,7 +1226,7 @@ internal static bool ResolveLabel(string objectIdentifier, string distinguishedN
if (!directoryObject.GetObjectIdentifier(out var objectIdentifier)) {
return (false, default);
}

var res = new ResolvedSearchResult {
ObjectId = objectIdentifier
};
Expand Down Expand Up @@ -1270,11 +1282,10 @@ await utils.GetDomainNameFromSid(objectIdentifier) is (true, var domainName)) {
if (await utils.GetWellKnownPrincipal(objectIdentifier, domain) is (true, var convertedPrincipal)) {
res.ObjectId = convertedPrincipal.ObjectIdentifier;
}

return (true, res);
}

res.ObjectType = await ComputeLabel(directoryObject, objectIdentifier, domain, utils);
res.ObjectType = await ComputeLabel(directoryObject, objectIdentifier, domain, utils);

directoryObject.TryGetProperty(LDAPProperties.SAMAccountName, out var samAccountName);
res.DisplayName = ComputeDisplayName(directoryObject, domain, res.ObjectType, samAccountName);
Expand Down Expand Up @@ -1395,6 +1406,43 @@ private static string ComputeDisplayName(IDirectoryObject directoryObject, strin
displayName = $"UNKNOWN@{domain}";
}

break;
}
case Label.Site: {
if (directoryObject.TryGetProperty(LDAPProperties.Name, out var name))
{
displayName = $"{name}@{domain}";
}
else
{
displayName = $"UNKNOWN@{domain}";
}
break;
}
case Label.SiteServer:
{
// Not specifying @{domain} here since Site servers may belong to other domains, so this might confuse the user
if (directoryObject.TryGetProperty(LDAPProperties.Name, out var name))
{
displayName = $"{name}";
}
else
{
displayName = $"UNKNOWN";
}
break;
}
case Label.SiteSubnet:
{
// Not specifying @{domain} here since subnets are not domain-specific
if (directoryObject.TryGetProperty(LDAPProperties.Name, out var name))
{
displayName = $"{name}";
}
else
{
displayName = $"UNKNOWN";
}
break;
}
default:
Expand Down
12 changes: 12 additions & 0 deletions src/CommonLib/OutputTypes/Site.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace SharpHoundCommonLib.OutputTypes
{
public class Site : OutputBase
{
// Subnets and Servers are common site children; keep them optional and empty by default.
//public string[] Subnets { get; set; } = Array.Empty<string>();
//public TypedPrincipal[] Servers { get; set; } = Array.Empty<TypedPrincipal>();
public GPLink[] Links { get; set; } = Array.Empty<GPLink>();
}
}
7 changes: 7 additions & 0 deletions src/CommonLib/OutputTypes/SiteServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace SharpHoundCommonLib.OutputTypes
{
public class SiteServer : OutputBase
{

}
}
7 changes: 7 additions & 0 deletions src/CommonLib/OutputTypes/SiteSubnet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace SharpHoundCommonLib.OutputTypes
{
public class SiteSubnet : OutputBase
{

}
}
12 changes: 9 additions & 3 deletions src/CommonLib/Processors/ACLProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ static ACLProcessor() {
{ Label.EnterpriseCA, "ee4aa692-3bba-11d2-90cc-00c04fd91ab1" },
{ Label.NTAuthStore, "3fdfee50-47f4-11d1-a9c3-0000f80367c1" },
{ Label.CertTemplate, "e5209ca2-3bba-11d2-90cc-00c04fd91ab1" },
{ Label.IssuancePolicy, "37cfd85c-6719-4ad8-8f9e-8678ba627563" }
{ Label.IssuancePolicy, "37cfd85c-6719-4ad8-8f9e-8678ba627563" },
{ Label.Site, "bf967ab3-0de6-11d0-a285-00aa003049e2" },
{ Label.SiteServer, "bf967a92-0de6-11d0-a285-00aa003049e2" },
{ Label.SiteSubnet, "b7b13124-b82e-11d0-afee-0000f80367c1" }
};
}

Expand Down Expand Up @@ -734,7 +737,10 @@ or Label.RootCA
or Label.EnterpriseCA
or Label.AIACA
or Label.NTAuthStore
or Label.IssuancePolicy)
or Label.IssuancePolicy
or Label.Site
or Label.SiteServer
or Label.SiteSubnet)
if (aceType is ACEGuids.AllGuid or "")
yield return new ACE {
PrincipalType = resolvedPrincipal.ObjectType,
Expand Down Expand Up @@ -776,7 +782,7 @@ or Label.NTAuthStore
IsPermissionForOwnerRightsSid = isPermissionForOwnerRightsSid,
IsInheritedPermissionForOwnerRightsSid = isInheritedPermissionForOwnerRightsSid,
};
else if (objectType is Label.OU or Label.Domain && aceType == ACEGuids.WriteGPLink)
else if (objectType is Label.OU or Label.Domain or Label.Site && aceType == ACEGuids.WriteGPLink)
yield return new ACE {
PrincipalType = resolvedPrincipal.ObjectType,
PrincipalSID = resolvedPrincipal.ObjectIdentifier,
Expand Down
23 changes: 23 additions & 0 deletions src/CommonLib/Processors/LdapPropertyProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,29 @@ public async Task<IssuancePolicyProperties> ReadIssuancePolicyProperties(IDirect
return ret;
}

public static Dictionary<string, object> ReadSiteProperties(IDirectoryObject entry)
{
var props = GetCommonProps(entry);
return props;
}


public static Dictionary<string, object> ReadSiteServerProperties(IDirectoryObject entry)
{
var props = GetCommonProps(entry);
props.Add("dnshostname", entry.GetProperty(LDAPProperties.DNSHostName));
props.Add("serverreference", entry.GetProperty(LDAPProperties.ServerReference));
return props;
}

public static Dictionary<string, object> ReadSiteSubnetProperties(IDirectoryObject entry)
{
var props = GetCommonProps(entry);
props.Add("cn", entry.GetProperty(LDAPProperties.CanonicalName));
props.Add("siteObject", entry.GetProperty(LDAPProperties.SiteObject));
return props;
}

/// <summary>
/// Attempts to parse all LDAP attributes outside of the ones already collected and converts them to a human readable
/// format using a best guess
Expand Down
Loading