Skip to content

Commit df54c41

Browse files
vletouxVincent LE TOUX
and
Vincent LE TOUX
authored
PingCastle 3.3.0.0 (#256)
Co-authored-by: Vincent LE TOUX <vincent.letoux@pingcastle.com>
1 parent 5025359 commit df54c41

File tree

81 files changed

+3424
-665
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+3424
-665
lines changed

ADWS/ADItem.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,15 @@ public class DnsProperty
6464
[AttributeUsage(AttributeTargets.Property)]
6565
private class ADAttributeAttribute : Attribute
6666
{
67-
public ADAttributeAttribute(string aDAttribute, ADAttributeValueKind valueKind)
67+
public ADAttributeAttribute(string aDAttribute, ADAttributeValueKind valueKind, object defaultValue = null)
6868
{
6969
ADAttribute = aDAttribute;
7070
ValueKind = valueKind;
71+
DefaultValue = defaultValue;
7172
}
7273
public string ADAttribute { get; set; }
7374
public ADAttributeValueKind ValueKind { get; set; }
75+
public object DefaultValue { get; set; }
7476
}
7577

7678
private enum ADAttributeValueKind
@@ -118,7 +120,24 @@ static ADItem()
118120
var attributes = prop.GetCustomAttributes(typeof(ADAttributeAttribute), false);
119121
if (attributes != null && attributes.Length != 0)
120122
{
121-
AttributeTranslation.Add(((ADAttributeAttribute)attributes[0]).ADAttribute.ToLowerInvariant(), new ADAttributeTranslation((ADAttributeAttribute)attributes[0], prop));
123+
var attribute = (ADAttributeAttribute)attributes[0];
124+
AttributeTranslation.Add(attribute.ADAttribute.ToLowerInvariant(), new ADAttributeTranslation(attribute, prop));
125+
}
126+
}
127+
}
128+
129+
protected ADItem()
130+
{
131+
foreach (var prop in typeof(ADItem).GetProperties())
132+
{
133+
var attributes = prop.GetCustomAttributes(typeof(ADAttributeAttribute), false);
134+
if (attributes != null && attributes.Length != 0)
135+
{
136+
var attribute = (ADAttributeAttribute)attributes[0];
137+
if (attribute.DefaultValue != null)
138+
{
139+
prop.SetValue(this, attribute.DefaultValue);
140+
}
122141
}
123142
}
124143
}
@@ -149,7 +168,7 @@ static ADItem()
149168
public string DnsRoot { get; set; }
150169
[ADAttributeAttribute("dSHeuristics", ADAttributeValueKind.StringValue)]
151170
public string DSHeuristics { get; set; }
152-
[ADAttributeAttribute("ms-DS-MachineAccountQuota", ADAttributeValueKind.IntValue)]
171+
[ADAttributeAttribute("ms-DS-MachineAccountQuota", ADAttributeValueKind.IntValue, int.MaxValue)]
153172
public int DSMachineAccountQuota { get; set; }
154173
[ADAttributeAttribute("flags", ADAttributeValueKind.IntValue)]
155174
public int Flags { get; set; }
@@ -187,6 +206,8 @@ static ADItem()
187206
public SecurityIdentifier msDSCreatorSID { get; set; }
188207
[ADAttributeAttribute("msDS-EnabledFeature", ADAttributeValueKind.StringArrayValue)]
189208
public string[] msDSEnabledFeature { get; set; }
209+
[ADAttributeAttribute("msDS-ExpirePasswordsOnSmartCardOnlyAccounts", ADAttributeValueKind.BoolValue)]
210+
public bool msDSExpirePasswordsOnSmartCardOnlyAccounts { get; set; }
190211
[ADAttributeAttribute("msDS-IntId", ADAttributeValueKind.IntValue)]
191212
public int msDSIntId { get; set; }
192213
[ADAttributeAttribute("msDS-SupportedEncryptionTypes", ADAttributeValueKind.IntValue)]
@@ -197,6 +218,8 @@ static ADItem()
197218
public long msDSMaximumPasswordAge { get; set; }
198219
[ADAttributeAttribute("msDS-MinimumPasswordLength", ADAttributeValueKind.IntValue)]
199220
public int msDSMinimumPasswordLength { get; set; }
221+
[ADAttributeAttribute("msDS-Other-Settings", ADAttributeValueKind.StringArrayValue)]
222+
public string[] msDSOtherSettings { get; set; }
200223
[ADAttributeAttribute("msDS-PasswordComplexityEnabled", ADAttributeValueKind.BoolValue)]
201224
public bool msDSPasswordComplexityEnabled { get; set; }
202225
[ADAttributeAttribute("msDS-PasswordHistoryLength", ADAttributeValueKind.IntValue)]

