8000 Development v1.2 by Sleepw4lker · Pull Request #2 · Sleepw4lker/TameMyCerts · GitHub
[go: up one dir, main page]

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

Development v1.2 #2

Merged
merged 28 commits into from
Aug 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2839937
Implement fixed expiration date
Sleepw4lker Apr 21, 2022
dab3169
Implement mitigation against abuse of new cert extension introduced w…
Sleepw4lker May 14, 2022
047ffb4
Update README
Sleepw4lker May 17, 2022
20d23fd
Implement error handling for the case that a SAN extension cannot be …
Sleepw4lker May 17, 2022
b565263
Rename organizationalUnit RDN to organizationalUnitName to align with…
Sleepw4lker Jun 7, 2022
3bbd04f
Prevent installer to operate when DLL is missing
Sleepw4lker Jun 7, 2022
eeb7289
Remove unnecessary garbage collection
Sleepw4lker Jun 7, 2022
4d900e7
Code refactoring
Sleepw4lker Jun 7, 2022
6961286
Code refactoring
Sleepw4lker Jun 9, 2022
eb7499f
Code refactoring
Sleepw4lker Jun 20, 2022
966b880
Improve and extend unit tests
Sleepw4lker Jun 20, 2022
30323e9
Add copyright notice to RequestValidator test project
Sleepw4lker Aug 8, 2022
1cceb52
Modify Copyright notice
Sleepw4lker Aug 8, 2022
26982f1
Modify Copyright notice
Sleepw4lker Aug 8, 2022
c03e0f1
Add IL to project config
Sleepw4lker Aug 8, 2022
18fe651
Code refactoring
Sleepw4lker Aug 8, 2022
54e6a0a
Modify copyright notice
Sleepw4lker Aug 8, 2022
2e6f3d7
Implement support for AD lookup for offline templates
Sleepw4lker Aug 8, 2022
919c8d9
Implement support for adding sid certificate extension into offline r…
Sleepw4lker Aug 8, 2022
d3a3a82
Update README
Sleepw4lker Aug 9, 2022
679785d
Release candidate 1
Sleepw4lker Aug 9, 2022
4f1ad6a
Add Unit test for SidCertificateExtension
Sleepw4lker Aug 11, 2022
d5e67f0
Refactor samples
Sleepw4lker Aug 11, 2022
ddfb821
Refactor SidCertificateExtension class
Sleepw4lker Aug 11, 2022
8f7d1d5
Fix a variable in installer
Sleepw4lker Aug 11, 2022
36b0819
Update README
Sleepw4lker Aug 11, 2022
ac329ae
Refactor SidCertificateExtension class
Sleepw4lker Aug 11, 2022
ad24464
Release 1.2.585.878
Sleepw4lker Aug 11, 2022
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
Prev Previous commit
Next Next commit
Implement support for adding sid certificate extension into offline r…
…equests
  • Loading branch information
Sleepw4lker committed Aug 8, 2022
commit 919c8d983803804e954b5dfb1e5e92f417347713
31 changes: 31 additions & 0 deletions TameMyCerts/CCertServerPolicyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,36 @@ public static byte[] GetBinaryRequestPropertyOrDefault(this CCertServerPolicy se
}

#endregion

#region SetCertificateExtension

public static void SetCertificateExtension(this CCertServerPolicy serverPolicy, string oid, string value, bool critical = false)
{
var rawData = Convert.FromBase64String(value);

IntPtr pBstr = Marshal.AllocHGlobal(rawData.Length + 4);
Marshal.WriteInt32(pBstr, 0, rawData.Length);
Marshal.Copy(rawData, 0, pBstr + 4, rawData.Length);
var variant = new OleAut32.VARIANT
{
vt = 8, // VT_BSTR
pvRecord = pBstr + 4
};
IntPtr pvarValue = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OleAut32.VARIANT)));
Marshal.StructureToPtr(variant, pvarValue, false);
Int32 dwCritical = critical ? 1 : 0;

try
{
serverPolicy.SetCertificateExtension(oid, CertSrv.PROPTYPE_BINARY, dwCritical, pvarValue);
}
finally
{
Marshal.FreeHGlobal(pBstr);
Marshal.FreeHGlobal(pvarValue);
}
}

