Certify icon indicating copy to clipboard operation
Certify copied to clipboard

Crashes on Server 2012R2 - possibly related to certlib version.

Open l0ss opened this issue 3 years ago • 11 comments

As discussed on BH slack:

Compiled Certify on Win10 2004 with VS2019. Executed via Cobalt Strike's execute-assembly on Windows Server 2012R2. Certify.exe find /vulnerable appeared to work fine. Certify.exe request /ca:**REDACTED** /template:**REDACTED** /altname:**REDACTED* threw the following exception:

System.InvalidCastException: Unable to cast COM object of type 'CERTENROLLLib.CX509PrivateKeyClass' to interface type 'CERTENROLLLib.IX509PrivateKey2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{728AB362-217D-11DA-B2A4-000E7BBB2B09}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
   at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease)
   at CERTENROLLLib.CX509PrivateKeyClass.set_Length(Int32 pValue)
   at Certify.Cert.CreatePrivateKey(Boolean machineContext)
   at Certify.Cert.CreateCertRequestMessage(String templateName, Boolean machineContext, String subjectName, String altName)
   at Certify.Cert.RequestCert(String CA, Boolean machineContext, String templateName, String subject, String altName, Boolean install)
   at Certify.Commands.Request.Execute(Dictionary`2 arguments)
   at Certify.CommandCollection.ExecuteCommand(String commandName, Dictionary`2 arguments)
   at Certify.Program.MainExecute(String commandName, Dictionary`2 parsedArgs)

After some trial and error I found that by changing CreatePrivateKey() to return a CX509PrivateKey instead of IX509PrivateKey (and compiling it on Server2012) I could get Certify to request a cert and receive a valid-looking pem-formatted cert back from the CA.

Unfortunately, when trying to actually use the cert with Rubeus.exe asktgt I was getting KDC_ERR_CLIENT_NOT_TRUSTED. On further examination of the pem-formatted cert that certify gave me back (with openssl x509 -in cert.pem -text I noticed that the SAN field wasn't as expected, and was instead showing this:

            X509v3 Subject Alternative Name: 
                othername:<unsupported>

Let me know if there's any other details I can provide to help troubleshoot and I'll do my best.

l0ss avatar Aug 05 '21 12:08 l0ss

Same problem here (Unable to cast COM object [...]). If you need any further details, please let me know.

achsooistdas avatar Aug 06 '21 09:08 achsooistdas

Same here, any help appreciated. Tried some quick fixes (e.g., replacing Interop.CERTENROLLLib.dll) - but this was more or less trial and error... (target server is Windows Server 2012 R2 Standard)

symmetrisch avatar Aug 06 '21 10:08 symmetrisch

In my experience it's pretty common when dealing with the CERTENROLLLib on older OS to have to replace stuff like this:

CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10();

with something like this:

IX509CertificateRequestPkcs10 objPkcs10 = (IX509CertificateRequestPkcs10)Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509CertificateRequestPkcs10"));

You might try something like this for CreatePrivateKey():

        private static IX509PrivateKey CreatePrivateKey(bool machineContext)
        {
            var cspInfo = new CCspInformations();
            cspInfo.AddAvailableCsps();

            var privateKey = (IX509PrivateKey)Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509PrivateKey"));

            privateKey.Length = 2048;
            privateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;
            privateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;
            privateKey.MachineContext = machineContext;
            privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG;
            privateKey.CspInformations = cspInfo;

            privateKey.Create();

            return privateKey;
        }

aseigler avatar Aug 06 '21 14:08 aseigler

This ☝️ Many thanks!!

symmetrisch avatar Aug 06 '21 16:08 symmetrisch

I also encountered this error while trying to use these new Certificate Vulnerabilities with an 2012R2 server. When changing the code to what @aseigler recommended there seems to be another error that crops up near line 115 in Cert.cs source code.

 // format 2 - required for the EDITF_ATTRIBUTESUBJECTALTNAME2 scenario
                var altNamePair = new CX509NameValuePair();
                altNamePair.Initialize("SAN", $"upn={altName}");
                objPkcs10.NameValuePairs.Add(altNamePair);

It states that the object pbjPkc10 (IX509CertificateRequestPkcs10 type) does not contain a definition for 'NameValuePairs' and no accessible extension method 'NameValuePairs' accepting a first argument of type 'IX509CertificateRequestPkcs10' can be found.

Was anybody able to get around this.

SV-ZeroOne avatar Aug 16 '21 13:08 SV-ZeroOne

Try replacing this:

var objPkcs10 = new CX509CertificateRequestPkcs10();

With this:

            IX509CertificateRequestPkcs10V3 objPkcs10 = (IX509CertificateRequestPkcs10V3)Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509CertificateRequestPkcs10"));
            var context = machineContext
                ? X509CertificateEnrollmentContext.ContextMachine
                : X509CertificateEnrollmentContext.ContextUser;

            objPkcs10.InitializeFromPrivateKey(context, privateKey, "");

            CX509ExtensionTemplateName objExtensionTemplate = new CX509ExtensionTemplateName();
            objExtensionTemplate.InitializeEncode(templateName);
            objPkcs10.X509Extensions.Add((CX509Extension)objExtensionTemplate);

My fork has these set and worked for me on 2012R2.

aseigler avatar Aug 16 '21 13:08 aseigler

This should be fixed now with 4c24a835527e5524d5fd2777fc7185422cf5fe4d. If any of you could test and verify, please let us know if it solved your problem! I tested on a 2016 server and a similar issue was fixed, so hopefully it covers the 2012 case as well (I don't have a server up to test with right now)

leechristensen avatar Oct 06 '21 06:10 leechristensen

Ran into an issue that appears to be related, using latest build as of yesterday.

[!] Unhandled Certify exception:

System.Exception: Your certlib does not know an implementation of X509Enrollment.CX509CertificateRequestPkcs10 (in HKLM:\SOFTWARE\Classes\Interface\)!
   at Certify.Cert.CreateCertRequestMessage(String templateName, Boolean machineContext, String subjectName, String altName)
   at Certify.Cert.RequestCert(String CA, Boolean machineContext, String templateName, String subject, String altName, Boolean install)
   at Certify.Commands.Request.Execute(Dictionary`2 arguments)
   at Certify.CommandCollection.ExecuteCommand(String commandName, Dictionary`2 arguments)
   at Certify.Program.MainExecute(String commandName, Dictionary`2 parsedArgs)

l0ss avatar Oct 21 '21 23:10 l0ss

@leechristensen - Attempted on a Windows 2012 R2 today (proven vulnerable and exploited through other methods) and the latest version did not resolve this. Going to look into @aseigler's recommendations and will report back how it works out.

ac3lives avatar Nov 02 '22 19:11 ac3lives

Today, faced the similar issue (as in the beginning of the post) in windows 8 machine. Compiled with the suggestion of what @aseigler mentioned. It worked for me nicely.

mali44 avatar Nov 29 '22 18:11 mali44