ADWS/LDAPConnection.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
using System.Diagnostics;
99
using System.DirectoryServices;
1010
using System.Net;
11+
using System.Net.Security;
12+
using System.Net.Sockets;
1113
using System.Runtime.InteropServices;
14+
using System.Security.Cryptography.X509Certificates;
1215
using System.Security.Permissions;
1316

1417
namespace PingCastle.ADWS
@@ -187,6 +190,10 @@ private ADDomainInfo GetLDAPDomainInfo()
187190
// Windows 2000 does not support a bind to the rootDse and returns "The server is not operational" (0x8007203A)
188191
if (ex.ErrorCode == -2147016646)
189192
{
193+
if (Port == 636)
194+
{
195+
EnsureLDAPSIsWorking();
196+
}
190197
if (Credential == null)
191198
{
192199
rootDse = new DirectoryEntry(@"LDAP://" + Server + (Port == 0 ? null : ":" + Port) + "/RootDSE", null, null, AuthenticationTypes.Secure | (Port == 636 ? AuthenticationTypes.SecureSocketsLayer : 0));
@@ -204,6 +211,38 @@ private ADDomainInfo GetLDAPDomainInfo()
204211
return ADDomainInfo.Create(rootDse);
205212
}
206213

214+
private void EnsureLDAPSIsWorking()
215+
{
216+
Trace.WriteLine("testing LDAPS connectivity");
217+
using (TcpClient client = new TcpClient(Server, Port))
218+
{
219+
client.ReceiveTimeout = 1000;
220+
client.SendTimeout = 1000;
221+
using (SslStream sslstream = new SslStream(client.GetStream(), false,
222+
(object sender, X509Certificate CACert, X509Chain CAChain, SslPolicyErrors sslPolicyErrors)
223+
=>
224+
{
225+
Trace.WriteLine("Certificate presented: " + CACert.Subject);
226+
Trace.WriteLine("Certificate expires: " + CACert.GetExpirationDateString());
227+
Trace.WriteLine("SSLPolicyErrors: " + sslPolicyErrors);
228+
if (sslPolicyErrors != SslPolicyErrors.None)
229+
{
230+
Console.WriteLine("While testing the LDAPS certificate, PingCastle found the following error: " + sslPolicyErrors);
231+
Console.WriteLine("The certificate is untrusted and Windows prohibits PingCastle to connect to it");
232+
Console.WriteLine("Certificate: " + CACert.Subject);
233+
Console.WriteLine("Expires: " + CACert.GetExpirationDateString());
234+
}
235+
return true;
236+
}
237+
, null))
238+
{
239+
Trace.WriteLine("before testing LDAPS certificatre for " + Server);
240+
sslstream.AuthenticateAsClient(Server, null, System.Security.Authentication.SslProtocols.Default, false);
241+
Trace.WriteLine("testing LDAPS certificatre for " + Server + " worked");
242+
}
243+
}
244+
}
245+
207246
// connecting using LDAP
208247
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
209248
public override void EstablishConnection()

Cloud/Analyzer/Analyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ private void AnalyzePolicies()
332332
}
333333
}
334334

