Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add certservices collection method #76

Merged
merged 2 commits into from
Nov 22, 2023
Merged
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ dotnet build

SharpHound is designed targeting .Net 4.6.2. SharpHound must be run from the context of a domain user, either directly through a logon or through another method such as RUNAS.


# SharpHound

```csharp
Expand All @@ -28,9 +27,10 @@ dotnet build
```

# CLI

```
-c, --collectionmethods (Default: Default) Collection Methods: Container, Group, LocalGroup, GPOLocalGroup,
Session, LoggedOn, ObjectProps, ACL, ComputerOnly, Trusts, Default, RDP, DCOM, DCOnly, CARegistry, DCRegistry
Session, LoggedOn, ObjectProps, ACL, ComputerOnly, Trusts, Default, RDP, DCOM, DCOnly, CARegistry, DCRegistry, CertServices

-d, --domain Specify domain to enumerate

Expand Down Expand Up @@ -75,15 +75,15 @@ dotnet build
--ldapport (Default: 0) Override port for LDAP

--secureldap (Default: false) Connect to LDAP SSL instead of regular LDAP

--disablecertverification (Default: false) Disable certificate verification for secure LDAP

--disablesigning (Default: false) Disables Kerberos Signing/Sealing

--skipportcheck (Default: false) Skip checking if 445 is open

--portchecktimeout (Default: 500) Timeout for port checks in milliseconds

--skippasswordcheck (Default: false) Skip PwdLastSet age check when checking computers

--excludedcs (Default: false) Exclude domain controllers from session/localgroup enumeration (mostly for
Expand Down
1 change: 1 addition & 0 deletions src/Client/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public enum CollectionMethodOptions
ComputerOnly,
CARegistry,
DCRegistry,
CertServices,
All
}
}
19 changes: 10 additions & 9 deletions src/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class Options
// Options that affect what is collected
[Option('c', "collectionmethods", Default = new[] { "Default" },
HelpText =
"Collection Methods: Group, LocalGroup, LocalAdmin, RDP, DCOM, PSRemote, Session, Trusts, ACL, Container, ComputerOnly, GPOLocalGroup, LoggedOn, ObjectProps, SPNTargets, UserRights, Default, DCOnly, CARegistry, DCRegistry, All")]
"Collection Methods: Group, LocalGroup, LocalAdmin, RDP, DCOM, PSRemote, Session, Trusts, ACL, Container, ComputerOnly, GPOLocalGroup, LoggedOn, ObjectProps, SPNTargets, UserRights, Default, DCOnly, CARegistry, DCRegistry, CertServices, All")]
public IEnumerable<string> CollectionMethods { get; set; }

[Option('d', "domain", Default = null, HelpText = "Specify domain to enumerate")]
Expand Down Expand Up @@ -61,7 +61,7 @@ public class Options

[Option(HelpText = "Don't zip files", Default = false)]
public bool NoZip { get; set; }

[Option(HelpText = "Password protects the zip with the specified password", Default = null)]
public string ZipPassword { get; set; }

Expand All @@ -87,7 +87,7 @@ public class Options

[Option(HelpText = "Connect to LDAP SSL instead of regular LDAP", Default = false)]
public bool SecureLDAP { get; set; }

[Option(HelpText = "Disables certificate verification when using LDAPS", Default = false)]
public bool DisableCertVerification { get; set; }

Expand All @@ -97,10 +97,10 @@ public class Options
//Options that affect how enumeration is performed
[Option(HelpText = "Skip checking if 445 is open", Default = false)]
public bool SkipPortCheck { get; set; }

[Option(HelpText = "Timeout for port checks in milliseconds", Default = 500)]
public int PortCheckTimeout { get; set; }

[Option(HelpText = "Skip check for PwdLastSet when enumerating computers", Default = false)]
public bool SkipPasswordCheck { get; set; }

Expand All @@ -114,7 +114,7 @@ public class Options
[Option(HelpText = "Add jitter to throttle (percent)")]
public int Jitter { get; set; }

[Option('t',"threads", HelpText = "Number of threads to run enumeration with", Default = 50)]
[Option('t', "threads", HelpText = "Number of threads to run enumeration with", Default = 50)]
public int Threads { get; set; }

[Option(HelpText = "Skip registry session enumeration")]
Expand All @@ -133,10 +133,10 @@ public class Options
[Option('l', "Loop", HelpText = "Loop computer collection")]
public bool Loop { get; set; }

[Option(HelpText="Loop duration (hh:mm:ss - 05:00:00 is 5 hours, default: 2 hrs)")]
[Option(HelpText = "Loop duration (hh:mm:ss - 05:00:00 is 5 hours, default: 2 hrs)")]
public TimeSpan LoopDuration { get; set; }

[Option(HelpText="Add delay between loops (hh:mm:ss - 00:03:00 is 3 minutes)")] public TimeSpan LoopInterval { get; set; }
[Option(HelpText = "Add delay between loops (hh:mm:ss - 00:03:00 is 3 minutes)")] public TimeSpan LoopInterval { get; set; }

//Misc Options
[Option(HelpText = "Interval in which to display status in milliseconds", Default = 30000)]
Expand Down Expand Up @@ -189,6 +189,7 @@ internal bool ResolveCollectionMethods(ILogger logger, out ResolvedCollectionMet
CollectionMethodOptions.ComputerOnly => ResolvedCollectionMethod.ComputerOnly,
CollectionMethodOptions.CARegistry => ResolvedCollectionMethod.CARegistry,
CollectionMethodOptions.DCRegistry => ResolvedCollectionMethod.DCRegistry,
CollectionMethodOptions.CertServices => ResolvedCollectionMethod.CertServices,
CollectionMethodOptions.All => ResolvedCollectionMethod.All,
CollectionMethodOptions.None => ResolvedCollectionMethod.None,
_ => throw new ArgumentOutOfRangeException()
Expand Down Expand Up @@ -234,7 +235,7 @@ internal bool ResolveCollectionMethods(ILogger logger, out ResolvedCollectionMet
resolved ^= ResolvedCollectionMethod.LocalAdmin;
updates.Add("[-] Removed LocalAdmin Collection");
}

if ((resolved & ResolvedCollectionMethod.CARegistry) != 0)
{
resolved ^= ResolvedCollectionMethod.CARegistry;
Expand Down
1 change: 1 addition & 0 deletions src/PowerShell/Template.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
DcOnly - Collects Group Membership, ACLs, ObjectProps, Trusts, Containers, and GPO Admins
CARegistry - Collect ADCS properties from registry of Certificate Authority servers
DCRegistry - Collect properties from registry of Domain Controller servers
CertServices - Collect ADCS properties from Certificate Services
All - Collect all data

This can be a list of comma separated valued as well to run multiple collection methods!
Expand Down
56 changes: 34 additions & 22 deletions src/Producers/BaseProducer.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
using System.Collections.Generic;

using System.Threading.Channels;

using System.Threading.Tasks;

using Sharphound.Client;

using SharpHoundCommonLib;

using SharpHoundCommonLib.Enums;

using SharpHoundCommonLib.LDAPQueries;

using SharpHoundCommonLib.OutputTypes;

namespace Sharphound.Producers
Expand All @@ -28,7 +35,7 @@ protected BaseProducer(IContext context, Channel<ISearchResultEntry> channel, Ch
public abstract Task Produce();
public abstract Task ProduceConfigNC();

protected LDAPData CreateLDAPData()
protected LDAPData CreateDefaultNCData()
{
var query = new LDAPFilter();
var props = new List<string>();
Expand Down Expand Up @@ -60,9 +67,9 @@ protected LDAPData CreateLDAPData()
(methods & ResolvedCollectionMethod.RDP) != 0 ||
(methods & ResolvedCollectionMethod.LoggedOn) != 0 ||
(methods & ResolvedCollectionMethod.Session) != 0 ||
(methods & ResolvedCollectionMethod.ObjectProps) != 0 ||
(methods & ResolvedCollectionMethod.ObjectProps) != 0 ||
(methods & ResolvedCollectionMethod.UserRights) != 0)

props.AddRange(CommonProperties.ComputerMethodProps);

if ((methods & ResolvedCollectionMethod.Trusts) != 0) props.AddRange(CommonProperties.DomainTrustProps);
Expand Down Expand Up @@ -96,7 +103,7 @@ protected LDAPData CreateLDAPData()
(methods & ResolvedCollectionMethod.RDP) != 0 ||
(methods & ResolvedCollectionMethod.LoggedOn) != 0 ||
(methods & ResolvedCollectionMethod.Session) != 0 ||
(methods & ResolvedCollectionMethod.ObjectProps) != 0 ||
(methods & ResolvedCollectionMethod.ObjectProps) != 0 ||
(methods & ResolvedCollectionMethod.UserRights) != 0)
{
query = query.AddComputers();
Expand Down Expand Up @@ -144,34 +151,39 @@ protected LDAPData CreateConfigNCData()
props.AddRange(CommonProperties.TypeResolutionProps);

var methods = Context.ResolvedCollectionMethods;
var allObjectTypesQuery = query.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities();

if ((methods & ResolvedCollectionMethod.ObjectProps) != 0 || (methods & ResolvedCollectionMethod.ACL) != 0)
if ((methods & ResolvedCollectionMethod.ObjectProps) != 0)
{
query = query.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities();
query = allObjectTypesQuery;
props.AddRange(CommonProperties.ObjectPropsProps);
props.AddRange(CommonProperties.CertAbuseProps);
}

if ((methods & ResolvedCollectionMethod.Container) != 0)
props.AddRange(CommonProperties.ContainerProps);
if ((methods & ResolvedCollectionMethod.ACL) != 0)
{
query = allObjectTypesQuery;
props.AddRange(CommonProperties.ACLProps);
}

if ((methods & ResolvedCollectionMethod.ACL) != 0)
props.AddRange(CommonProperties.ACLProps);
if ((methods & ResolvedCollectionMethod.CertServices) != 0)
{
query = allObjectTypesQuery;
props.AddRange(CommonProperties.CertAbuseProps);
}
else

if ((methods & ResolvedCollectionMethod.Container) != 0)
{
if ((methods & ResolvedCollectionMethod.Container) != 0)
{
query = query.AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities();
props.AddRange(CommonProperties.ContainerProps);
}
query = allObjectTypesQuery;
props.AddRange(CommonProperties.ContainerProps);
}

if ((methods & ResolvedCollectionMethod.CARegistry) != 0)
{
query = query.AddEnterpriseCertificationAuthorities();
props.AddRange(CommonProperties.CertAbuseProps);
}
if ((methods & ResolvedCollectionMethod.CARegistry) != 0)
{
query = query.AddEnterpriseCertificationAuthorities();
props.AddRange(CommonProperties.CertAbuseProps);
}


if (Context.LdapFilter != null) query.AddFilter(Context.LdapFilter, true);

data.Filter = query;
Expand Down
2 changes: 1 addition & 1 deletion src/Producers/ComputerFileProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public override async Task Produce()
var computerFile = Context.ComputerFile;
var cancellationToken = Context.CancellationTokenSource.Token;

var ldapData = CreateLDAPData();
var ldapData = CreateDefaultNCData();

try
{
Expand Down
8 changes: 4 additions & 4 deletions src/Producers/LdapProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public override async Task Produce()
{
var cancellationToken = Context.CancellationTokenSource.Token;

var ldapData = CreateLDAPData();
var ldapData = CreateDefaultNCData();

var log = Context.Logger;
var utils = Context.LDAPUtils;
Expand Down Expand Up @@ -67,7 +67,7 @@ await OutputChannel.Writer.WriteAsync(new Domain
{ "collected", true },
}
});

foreach (var searchResult in Context.LDAPUtils.QueryLDAP(ldapData.Filter.GetFilter(), SearchScope.Subtree,
ldapData.Props.Distinct().ToArray(), cancellationToken, domain.Name,
adsPath: Context.SearchBase,
Expand All @@ -83,7 +83,7 @@ await OutputChannel.Writer.WriteAsync(new Domain
Context.Logger.LogTrace("Producer wrote {DistinguishedName} to channel", searchResult.DistinguishedName);
}
}

}

/// <summary>
Expand Down Expand Up @@ -121,7 +121,7 @@ public override async Task ProduceConfigNC()
Context.Logger.LogTrace("Skipping already collected config NC '{path}' for domain {Domain}", configAdsPath, domain.Name);
}
}

}

}
Expand Down
4 changes: 2 additions & 2 deletions src/Producers/StealthProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal class StealthProducer : BaseProducer

public StealthProducer(IContext context, Channel<ISearchResultEntry> channel, Channel<OutputBase> outputChannel) : base(context, channel, outputChannel)
{
var ldapData = CreateLDAPData();
var ldapData = CreateDefaultNCData();
_query = ldapData.Filter;
_props = ldapData.Props;

Expand Down Expand Up @@ -124,7 +124,7 @@ private async Task<Dictionary<string, ISearchResultEntry>> FindPathTargetSids()
}
});
}



// Loop over the paths we grabbed, and resolve them to sids.
Expand Down
Loading