Skip to content
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
3 changes: 2 additions & 1 deletion src/CommonLib/CSVComputerStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ public class CSVComputerStatus
public string ComputerName { get; set; }
public string Task { get; set; }
public string Status { get; set; }
public string ObjectId { get; set; }

/// <summary>
/// Converts to CSV format for output
/// </summary>
/// <returns></returns>
public string ToCsv()
{
return $"{StringToCsvCell(ComputerName)}, {StringToCsvCell(Task)}, {StringToCsvCell(Status)}";
return $"{StringToCsvCell(ComputerName)}, {StringToCsvCell(Task)}, {StringToCsvCell(Status)}, {StringToCsvCell(ObjectId)}";
}

/// <summary>
Expand Down
6 changes: 4 additions & 2 deletions src/CommonLib/Processors/CertAbuseProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = "SamConnect",
ComputerName = computerName,
Status = openServerResult.SError
Status = openServerResult.SError,
ObjectId = computerObjectId,
});
return null;
}
Expand All @@ -376,7 +377,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Status = getMachineSidResult.SError,
ComputerName = computerName,
Task = "GetMachineSid"
Task = "GetMachineSid",
ObjectId = computerObjectId,
});
//If we can't get a machine sid, we wont be able to make local principals with unique object ids, or differentiate local/domain objects
_log.LogWarning("Unable to get machineSid for {Computer}: {Status}", computerName, getMachineSidResult.SError);
Expand Down
17 changes: 11 additions & 6 deletions src/CommonLib/Processors/ComputerAvailability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public Task<ComputerStatus> IsComputerAvailable(ResolvedSearchResult result, IDi
var pwdlastset = entry.GetProperty(LDAPProperties.PasswordLastSet);
var lastLogon = entry.GetProperty(LDAPProperties.LastLogonTimestamp);

return IsComputerAvailable(name, os, pwdlastset, lastLogon);
return IsComputerAvailable(name, os, pwdlastset, lastLogon, result.ObjectId);
}

/// <summary>
Expand All @@ -60,16 +60,18 @@ public Task<ComputerStatus> IsComputerAvailable(ResolvedSearchResult result, IDi
/// <param name="operatingSystem">The LDAP operatingsystem attribute value</param>
/// <param name="pwdLastSet">The LDAP pwdlastset attribute value</param>
/// <param name="lastLogon">The LDAP lastlogontimestamp attribute value</param>
/// <param name="objectId">The objectId that pertains to the computer.</param>
/// <returns>A <cref>ComputerStatus</cref> object that represents the availability of the computer</returns>
public async Task<ComputerStatus> IsComputerAvailable(string computerName, string operatingSystem,
string pwdLastSet, string lastLogon) {
string pwdLastSet, string lastLogon, string objectId = null) {
if (operatingSystem != null && !operatingSystem.StartsWith("Windows", StringComparison.OrdinalIgnoreCase)) {
_log.LogTrace("{ComputerName} is not available because operating system {OperatingSystem} is not valid",
computerName, operatingSystem);
await SendComputerStatus(new CSVComputerStatus {
Status = ComputerStatus.NonWindowsOS,
Task = "ComputerAvailability",
ComputerName = computerName
ComputerName = computerName,
ObjectId = objectId,
});
return new ComputerStatus {
Connectable = false,
Expand All @@ -84,7 +86,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = ComputerStatus.NotActive,
Task = "ComputerAvailability",
ComputerName = computerName
ComputerName = computerName,
ObjectId = objectId,
});
return new ComputerStatus {
Connectable = false,
Expand All @@ -103,7 +106,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = ComputerStatus.PortNotOpen,
Task = "ComputerAvailability",
ComputerName = computerName
ComputerName = computerName,
ObjectId = objectId,
});
return new ComputerStatus {
Connectable = false,
Expand All @@ -116,7 +120,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "ComputerAvailability",
ComputerName = computerName
ComputerName = computerName,
ObjectId = objectId,
});

return new ComputerStatus {
Expand Down
20 changes: 14 additions & 6 deletions src/CommonLib/Processors/ComputerSessionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public async Task<SessionAPIResult> ReadUserSessions(string computerName, string
await SendComputerStatus(new CSVComputerStatus {
Status = result.GetErrorStatus(),
Task = "NetSessionEnum",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerSid,
});
_log.LogTrace("NetSessionEnum failed on {ComputerName}: {Status}", computerName, result.Status);
ret.Collected = false;
Expand All @@ -99,7 +100,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "NetSessionEnum",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerSid,
});