335-
var ms = new MicrosoftGraph(new PRTCredential());
335+
var ms = new MicrosoftGraph(credential);
336336
var authorizationPolicies = ms.GetAuthorizationPolicy();
337337
if (authorizationPolicies != null && authorizationPolicies.Count > 0)
338338
{

Cloud/RESTServices/Azure/MicrosoftGraph.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ namespace PingCastle.Cloud.RESTServices
1919
[AzureService("1b730954-1685-4b74-9bfd-dac224a7b894", "https://graph.microsoft.com")]
2020
public class MicrosoftGraph : RESTClientBase<MicrosoftGraph>, IAzureService
2121
{
22-
public MicrosoftGraph(IAzureCredential credential) : base(credential)
22+
public MicrosoftGraph(IAzureCredential credential)
23+
: base(credential)
2324
{
2425
}
2526
protected override string BuidEndPoint(string function, string optionalQuery)
@@ -42,6 +43,11 @@ public List<AuthorizationPolicy> GetAuthorizationPolicy()
4243
return CallEndPointWithPaggingAsync<object, AuthorizationPolicy>("policies/authorizationPolicy", null).GetAwaiter().GetResult();
4344
}
4445

46+
public permissionGrantPolicy GetPermissionGrantPolicies(string id)
47+
{
48+
return CallEndPointAsync<object, permissionGrantPolicy>("policies/permissionGrantPolicies/" + id, null).GetAwaiter().GetResult();
49+
}
50+
4551
// message=Insufficient privileges to complete the operation.
4652
public string GetTenantRelationships(string tenantId)
4753
{
@@ -55,6 +61,7 @@ public class AuthorizationPolicy
5561
public bool allowedToSignUpEmailBasedSubscriptions { get; set; }
5662
public bool allowedToUseSSPR { get; set; }
5763
public bool allowEmailVerifiedUsersToJoinOrganization { get; set; }
64+
public bool? allowUserConsentForRiskyApps { get; set; }
5865
public bool blockMsolPowerShell { get; set; }
5966
public string description { get; set; }
6067
public string displayName { get; set; }
@@ -72,5 +79,38 @@ public class UserRolePermissions
7279
public bool allowedToReadBitlockerKeysForOwnedDevice { get; set; }
7380
public bool allowedToReadOtherUsers { get; set; }
7481
}
82+
83+
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
84+
public class permissionGrantPolicyInclude
85+
{
86+
public string id { get; set; }
87+
public string permissionClassification { get; set; }
88+
public string permissionType { get; set; }
89+
public string resourceApplication { get; set; }
90+
public List<string> permissions { get; set; }
91+
public List<string> clientApplicationIds { get; set; }
92+
public List<string> clientApplicationTenantIds { get; set; }
93+
public List<string> clientApplicationPublisherIds { get; set; }
94+
public bool clientApplicationsFromVerifiedPublisherOnly { get; set; }
95+
public bool certifiedClientApplicationsOnly { get; set; }
96+
public ScopeSensitivityLabels scopeSensitivityLabels { get; set; }
97+
}
98+
99+
public class permissionGrantPolicy
100+
{
101+
public string id { get; set; }
102+
public string displayName { get; set; }
103+
public string description { get; set; }
104+
public bool includeAllPreApprovedApplications { get; set; }
105+
public string resourceScopeType { get; set; }
106+
public List<permissionGrantPolicyInclude> includes { get; set; }
107+
public List<object> excludes { get; set; }
108+
}
109+
110+
public class ScopeSensitivityLabels
111+
{
112+
public string labelKind { get; set; }
113+
}
114+
75115
}
76116
}