#endregion
}
}
16 changes: 10 additions & 6 deletions TameMyCerts/CERTCLILIB.il
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,8 @@
instance object
marshal( struct)
GetCertificateExtension([in] string marshal( bstr) strExtensionName,
[in] int32 Type) runtime managed internalcall
[in] int32 Type,
[out] native int pvarValue) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 05 00 02 60 00 00 ) // .....`..
} // end of method ICertServerPolicy::GetCertificateExtension
Expand All @@ -815,7 +816,7 @@
instance void SetCertificateExtension([in] string marshal( bstr) strExtensionName,
[in] int32 Type,
[in] int32 ExtFlags,
[in] object& marshal( struct) pvarValue) runtime managed internalcall
[in] native int pvarValue) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 07 00 02 60 00 00 ) // .....`..
} // end of method ICertServerPolicy::SetCertificateExtension
Expand Down Expand Up @@ -939,7 +940,8 @@
instance object
marshal( struct)
GetCertificateExtension([in] string marshal( bstr) strExtensionName,
[in] int32 Type) runtime managed internalcall
[in] int32 Type,
[out] native int pvarValue) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 05 00 02 60 00 00 ) // .....`..
.override CERTCLILib.ICertServerPolicy::GetCertificateExtension
Expand All @@ -956,7 +958,7 @@
instance void SetCertificateExtension([in] string marshal( bstr) strExtensionName,
[in] int32 Type,
[in] int32 ExtFlags,
[in] object& marshal( struct) pvarValue) runtime managed internalcall
[in] native int pvarValue) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 07 00 02 60 00 00 ) // .....`..
.override CERTCLILib.ICertServerPolicy::SetCertificateExtension
Expand Down Expand Up @@ -1054,7 +1056,8 @@
instance object
marshal( struct)
GetCertificateExtension([in] string marshal( bstr) strExtensionName,
[in] int32 Type) runtime managed internalcall
[in] int32 Type,
[out] native int pvarValue) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 04 00 02 60 00 00 ) // .....`..
} // end of method ICertServerExit::GetCertificateExtension
Expand Down Expand Up @@ -1175,7 +1178,8 @@
instance object
marshal( struct)
GetCertificateExtension([in] string marshal( bstr) strExtensionName,
[in] int32 Type) runtime managed internalcall
[in] int32 Type,
[out] native int pvarValue) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 04 00 02 60 00 00 ) // .....`..
.override CERTCLILib.ICertServerExit::GetCertificateExtension
Expand Down
Binary file modified TameMyCerts/CERTCLILib.dll
Binary file not shown.
1 change: 1 addition & 0 deletions TameMyCerts/CertificateRequestValidationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public CertificateRequestValidationResult(bool auditOnly, string notAfter)
public bool AuditOnly { get; }
public List<string> Description { get; set; } = new List<string>();
public List<KeyValuePair<string, string>> Identities { get; set; } = new List<KeyValuePair<string, string>>();
public List<KeyValuePair<string, string>> Extensions { get; set; } = new List<KeyValuePair<string, string>>();

