diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index edb1dbd3..be378cd4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,10 +39,16 @@ jobs: - name: Pack run: dotnet pack --no-restore -c Release -p:PackageVersion=${{ steps.version.outputs.result }} -o . + + - name: Prep Packages + run: dotnet nuget add source --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/BloodHoundAD/index.json" - - name: Publish NuGet - run: dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_TOKEN }} + - name: Publish to GitHub Packages + run: dotnet nuget push *.nupkg --api-key ${{ secrets.GITHUB_TOKEN }} --source "github" + - name: Publish NuGet + run: dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_TOKEN }} --skip-duplicate + ghpages: name: ghpages needs: nuget diff --git a/src/CommonLib/LDAPProperties.cs b/src/CommonLib/LDAPProperties.cs index e73d5b6c..d2f12e28 100644 --- a/src/CommonLib/LDAPProperties.cs +++ b/src/CommonLib/LDAPProperties.cs @@ -34,7 +34,8 @@ public static class LDAPProperties public const string OperatingSystem = "operatingsystem"; public const string ServicePack = "operatingsystemservicepack"; public const string DNSHostName = "dnshostname"; - public const string LAPSExpirationTime = "ms-mcs-admpwdexpirationtime"; + public const string LAPSExpirationTime = "mslaps-passwordexpirationtime"; + public const string LegacyLAPSExpirationTime = "ms-mcs-admpwdexpirationtime"; public const string Members = "member"; public const string SecurityDescriptor = "ntsecuritydescriptor"; public const string SecurityIdentifier = "securityidentifier"; @@ -63,4 +64,4 @@ public static class LDAPProperties public const string CertificateTemplates = "certificatetemplates"; public const string CrossCertificatePair = "crosscertificatepair"; } -} \ No newline at end of file +} diff --git a/src/CommonLib/Processors/LDAPPropertyProcessor.cs b/src/CommonLib/Processors/LDAPPropertyProcessor.cs index 34f5c7c9..5b3a181a 100644 --- a/src/CommonLib/Processors/LDAPPropertyProcessor.cs +++ b/src/CommonLib/Processors/LDAPPropertyProcessor.cs @@ -8,12 +8,20 @@ using System.Security.Principal; using System.Threading.Tasks; using SharpHoundCommonLib.Enums; +using SharpHoundCommonLib.LDAPQueries; using SharpHoundCommonLib.OutputTypes; namespace SharpHoundCommonLib.Processors { public class LDAPPropertyProcessor { + private static readonly string[] ReservedAttributes = CommonProperties.TypeResolutionProps + .Concat(CommonProperties.BaseQueryProps).Concat(CommonProperties.GroupResolutionProps) + .Concat(CommonProperties.ComputerMethodProps).Concat(CommonProperties.ACLProps) + .Concat(CommonProperties.ObjectPropsProps).Concat(CommonProperties.ContainerProps) + .Concat(CommonProperties.SPNTargetProps).Concat(CommonProperties.DomainTrustProps) + .Concat(CommonProperties.GPOLocalGroupProps).ToArray(); + private readonly ILDAPUtils _utils; public LDAPPropertyProcessor(ILDAPUtils utils) @@ -144,7 +152,7 @@ public async Task ReadUserProperties(ISearchResultEntry entry) bool enabled, trustedToAuth, sensitive, dontReqPreAuth, passwdNotReq, unconstrained, pwdNeverExpires; if (int.TryParse(uac, out var flag)) { - var flags = (UacFlags) flag; + var flags = (UacFlags)flag; enabled = (flags & UacFlags.AccountDisable) == 0; trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0; sensitive = (flags & UacFlags.NotDelegated) != 0; @@ -272,7 +280,7 @@ public async Task ReadComputerProperties(ISearchResultEntry bool enabled, unconstrained, trustedToAuth; if (int.TryParse(uac, out var flag)) { - var flags = (UacFlags) flag; + var flags = (UacFlags)flag; enabled = (flags & UacFlags.AccountDisable) == 0; unconstrained = (flags & UacFlags.TrustedForDelegation) == UacFlags.TrustedForDelegation; trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0; @@ -367,7 +375,8 @@ public async Task ReadComputerProperties(ISearchResultEntry var hsa = entry.GetArrayProperty(LDAPProperties.HostServiceAccount); var smsaPrincipals = new List(); - if (hsa != null) { + if (hsa != null) + { foreach (var dn in hsa) { var resolvedPrincipal = _utils.ResolveDistinguishedName(dn); @@ -400,7 +409,7 @@ public static Dictionary ReadAIACAProperties(ISearchResultEntry public static Dictionary ReadEnrollmentServiceProperties(ISearchResultEntry entry) { var props = GetCommonProps(entry); - if (entry.GetIntProperty("flags", out var flags)) props.Add("flags", (PKIEnrollmentServiceFlags) flags); + if (entry.GetIntProperty("flags", out var flags)) props.Add("flags", (PKIEnrollmentServiceFlags)flags); return props; } @@ -421,14 +430,14 @@ public static Dictionary ReadCertTemplateProperties(ISearchResul props.Add("oid", entry.GetProperty(LDAPProperties.CertTemplateOID)); if (entry.GetIntProperty(LDAPProperties.PKIEnrollmentFlag, out var enrollmentFlagsRaw)) { - var enrollmentFlags = (PKIEnrollmentFlag) enrollmentFlagsRaw; + var enrollmentFlags = (PKIEnrollmentFlag)enrollmentFlagsRaw; props.Add("enrollmentflag", enrollmentFlags); props.Add("requiresmanagerapproval", enrollmentFlags.HasFlag(PKIEnrollmentFlag.PEND_ALL_REQUESTS)); } if (entry.GetIntProperty(LDAPProperties.PKINameFlag, out var nameFlagsRaw)) { - var nameFlags = (PKICertificateNameFlag) nameFlagsRaw; + var nameFlags = (PKICertificateNameFlag)nameFlagsRaw; props.Add("certificatenameflag", nameFlags); props.Add("enrolleesuppliessubject", nameFlags.HasFlag(PKICertificateNameFlag.ENROLLEE_SUPPLIES_SUBJECT)); @@ -456,7 +465,6 @@ public static Dictionary ReadCertTemplateProperties(ISearchResul /// public Dictionary ParseAllProperties(ISearchResultEntry entry) { - var flag = IsTextUnicodeFlags.IS_TEXT_UNICODE_STATISTICS; var props = new Dictionary(); var type = typeof(LDAPProperties); @@ -464,7 +472,7 @@ public Dictionary ParseAllProperties(ISearchResultEntry entry) foreach (var property in entry.PropertyNames()) { - if (reserved.Contains(property, StringComparer.InvariantCultureIgnoreCase)) + if (ReservedAttributes.Contains(property, StringComparer.OrdinalIgnoreCase)) continue; var collCount = entry.PropCount(property); @@ -475,8 +483,7 @@ public Dictionary ParseAllProperties(ISearchResultEntry entry) { var testBytes = entry.GetByteProperty(property); - if (testBytes == null || testBytes.Length == 0 || - !IsTextUnicode(testBytes, testBytes.Length, ref flag)) continue; + if (testBytes == null || testBytes.Length == 0) continue; var testString = entry.GetProperty(property); @@ -489,7 +496,7 @@ public Dictionary ParseAllProperties(ISearchResultEntry entry) else { var arrBytes = entry.GetByteArrayProperty(property); - if (arrBytes.Length == 0 || !IsTextUnicode(arrBytes[0], arrBytes[0].Length, ref flag)) + if (arrBytes.Length == 0) continue; var arr = entry.GetArrayProperty(property); @@ -516,6 +523,10 @@ private static object BestGuessConvert(string property) //This string corresponds to the max int, and is usually set in accountexpires if (property == "9223372036854775807") return -1; + //Try parsing as an int + if (int.TryParse(property, out var num)) return num; + + //Just return the property as a string return property; } diff --git a/src/CommonLib/SearchResultEntryWrapper.cs b/src/CommonLib/SearchResultEntryWrapper.cs index 938b12b3..f5788209 100644 --- a/src/CommonLib/SearchResultEntryWrapper.cs +++ b/src/CommonLib/SearchResultEntryWrapper.cs @@ -262,7 +262,7 @@ public bool IsGMSA() public bool HasLAPS() { - return GetProperty(LDAPProperties.LAPSExpirationTime) != null; + return GetProperty(LDAPProperties.LAPSExpirationTime) != null || GetProperty(LDAPProperties.LegacyLAPSExpirationTime) != null; } public SearchResultEntry GetEntry() @@ -270,4 +270,4 @@ public SearchResultEntry GetEntry() return _entry; } } -} \ No newline at end of file +} diff --git a/src/CommonLib/SharpHoundCommonLib.csproj b/src/CommonLib/SharpHoundCommonLib.csproj index d0938a38..92ff866e 100644 --- a/src/CommonLib/SharpHoundCommonLib.csproj +++ b/src/CommonLib/SharpHoundCommonLib.csproj @@ -9,7 +9,7 @@ Common library for C# BloodHound enumeration tasks GPL-3.0-only https://github.com/BloodHoundAD/SharpHoundCommon - 3.0.6 + 3.0.7 SharpHoundCommonLib SharpHoundCommonLib