Join Keyfactor at RSA Conference™ 2024    |    May 6 – 9th    | Learn More

Safely Adding SAN Information to a Certificate Request

SSL/TLS Certificates

This blog is a continuation in a series of blogs, relating to the perils of adding Subject Alternate Name (SAN) information to a certificate signing request (CSR).

In previous blogs, I described how configurations required to add SAN information to existing certificate signing requests can leave one’s CA vulnerable to impersonation attacks. That is to say, if your certificate issuance workflow depends on the certificate SAN information being added after a CSR is created, then it’s likely your CA can be used in malicious ways.

Why is this?

In order to add SAN information to a certificate safely, the SAN information must be included within the signed portion of its certificate request.  SAN information can be submitted within a CSR, or alongside it.  And the Microsoft CA can be configured (by setting the “EDITF_ATTRIBUTESUBJECTALTNAME2” policy flag) to trust and use both locations when adding SAN information to a certificate. However, CSS does not generally recommend using this flag.

Adding the SAN information after a CSR has been signed, means that one cannot include the certificate’s SAN information within the signed portion. Therefore the SAN information must be added to the end of the CSR. This method adds SAN information to the CSR in the form of a certificate request attribute. A certificate request attribute in this case can only be outside the signed portion of the original request, and is therefore not considered safe. Adding SAN information in this manner means that the SAN information can modified at any time, and by anyone. Typically this is not considered safe, and is the reason Microsoft and CSS strongly warn against this method.

Unfortunately this is exactly how many administrators have structured their CSR workflow.  A CSR is generated by an app team, then sent to the Certificate Officer for signature. The certificate officer then adds all appropriate SAN information to the request, and signs the CSR and returns the signed certificate. Sound familiar?

Unfortunately I see this sort of configuration all too often.  And to an extent, it’s understandable.

But what’s the alternative?

In the past, I’ve suggested that the best approach is to ensure that the app team knows what the appropriate SAN information should be, and ensure that all SAN information is included as a part of the CSR generation process. Rejecting any CSRs that are lacking appropriate SAN information, and signing only those that are correct.

This is still sound advice.

But for those environments where this approach will simply not work, there may be an alternative.

Resigning the CSRs

A safer option for adding SAN information to an already-signed CSR is to use an enrollment agent (EA) certificate to re-sign the original request. You can then specify the correct SAN information, and re-sign the original request with the EA certificate.

This allows the SAN information to be included after the initial creation of the certificate, but still be in a signed portion of a CSR.

Here is how:

  1. Acquire an Enrollment Agent Certificate
  2. Modify an SSL certificate template to require an EA certificate for issuance
  3. Acquire a CSR that needs SAN Information
  4. Use the EA certificate to resign the CSR while adding the SAN information.

The following is a quick overview of these 4 steps.   This blog is not prescriptive guidance, but is intended to provide an overview of the process.

1.) Acquire an Enrollment Agent Certificate

This is a certificate based off the Enrollment Agent default template. The resulting EA certificate must contain the “Certificate Request Agent” application policy extension. (1.3.6.1.4.1.311.20.2.1.)

WHa.png

This certificate (and associated private key) should be located on a workstation where the administrator would have access to both. It is this certificate that a Certificate Officer would select when asked during the re-signing process.

2.) Modify an SSL certificate template to require an EA certificate for issuance

Modify your existing SSL template to require an EA Signature. This template should also be configured to accept the subject in the request itself.

WHb.png

This means that only those that possess an EA Certificate would be able to use this template. And while restricted enrollment agents are not the point of this blog post, you might consider specifying a specific enrollment agent for the specific SSL template being tested for this exercise.

3.) Acquire a CSR that needs SAN Information

The creation of a CSR can be accomplished in a myriad of ways.  This blog post will assume that a CSR already exists. Here is an overview of an existing CSR:

PKCS10 Certificate Request:

Version: 1

Subject:

    CN=Demonstration Web Server v1

  Name Hash(sha1): ded0833a1bb48a7a747a06598988c9e12ef97342

  Name Hash(md5): bd27f43381a77a239a935f86206424e5

 

    2.5.29.17: Flags = 0, Length = 1f

    Subject Alternative Name

        DNS Name=Banana.css-vstc.com

        DNS Name=Banana

Signature matches Public Key

Key Id Hash(rfc-sha1): bc bd 57 27 3a cc 63 79 01 dc 57 9c 2e 38 05 37 09 55 7b 2c

