Other posts in the series:


Security considerations

Many of you already heared about a recommendation to place all requests where subject is supplied in the request in pending state for future revision and request approval by the CA manager. Many of PKI administrators consider this as a waste measure and do not follow this recommendation. Several of PKI administrators are aware about the security risk that the requester can put any subject in the request and they require manual approval of the certificate request. Though, they just check for Subject field and/or SAN extension in the request and approve the request if the subject looks like valid.

However there is less-known (but not less dangerous) risk that the requester has included wrong or inappropriate extensions. For example, with default Web Server template it is possible to issue a certificate for OCSP Response Signing. If the administrator is not too smart, a PKI can be compromised due to inappropriate certificate issuance. If you run Get-ExtensionList command from my PowerShell PKI module you will see two interesting properties: EnabledExtensionList and OfflineExtensionList:

PS C:\> Get-CA | Get-ExtensionList | select -ExpandProperty enabledextensionlist

Value                                                       FriendlyName
-----                                                       ------------
1.2.840.113549.1.9.15                                       SMIME Capabilities
1.3.6.1.4.1.311.21.1                                        CA Version
1.3.6.1.4.1.311.21.2                                        Previous CA Certificate Hash
2.5.29.15                                                   Key Usage


PS C:\> Get-CA | Get-ExtensionList | select -ExpandProperty offlineextensionlist

Value                                                       FriendlyName
-----                                                       ------------
1.3.6.1.4.1.311.10.9.1                                      Cross-Certificate Distribution Points
1.3.6.1.4.1.311.20.2                                        Certificate Template Name
1.3.6.1.4.1.311.21.7                                        Certificate Template Information
1.3.6.1.4.1.311.21.10                                       Application Policies
1.3.6.1.4.1.311.21.11                                       Application Policy Mappings
1.3.6.1.4.1.311.21.12                                       Application Policy Constraints
2.5.29.17                                                   Subject Alternative Name
2.5.29.30                                                   Name Constraints
2.5.29.32                                                   Certificate Policies
2.5.29.33                                                   Policy Mappings
2.5.29.36                                                   Policy Constraints
2.5.29.37                                                   Enhanced Key Usage


PS C:\>

As per documentation, EnabledExtensionList contains a list of extensions that are processed each time the request is submitted. There are no interesting extension. OfflineExtensionList contains a list of extensions that are processed by the CA only for those requests that use certificate template which constructs subject information based on a request (supply in the request). Even though, a requester cannot override extensions defined in the template, he can add additional values for these extensions. Here is a little PoC:

# instantiate request object:
$Request = New-Object -ComObject X509Enrollment.CX509Enrollment
$Request.InitializeFromTemplateName(0x2,"WebServer")
# add sample subject
$SubjectDN = New-Object -ComObject X509Enrollment.CX500DistinguishedName
$SubjectDN.Encode("CN=www.microsoft.com", 0x0)

# add Application Policies and EKU extensions with OCSP Response Signing value:
$OIDs = New-Object -ComObject X509Enrollment.CObjectIDs
$Policies = New-Object -ComObject X509Enrollment.CCertificatePolicies
foreach ($OIDstring in "1.3.6.1.5.5.7.3.1","1.3.6.1.5.5.7.3.9") {
    $OID = New-Object -ComObject X509Enrollment.CObjectID
    $Policy = New-Object -ComObject X509Enrollment.CCertificatePolicy
    $OID.InitializeFromValue($OIDstring)
    $Policy.Initialize($OID)
    $OIDs.Add($OID)
    $Policies.Add($Policy)
}
$cEKU = New-Object -ComObject X509Enrollment.CX509ExtensionEnhancedKeyUsage
$cMSAppId = New-Object -ComObject X509Enrollment.CX509ExtensionMSApplicationPolicies
$cEKU.InitializeEncode($OIDs)
$cMSAppId.InitializeEncode($Policies)

# add subject and extension information
$Request.Request.Subject = $SubjectDN
$Template = $Request.Request.X509Extensions.ItemByIndex(0)
$Request.Request.X509Extensions.Clear()
$cEKU, $cMSAppId, $Template | %{$Request.Request.X509Extensions.Add($_)}

# pushhhhhhhhh
$Request.Enroll()

Resulting certificate is:

image

In order to avoid possible issues with incoming requests, configure the template to store all requests pending if the template is configured to supply subject information in the request. And, of course, review them in details before approving.

Other stuff

And the last thing in the CertEnroll I want to talk about. Do you know, that CertErnoll can easy create self-signed certificates? If the answer is positive, stop reading this post.

The trick is that there is a IX509CertificateRequestCertificate interface. This interface is very similar to IX509CertificateRequestPkcs10 and you can use previous example to fill the properties and extension. Moreover, you can easily use certificate templates to create preconfigured self-signed certificate:

$Cert = New-Object -ComObject X509enrollment.CX509CertificateRequestCertificate
$Cert.InitializeFromTemplateName(0x2,"WebServer")
# provide some subject
$SubjectDN = New-Object -ComObject X509Enrollment.CX500DistinguishedName
$SubjectDN.Encode("CN=www.microsoft.com", 0x0)
$Cert.Subject = $SubjectDN
# you can use either default or custom validity settings:
$Cert.NotBefore = [datetime]::Now
$Cert.NotAfter = [datetime]::Now.AddYears(5)

$Request = New-Object -ComObject X509Enrollment.CX509enrollment
# process request
$Request.InitializeFromRequest($Cert)
# retrieve certificate encoded in Base64.
$endCert = $Request.CreateRequest(0x1)
# install certificate to machine store
$Request.InstallResponse(0x2,$endCert,0x1,"")

and the resulting certificate:

image

If you switch to Details tab you will see specified template settings.

Note: do not use self-signed certificates in production environments. You should use self-signed certificates solely in test purposes. In a production environments all end-entity certificates must be signed by a trusted CA.


Share this article:

Comments:


Post your comment:

Please, solve this little equation and enter result below. Captcha