Cloud/Rules/UserConsentCompanyData.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ public class UserConsentCompanyData : RuleBase<HealthCheckCloudData>
2121
{
2222
protected override int? AnalyzeDataNew(HealthCheckCloudData healthCheckCloudData)
2323
{
24+
// disable the rule since MS changed the rule logic
25+
/*
2426
if (healthCheckCloudData.UsersPermissionToUserConsentToAppEnabled == true)
2527
{
2628
AddRawDetail("true");
27-
}
29+
}*/
2830
return null;
2931
}
3032

ConsoleMenu.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,5 +355,76 @@ public static DateTime GetBuildDateTime(Assembly assembly)
355355
}
356356
return new DateTime();
357357
}
358+
359+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
360+
public class WinTrustFileInfo
361+
{
362+
public UInt32 StructSize = (UInt32)Marshal.SizeOf(typeof(WinTrustFileInfo));
363+
public IntPtr pszFilePath;
364+
public IntPtr hFile = IntPtr.Zero;
365+
public IntPtr pgKnownSubject = IntPtr.Zero;
366+
}
367+
368+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
369+
public class WinTrustData
370+
{
371+
public UInt32 StructSize = (UInt32)Marshal.SizeOf(typeof(WinTrustData));
372+
public IntPtr PolicyCallbackData = IntPtr.Zero;
373+
public IntPtr SIPClientData = IntPtr.Zero;
374+
public UInt32 UIChoice = 2;
375+
public UInt32 RevocationChecks = 0;
376+
public UInt32 UnionChoice = 1;
377+
public IntPtr FileInfoPtr;
378+
public UInt32 StateAction = 0;
379+
public IntPtr StateData = IntPtr.Zero;
380+
public String URLReference = null;
381+
public UInt32 ProvFlags = 0x00000010;
382+
public UInt32 UIContext = 0;
383+
}
384+
385+
public class WinTrust
386+
{
387+
[DllImport("wintrust.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
388+
public static extern uint WinVerifyTrust(IntPtr hwnd, [MarshalAs(UnmanagedType.LPStruct)] Guid pgActionID, [MarshalAs(UnmanagedType.LPStruct)] WinTrustData pWVTData);
389+
390+
public static Guid WINTRUST_ACTION_GENERIC_VERIFY_V2 = new Guid("00AAC56B-CD44-11d0-8CC2-00C04FC295EE");
391+
}
392+
393+
public static uint CheckWinTrustFlags(Assembly assembly)
394+
{
395+
var path = assembly.Location;
396+
if (string.IsNullOrEmpty(path))
397+
{
398+
System.Diagnostics.Trace.WriteLine("In memory location detected");
399+
return 0x80070002;
400+
}
401+
else if (File.Exists(path))
402+
{
403+
return CheckWinTrustFlags(path);
404+
}
405+
return 0;
406+
}
407+
408+
public static uint CheckWinTrustFlags(string filePath)
409+
{
410+
WinTrustFileInfo fileInfo = new WinTrustFileInfo
411+
{
412+
pszFilePath = Marshal.StringToCoTaskMemAuto(filePath)
413+
};
414+
415+
WinTrustData trustData = new WinTrustData
416+
{
417+
FileInfoPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(WinTrustFileInfo))),
418+
RevocationChecks = 0,
419+
};
420+
Marshal.StructureToPtr(fileInfo, trustData.FileInfoPtr, false);
421+
422+
uint result = WinTrust.WinVerifyTrust(IntPtr.Subtract(IntPtr.Zero, 1), WinTrust.WINTRUST_ACTION_GENERIC_VERIFY_V2, trustData);
423+
424+
Marshal.FreeCoTaskMem(fileInfo.pszFilePath);
425+
Marshal.FreeCoTaskMem(trustData.FileInfoPtr);
426+
427+
return result;
428+
}
358429
}
359430
}

Data/CompromiseGraphData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ public bool IsTypeAUser
314314
return (string.Equals(Type, "user", StringComparison.OrdinalIgnoreCase)
315315
|| string.Equals(Type, "inetOrgPerson", StringComparison.OrdinalIgnoreCase)
316316
|| string.Equals(Type, "msDS-GroupManagedServiceAccount", StringComparison.OrdinalIgnoreCase)
317-
|| string.Equals(Type, "msDS-ManagedServiceAccountt", StringComparison.OrdinalIgnoreCase)
317+
|| string.Equals(Type, "msDS-ManagedServiceAccount", StringComparison.OrdinalIgnoreCase)
318318
);
319319
}
320320
}

0 commit comments

Comments
 (0)