ret.Collected = true;
Expand Down Expand Up @@ -144,6 +146,7 @@ await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "NetSessionEnum",
ComputerName = computerSessionName,
ObjectId = resolvedComputerSID,
});
}

Expand All @@ -166,6 +169,7 @@ await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "NetSessionEnum",
ComputerName = computerSessionName,
ObjectId = resolvedComputerSID,
});
results.Add(new Session {
ComputerSID = resolvedComputerSID,
Expand Down Expand Up @@ -225,7 +229,8 @@ public async Task<SessionAPIResult> ReadUserSessionsPrivileged(string computerNa
await SendComputerStatus(new CSVComputerStatus {
Status = result.GetErrorStatus(),
Task = "NetWkstaUserEnum",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerSid,
});
_log.LogTrace("NetWkstaUserEnum failed on {ComputerName}: {Status}", computerName, result.Status);
ret.Collected = false;
Expand All @@ -237,7 +242,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = result.Status.ToString(),
Task = "NetWkstaUserEnum",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerSid,
});

ret.Collected = true;
Expand Down Expand Up @@ -292,7 +298,8 @@ public async Task<SessionAPIResult> ReadUserSessionsRegistry(string computerName
await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "RegistrySessionEnum",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerSid,
});
_log.LogTrace("Registry session enum succeeded on {ComputerName}", computerName);
var results = new List<Session>();
Expand All @@ -319,7 +326,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = e.Message,
Task = "RegistrySessionEnum",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerSid,
});
ret.Collected = false;
ret.FailureReason = e.Message;
Expand Down
14 changes: 9 additions & 5 deletions src/CommonLib/Processors/DCLdapProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

public class LdapAuthOptions {
public bool Signing { get; set; }
public ChannelBindings? Bindings { get; set; }

Check warning on line 16 in src/CommonLib/Processors/DCLdapProcessor.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
}

/// <summary>
Expand Down Expand Up @@ -45,7 +45,7 @@

public event ComputerStatusDelegate ComputerStatusEvent;

public async Task<LdapService> Scan(string computerName) {
public async Task<LdapService> Scan(string computerName, string computerObjectId) {
var hasLdap = await TestLdapPort();
var hasLdaps = await TestLdapsPort();
SharpHoundRPC.Result<bool> isSigningRequired = new(),
Expand All @@ -63,29 +63,33 @@
await SendComputerStatus(new CSVComputerStatus {
Status = isSigningRequired.Error,
Task = "DCLdapIsSigningRequired",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerObjectId
});
_log.LogTrace("DCLdapScan failed on IsSigningRequired for {ComputerName}: {Status}", computerName, isSigningRequired.Status);
} else {
await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "DCLdapIsSigningRequired",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerObjectId
});
}

if (isChannelBindingDisabled.IsFailed) {
await SendComputerStatus(new CSVComputerStatus {
Status = isChannelBindingDisabled.Error,
Task = "DCLdapIsChannelBindingDisabled",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerObjectId,
});
_log.LogTrace("DCLdapScan failed on IsChannelBindingDisabled for {ComputerName}: {Status}", computerName, isSigningRequired.Status);
} else {
await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "DCLdapIsChannelBindingDisabled",
ComputerName = computerName
ComputerName = computerName,
ObjectId = computerObjectId,
});
}