public void SetFailureStatus()
{
Expand Down
1 change: 0 additions & 1 deletion TameMyCerts/CertificateRequestValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ public CertificateRequestValidationResult VerifyRequest(string certificateReques

#region Process request extensions

// TODO: KB5014754. Validation logic is yet to be established. I assume we will need this for mobile devices until May 9, 2023.
if (certificateRequestPolicy.SecurityIdentifierExtension.Equals("Deny",
StringComparison.InvariantCultureIgnoreCase) &&
certificateRequestPkcs10.HasExtension(WinCrypt.szOID_DS_CA_SECURITY_EXT))
Expand Down
55 changes: 43 additions & 12 deletions TameMyCerts/DirectoryServicesValidator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
using System;
// Copyright 2021 Uwe Gradenegger <uwe@gradenegger.eu>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Security.Principal;

namespace TameMyCerts
{
Expand Down Expand Up @@ -101,6 +117,8 @@ public CertificateRequestValidationResult VerifyRequest(CertificateRequestPolicy
return result;
}

#region process memberships of allowed groups

if (dsMapping.AllowedSecurityGroups.Count > 0)
{
var matchFound = false;
Expand All @@ -122,23 +140,36 @@ public CertificateRequestValidationResult VerifyRequest(CertificateRequestPolicy
}
}

#endregion

#region process memberships of disallowed groups

if (dsMapping.DisallowedSecurityGroups.Count <= 0)
if (dsMapping.DisallowedSecurityGroups.Count > 0)
{
return result;
for (var index = 0; index < searchResults[0].Properties["memberOf"].Count; index++)
{
var group = searchResults[0].Properties["memberOf"][index];
if (dsMapping.DisallowedSecurityGroups.Any(x =>
x.Equals(group.ToString(), StringComparison.InvariantCultureIgnoreCase)))
{
result.SetFailureStatus(WinError.CERTSRV_E_TEMPLATE_DENIED, string.Format(
LocalizedStrings.DirVal_Account_Groups_Disallowed,
dsMapping.ObjectCategory, identity, group));
}
}
}

for (var index = 0; index < searchResults[0].Properties["memberOf"].Count; index++)
#endregion

#region Process SID certificate extension construction

if (certificateRequestPolicy.SecurityIdentifierExtension.Equals("Add",
StringComparison.InvariantCultureIgnoreCase))
{
var group = searchResults[0].Properties["memberOf"][index];
if (dsMapping.DisallowedSecurityGroups.Any(x =>
x.Equals(group.ToString(), StringComparison.InvariantCultureIgnoreCase)))
{
result.SetFailureStatus(WinError.CERTSRV_E_TEMPLATE_DENIED, string.Format(
LocalizedStrings.DirVal_Account_Groups_Disallowed,
dsMapping.ObjectCategory, identity, group));
}
var objectSid =
new SecurityIdentifier((byte[]) searchResults[0].Properties["objectSid"][0], 0).ToString();
result.Extensions.Add(new KeyValuePair<string, string>(WinCrypt.szOID_DS_CA_SECURITY_EXT,
new SidCertificateExtension(objectSid).value));
}

#endregion
Expand Down
36 changes: 36 additions & 0 deletions TameMyCerts/OleAut32.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2021 Uwe Gradenegger <uwe@gradenegger.eu>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Kudos to Vadims podans for his research and support!

using System;
using System.Runtime.InteropServices;

namespace TameMyCerts {
class OleAut32 {
public const Int16 VT_BSTR = 0x8;

[DllImport("OleAut32.dll", SetLastError = true)]
public static extern Int32 VariantClear(IntPtr pvarg);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct VARIANT {
public Int16 vt;
public Int16 wReserved1;
public Int16 wReserved2;
public Int16 wReserved3;
public IntPtr pvRecord;
}
}
}
7 changes: 5 additions & 2 deletions TameMyCerts/Policy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ public int VerifyRequest(string strConfig, int context, int bNewRequest, int fla

#region Process insecure flag/attribute combinations

// TODO: Move this into CertificateRequestValidator, remove dependency on EditFlags (it is never a good idea to use the san extension)

// Deny requests containing the "san" request attribute
if ((_editFlags & CertSrv.EDITF_ATTRIBUTESUBJECTALTNAME2) == CertSrv.EDITF_ATTRIBUTESUBJECTALTNAME2 &&
requestAttributeList.Any(x => x.Key.Equals("san", StringComparison.InvariantCultureIgnoreCase)))
Expand Down Expand Up @@ -241,6 +239,11 @@ public int VerifyRequest(string strConfig, int context, int bNewRequest, int fla
{
validationResult =
_directoryServicesValidator.VerifyRequest(requestPolicy, validationResult);

foreach (var extension in validationResult.Extensions)
{
certServerPolicy.SetCertificateExtension(extension.Key, extension.Value);
}
}

// No reason to deny the request, let's issue the certificate
Expand Down
85 changes: 85 additions & 0 deletions TameMyCerts/SidCertificateExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2021 Uwe Gradenegger <uwe@gradenegger.eu>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.IO;
using System.Linq;

namespace TameMyCerts
{
public class SidCertificateExtension
{
public string value;

public SidCertificateExtension(string sid)
{
var result = ConvertStringToDerNode("04", ConvertStringToHexString(sid));
result = ConvertStringToDerNode("A0", result);
result = $"060A2B060104018237190201{result}";
result = ConvertStringToDerNode("A0", result);
result = ConvertStringToDerNode("30", result);
result = Convert.ToBase64String(HexStringToByteArray(result));

value = result;
}

private static byte[] HexStringToByteArray(string input)
{
var outputLength = input.Length / 2;
var output = new byte[outputLength];
using (var sr = new StringReader(input))
{
for (var i = 0; i < outputLength; i++)
{
output[i] = Convert.ToByte(new string(new[] {(char) sr.Read(), (char) sr.Read()}), 16);
}
}

return output;
}

private static string ConvertStringToDerNode(string identifier, string content)
{
return $"{identifier}{GetAsn1LengthOctets(content.Length)}{content}";
}

private static string ConvertStringToHexString(string content)
{
return content.ToCharArray().Aggregate("", (current, c) => current + $"{(int) c:X2}");
}

private static string GetAsn1LengthOctets(int length)
{
var x = (int) Math.Ceiling(length / 2m);

var numBits = Convert.ToString(x, 2).Length;
var numOctets = Math.Ceiling(numBits / 8m);

if (numBits <= 7)
{
// Short form (for lengths between 0 and 127). One octet.
// Bit 8 has value "0" and bits 7-1 give the length.
return $"{x:X2}";
}

// Long form. Two to 127 octets.

// Second and following octets give the length, base 256, most significant digit first.
var result = string.Format("{0:X" + numOctets * 2 + "}", x);

// Bit 8 of first octet has value "1" and bits 7-1 give the number of additional length octets.
return string.Format("{0:X2}", (int) (128 + numOctets)) + result;
}
}
}
2 changes: 2 additions & 0 deletions TameMyCerts/TameMyCerts.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@
<DependentUpon>LocalizedStrings.resx</DependentUpon>
</Compile>
<Compile Include="Logger.cs" />
<Compile Include="OleAut32.cs" />
<Compile Include="Policy.cs" />
<Compile Include="PolicyManage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CertificateRequestValidator.cs" />
<Compile Include="CertificateTemplateInfo.cs" />
<Compile Include="Headers.cs" />
<Compile Include="SidCertificateExtension.cs" />
</ItemGroup>
<ItemGroup>
<None Include="CERTCLILib.il" />
Expand Down
0