Key Id Hash(sha1): 53 bb 85 45 53 3f 9a ef aa 59 08 91 37 da b1 c7 c4 29 9d 2d

As you can see, this CSR has a subject, and a subject alternative name.

For demonstration purposes, we will be changing the SAN information.

4.) Use the EA certificate to re-sign the CSR while adding the SAN information

Using a simple certreq.exe command, you can use the EA certificate to re-sign the above request using the following command line:

certreq -policy -config "CA1.csstest.com\CSS Test CA 1" "ORIGINAL-SERVER-REQUEST.REQ" "Server-policy.inf" "Corrected-Server-Request.req"

As one can see, this command specifies the original request file to build a new “corrected” request file.

This command line specifies a policy file called "Server-policy.inf" to specify correct new SAN information. Here is what my "Server-policy.inf" looks like:

[Extensions]

2.5.29.17 = "{text}"

_continue_ = "[email protected]&"

_continue_ = "DNS=Orange.css-vstc.com"

As you can see, this is just a simple text file that adds the corrected SAN information as an extension.

The above certreq command uses the “Server-policy.inf” file, and my EA certificate to add the new SAN information, and then re-sign the original CSR, creating a new file.

Internal to the new resulting CSR, the process wraps new information around the original CSR. The original CSR content is still there, it’s just layered inside the new content.  Here is an abbreviated look at what the new (now wrapped) CSR looks like:

PKCS7/CMS Message:

  CMSG_SIGNED(2)

  CMSG_SIGNED_DATA_CMS_VERSION(3)

  Content Type: 1.3.6.1.5.5.7.12.2 CMC Data

PKCS7 Message Content:

================ Begin Nesting Level 1 ================

CMS Certificate Request:

Tagged Attributes: 1

    Extensions: 1

    2.5.29.17: Flags = 0, Length = 2f

    Subject Alternative Name

        RFC822 [email protected]

        DNS Name=Orange.css-vstc.com

================ Begin Nesting Level 2 ================

Element 0:

PKCS10 Certificate Request:

Version: 1

Subject:

  CN=Demonstration Web Server v1

  Name Hash(sha1): ded0833a1bb48a7a747a06598988c9e12ef97342

  Name Hash(md5): bd27f43381a77a239a935f86206424e5

    2.5.29.17: Flags = 0, Length = 1f

    Subject Alternative Name

        DNS Name=Banana.css-vstc.com

        DNS Name=Banana

    2.5.29.14: Flags = 0, Length = 16

    Subject Key Identifier

        bc bd 57 27 3a cc 63 79 01 dc 57 9c 2e 38 05 37 09 55 7b 2c

 

Signature matches Public Key

Key Id Hash(rfc-sha1): bc bd 57 27 3a cc 63 79 01 dc 57 9c 2e 38 05 37 09 55 7b 2c

Key Id Hash(sha1): 53 bb 85 45 53 3f 9a ef aa 59 08 91 37 da b1 c7 c4 29 9d 2d

----------------  End Nesting Level 2  ----------------

Tagged Content Info: 0

Tagged Other Messages: 0

----------------  End Nesting Level 1  ----------------

As you can see, the original CSR is still there, but now with new SAN information wrapped around it, and signed with the EA certificate.

This new CSR would then simply be submitted to the CA:

Certreq -submit -config "CA1.csstest.com\CSS Test CA 1" "Corrected-Server-Request.req" "Server.cer"

Submitting this certificate to the CA will result in a certificate whose SAN information is updated by a Certificate Officer. More importantly, this is accomplished without setting the EDITF_ATTRIBUTESUBJECTALTNAME2” policy flag.

In this case, from Banana.css-vstc.com to Orange.css-vstc.com.

WHc.png

The CA’s policy module will not reject this request, as this new SAN information is still in a signed portion of the certificate signing request, and is indeed signed.  This solution results in a CA whose security is maintained, while allowing the flexibility of adding SAN information to existing CSRs, in safe, and controlled manner.

Summary

If you are in charge of a corporate PKI, and are considering setting the “EDITF_ATTRIBUTESUBJECTALTNAME2” policy flag on your CA in order to meet SAN workflow requirements, I would suggest you consider an alternative to this policy setting.

Instead, consider using an EA certificate to re-sign CSRs while specifying correct SAN information.

Re-signing your CSRs using Certreq.exe with an enrollment agent certificate allows for the safe addition of SAN information to a CSR *after* its creation, but in a way that does not leave your PKI vulnerable to impersonation attacks.