Expand Down
2 changes: 2 additions & 0 deletions src/CommonLib/Processors/LdapPropertyProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = nameof(ReadUserProperties),
ComputerName = Helpers.StripServicePrincipalName(d).ToUpper().TrimEnd('$'),
ObjectId = resolvedHost.SecurityIdentifier,
});
comps.Add(new TypedPrincipal {
ObjectIdentifier = resolvedHost.SecurityIdentifier,
Expand Down Expand Up @@ -384,6 +385,7 @@ await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = nameof(ReadComputerProperties),
ComputerName = d,
ObjectId = resolvedHost.SecurityIdentifier,
});
comps.Add(new TypedPrincipal {
ObjectIdentifier = resolvedHost.SecurityIdentifier,
Expand Down
24 changes: 16 additions & 8 deletions src/CommonLib/Processors/LocalGroupProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = "SamConnect",
ComputerName = computerName,
Status = openServerResult.SError
Status = openServerResult.SError,
ObjectId = computerObjectId,
});
yield break;
}
Expand All @@ -96,7 +97,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Status = getMachineSidResult.SError,
ComputerName = computerName,
Task = "GetMachineSid"
Task = "GetMachineSid",
ObjectId = computerObjectId,
});
//If we can't get a machine sid, we wont be able to make local principals with unique object ids, or differentiate local/domain objects
_log.LogWarning("Unable to get machineSid for {Computer}: {Status}. Abandoning local group processing", computerName, getMachineSidResult.SError);
Expand All @@ -120,7 +122,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = "GetDomains",
ComputerName = computerName,
Status = getDomainsResult.SError
Status = getDomainsResult.SError,
ObjectId = computerObjectId,
});
yield break;
}
Expand All @@ -141,7 +144,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = $"OpenDomain - {domainResult.Name}",
ComputerName = computerName,
Status = openDomainResult.SError
Status = openDomainResult.SError,
ObjectId = computerObjectId,
});
if (openDomainResult.IsTimeout) {
yield break;
Expand All @@ -161,7 +165,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = $"GetAliases - {domainResult.Name}",
ComputerName = computerName,
Status = getAliasesResult.SError
Status = getAliasesResult.SError,
ObjectId = computerObjectId,
});

if (getAliasesResult.IsTimeout) {
Expand Down Expand Up @@ -193,7 +198,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = $"OpenAlias - {alias.Name}",
ComputerName = computerName,
Status = openAliasResult.SError
Status = openAliasResult.SError,
ObjectId = computerObjectId,
});
ret.Collected = false;
ret.FailureReason = $"SamOpenAliasInDomain failed with status {openAliasResult.SError}";
Expand All @@ -214,7 +220,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = $"GetMembersInAlias - {alias.Name}",
ComputerName = computerName,
Status = getMembersResult.SError
Status = getMembersResult.SError,
ObjectId = computerObjectId,
});
ret.Collected = false;
ret.FailureReason = $"SamGetMembersInAlias failed with status {getMembersResult.SError}";
Expand All @@ -229,7 +236,8 @@ await SendComputerStatus(new CSVComputerStatus
{
Task = $"GetMembersInAlias - {alias.Name}",
ComputerName = computerName,
Status = CSVComputerStatus.StatusSuccess
Status = CSVComputerStatus.StatusSuccess,
ObjectId = computerObjectId,
});

var results = new List<TypedPrincipal>();
Expand Down
1 change: 1 addition & 0 deletions src/CommonLib/Processors/SPNProcessors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = nameof(ReadSPNTargets),
ComputerName = Helpers.StripServicePrincipalName(spn).ToUpper().TrimEnd('$'),
ObjectId = host
});
yield return new SPNPrivilege {
ComputerSID = host,
Expand Down
11 changes: 7 additions & 4 deletions src/CommonLib/Processors/SmbProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ public SmbProcessor(int timeoutMs, ISmbScanner smbScanner = null, ILogger log =
}

public event ComputerStatusDelegate ComputerStatusEvent;
public virtual async Task<APIResult<SmbInfo>> Scan(string host) {
public virtual async Task<APIResult<SmbInfo>> Scan(string host, string securityIdentifier) {
var result = await _scanHostAdaptiveTimeout.ExecuteRPCWithTimeout((timeoutToken) => _smbScanner.ScanHost(host, 445, timeoutToken));

if (result.IsFailed) {
await SendComputerStatus(new CSVComputerStatus {
Status = result.Error,
Task = "SmbScan",
ComputerName = host
ComputerName = host,
ObjectId = securityIdentifier,
});
_log.LogTrace("SmbScan failed on {ComputerName}: {Status}", host, result.Error);
return APIResult<SmbInfo>.Failure(result.Error);
Expand All @@ -43,7 +44,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = result.Error ?? "Unknown error",
Task = "SmbScan",
ComputerName = host
ComputerName = host,
ObjectId = securityIdentifier,
});
_log.LogTrace("SmbScan failed on {ComputerName} - null result: {Status}", host, result.Status);
return APIResult<SmbInfo>.Failure(result.Error ?? "Unknown error");
Expand All @@ -53,7 +55,8 @@ await SendComputerStatus(new CSVComputerStatus {
await SendComputerStatus(new CSVComputerStatus {
Status = CSVComputerStatus.StatusSuccess,
Task = "SmbScan",
ComputerName = host
ComputerName = host,
ObjectId = securityIdentifier,
});

var info = new SmbInfo() {
Expand Down
Loading
Loading