Tag Archives: Microsoft

Another Sleeping Giant: Microsoft’s Root Program and the 1.1.1.1 Certificate Slip

This morning (September 3, 2025), someone posted an incident to the Mozilla dev-security-policy list that exposed a serious incident: “Incident Report: Mis-issued Certificates for SAN iPAddress: 1.1.1.1 by Fina RDC 2020.” An obscure CA, Fina RDC 2020, issued certificates containing the IP address 1.1.1.1, used by Cloudflare for encrypted DNS. These certificates should never have been issued.

Reference: https://groups.google.com/a/mozilla.org/g/dev-security-policy/c/SgwC1QsEpvc

Why this matters

1.1.1.1 is a critical bootstrap endpoint

This IP anchors encrypted DNS (DoH, DoT). A mis-issued certificate, combined with a BGP hijack, allows an attacker to intercept traffic before secure tunnels form. Some may argue that an attacker would also need to perform a BGP hijack to exploit such a certificate, but this is no real mitigation. BGP hijacks are a regular occurrence – often state-sponsored — and when combined with a valid certificate, they turn a routing incident into a full man-in-the-middle compromise. Cloudflare documentation:

Mainstream browsers like Chrome and Firefox typically use the domain name cloudflare-dns.com when bootstrapping DoH/DoT, so they would ignore a certificate that only listed IP:1.1.1.1. However, both Google and Cloudflare also support direct IP endpoints (https://8.8.8.8/dns-query and https://1.1.1.1/dns-query). In these cases, an IP SAN certificate would validate just as Alex Radocea’s curl test showed: “subjectAltName: host “8.8.8.8” matched cert’s IP address!”.

The behavior differs slightly between providers:

  • Google accepts raw-IP DoH connections and does not mandate a specific HTTP Host header.
  • Cloudflare accepts raw-IP DoH connections but requires the Host: cloudflare-dns.com header.

This means raw-IP endpoints are real-world usage, not just theoretical. If a mis-issued IP SAN cert chains to a CA trusted by the platform (like in Microsoft’s store), exploitation becomes practical.

A Chronic Pattern of Mis-issuance

The incident report cites two mis-issued certs are still valid as of September 3 2025:

This was not an isolated event. A broader search of CT logs reveals a recurring pattern of these mis-issuances from the same CA, indicating a systemic problem. 

Reference: https://crt.sh/?q=1.1.1.1

CT monitoring failed to trigger remediation

Cloudflare runs its own CT monitoring system: https://developers.cloudflare.com/ssl/ct/monitor/

If these certs surfaced in crt.sh, Cloudflare should have flagged them. Instead, there was no visible remediation.

What’s going wrong?

  • Are IP SANs being monitored effectively enough to detect a pattern?
  • Is there a proper pipeline from alerts to action?
  • Why were these certs still valid after months?

It is easy to focus on where CT monitoring fell short in this case, and clearly it did. But we should not lose sight of its value. Without CT, we would not have visibility into many of these mis-issuances, and we do not know how many attackers were dissuaded simply because their activity would be logged. CT is not perfect, but this incident reinforces why it is worth doubling down: improving implementations, making monitoring easier, and investing in features like static CT and verifiable indices that make it easier to use this fantastic resource.

What this means for users

The impact is scoped to users of browsers and applications that rely on the Windows operating system’s root store, such as Microsoft Edge. Browsers like Chrome and Firefox, which manage their own root stores. However, because both Google and Cloudflare accept raw-IP DoH endpoints, the risk extends beyond pure edge cases.

For an affected user, at a public hotspot, if a BGP hijack redirects their traffic and the client connects directly to 1.1.1.1, their system checks the cert and sees a valid Cloudflare-like certificate. The attacker succeeds not just in breaking DNS, but in controlling secure web sessions.

This enables:

  • Silent proxying of all traffic
  • Token and session theft via impersonation
  • Decryption of DoH queries (for raw-IP clients)
  • In-flight alteration of pages and updates

This is the full man-in-the-middle playbook.

A tiny CA with outsized impact

Certificate issuance across the WebPKI is highly skewed, as of today:

CA Owner% of Unexpired Pre-Certificates
Internet Security Research Group46.52%
DigiCert22.19%
Sectigo11.89%
Google Trust Services8.88%
GoDaddy5.77%
Microsoft Corporation3.45%
IdenTrust0.63%
All others<0.70%

Refference: https://crt.sh/cert-populations and https://docs.google.com/spreadsheets/d/1gshICFyR6dtql-oB9uogKEvb2HarjEVLkrqGxYzb1C4/

Fina RDC 2020 has ~201 unexpired certs, accounting for <0.00002% of issuance. Yet Microsoft trusts it, while Chrome, Firefox, and Safari do not. That asymmetry leaves Edge and Windows users vulnerable.

Fina RDC 2020 is also listed in the EU Trusted List (EUTL) as authorized to issue Qualified Website Authentication Certificates (QWACs): https://eidas.ec.europa.eu/efda/trust-services/browse/eidas/tls/tl/HR/tsp/1/service/14. While no mainstream browsers currently import the EUTL for domain TLS, eIDAS 2.0 risks forcing them to. That means what is today a Microsoft-specific trust asymmetry could tomorrow be a regulatory mandate across all browsers.

Moreover, Microsoft requires that CAs provide “broad value to Windows customers and the internet community.”

Reference: https://learn.microsoft.com/en-us/security/trusted-root/program-requirements

Fina clearly does not meet that threshold.

Certificate lifespan context

The CA/Browser Forum (April 2025) approved ballot SC-081v3: TLS certificates will be limited to 47 days by March 2029:

  • March 15 2026: max 200 days
  • March 15 2027: max 100 days
  • March 15 2029: max 47 days

Reference: https://www.cyberark.com/resources/white-papers/how-47-day-tls-certificates-are-reshaping-digital-trust

IP SAN certs, however, are much shorter:

The missed opportunity: If short-lived IP certs were required by policy, this incident would have already expired, reducing exposure from months to days. Baseline Requirements currently do not differentiate IP SAN certs from DNS names. If they did, such exposure could be avoided.

On intent and attribution

Attribution in WebPKI failures is notoriously difficult. The noisy, repeated issuance pattern suggests this may have been a systemic accident rather than a targeted attack. Still, intent is irrelevant. A certificate that shouldn’t exist was issued and left valid for months. Once issued, there is no way to tell what a certificate and its key were used for. The governance failure is what matters.

From an attacker’s perspective, this is even more concerning. CT logs can be mined as a reconnaissance tool to identify the weakest CAs – those with a track record of mis-issuance. An adversary doesn’t need to compromise a major CA; they only need to find a small one with poor controls, like Fina RDC 2020, that is still widely trusted in some ecosystems. That makes weak governance itself an attack surface.

Reference: https://unmitigatedrisk.com/?p=850

Root governance failures

We need risk-aware, continuous root governance:

  • Blast radius control for low-volume CAs
  • Tiered validation for high-value targets (like IP SAN certificates)
  • Real CT monitoring that triggers remediation
  • Cross-vendor accountability (one vendor’s trust shouldn’t be universal if others reject it)

I wrote on this governance model here: https://unmitigatedrisk.com/?p=923

A broader pattern: software and the WebPKI

This incident is not a standalone. It follows previous failures:

DigiNotar (2011, Netherlands): Compromised, issuing hundreds of rogue certificates – including for Google – that were used in live MITM surveillance against Iranian users. The CA collapsed and was distrusted by all major browsers. 

Reference: https://unmitigatedrisk.com/?p=850

TÜRKTRUST (2013, Turkey): Issued an intermediate CA certificate later used to impersonate Google domains. 

Reference: https://unmitigatedrisk.com/?p=850

ANSSI (2013, France): Government CA issued Google-impersonation certs. Browsers blocked them.

Reference: https://arstechnica.com/information-technology/2013/12/french-agency-caught-minting-ssl-certificates-impersonating-google/

Microsoft code-signing trust (2025): I documented how poor governance turned Microsoft code signing into a subversion toolchain: https://unmitigatedrisk.com/?p=1085

The pattern is clear: long-lived trust, weak oversight, repeated governance failures. And notably, most of the major real-world MITM events trace back to European CAs. That history underscores how dangerous it is when regulatory frameworks like eIDAS 2.0 mandate trust regardless of technical or governance quality.

Why eIDAS 2.0 makes it worse

The EU’s provisional agreement on eIDAS 2.0 (November 2023) mandates that browsers must trust CAs approved by EU member states, issuing QWACs (Qualified Website Authentication Certificates).

References:

This comes as EV certificates (part of the “OV” slice) have declined to only ~4% of issuance as tracked on https://merkle.town (OV includes EV in their charts). EV failed because it misled users. The Stripe-name example shows that easily: https://arstechnica.com/information-technology/2017/12/nope-this-isnt-the-https-validated-stripe-website-you-think-it-is/

Browsers are negotiating with the EU to separate QWAC trust from normal trust. For now, however, eIDAS still forces browsers to trust potentially weak or misbehaving CAs. This repeats the Microsoft problem but now globally and legislatively enforced.

And the oversight problem runs deeper. Under eIDAS, Conformity Assessment Bodies (CABs) are responsible for auditing and certifying qualified trust service providers. Auditors should have caught systemic mis-issuance like the 1.1.1.1 case, and so should CABs. Yet in practice many CABs are general IT auditors with limited PKI depth. If they miss problems, the entire EU framework ends up institutionalizing weak governance rather than correcting it.

A parallel exists in other ecosystems: under Entrust’s audits, roughly 3% of issued certificates are supposed to be reviewed. Because CAs select the audit samples, in theory one could envision a CA trying to hide bad practices. But the more likely situation is that auditors simply missed it. With enough audits over time, all but deliberate concealment should have brought at least one of these mis-issued certificates into scope. That points to an auditing and CAB oversight gap, not just a rogue CA.

The bigger picture

A few CAs dominate WebPKI. The long tail, though small, can create massive risk if trusted. Microsoft’s root store is broader and more passive than others. The critical issue is the number of trusted organizations, each representing a potential point of failure. Microsoft’s own list of Trusted Root Program participants includes well over one hundred CAs from dozens of countries, creating a vast and difficult-to-audit trust surface. 

Reference: https://ccadb-public.secure.force.com/microsoft/IncludedCACertificateReportForMSFT

Forced or passive trust is a recipe for systemic risk.

Microsoft’s root store decisions expose its users to risks that Chrome, Firefox, and Safari users are shielded from. Yet Microsoft participates minimally in WebPKI governance. If the company wants to keep a broader and more permissive root store, it should fund the work needed to oversee it – staffing and empowering a credible root program, actively participating in CA/Browser Forum policy, and automating the monitoring Certificate Transparency logs for misuse. Without that investment, Microsoft is effectively subsidizing systemic risk for the rest of the web.


Thanks to Alex Radocea for double-checking DoH/DoT client behavior in support of this post.

The origin of the Windows Biometric Framework

One of the projects I was responsible for when I was at Microsoft was the design and delivery of the Windows Biometric Framework. This was actually one of my favorite projects during my entire tenure at the company.

What most people don’t know is the feature was a very late addition to Windows 7, an analysis of the crash data sent by clients to Windows showed that right after Video Cards these fingerprint readers were one of the largest sources of the “Blue Screen of Death”.

Something else most people don’t know that this was not the first attempt to provide a platform for biometrics into Windows, the prior attempts failed for various reasons but they did not have the same data we had – we knew these devices that were barley used were creating a bad experience for anyone just because the OEM decided to include these sensors as a differentiator.

To fix this a stellar team of senior engineers were re-assigned from other projects and began work almost halfway through the Windows 7 release cycle. Our goal was to make it possible for these devices (and in the future other forms of Biometrics) to work well with the minimal amount of vendor code.

You see these devices need to respond really quickly, especially swipe sensors because they take a picture of your finger as you drag it across the sensor and that data needs to get to a number of components very quickly to make a workable user experience. For this reason the sensor manufacturers all thought they needed to be in kernel, and since most driver developers have only been doing driver development for a few years they did a really bad job of it which resulted in the blue screens.

The value proposition of this project for the vendors was that ultimately they wouldn’t need to write so much software to get their sensors to work, for some this was seen as a positive – especially the new entrants since they didn’t have as much software. For those vendors with complete software suites, they were less thrilled in that a driver framework of any kind places architectural restrictions on the way you build things and since they didn’t get the support calls they didn’t really care that much about the crashes their software caused.

Despite this nearly every biometric vendor begun work on new driver’s client software based on this platform that was being developed at almost the same time they were writing their components. Every vendor who was in the first round of development made significant time investments to make the platform a reality.

The software team at Microsoft also executed amazingly, I am confident that I will allways think of this group of individuals as one of the best I worked with at the company.

In the end the platform made it out the door with more features than we had originally hoped with all the major vendors on board and by the general availability to OEMs people were ready to support real customers.

The late start did mean OEMs had to work very hard to get the new device drivers in their initial images, they had very little runway to do so but several did and those that did not at first got their revised images out shortly later.

This new model delivered a kernel mode and user mode driver model that significantly reduced the amount of software that was needed to get one of these devices working in Windows, we delivered a test suite that helped ensure the devices and their drivers worked reliably. And we were even able to deliver a framework for use, management, group policy, and a hook for enrollment.

The combination of the above meant that we essentially eliminated the historic problems these devices caused, improved the security of how they worked when integrating with windows, made them more supportable and simply work well.

The team went on to work on some very cool additions, many of the team changed but some remained and the work that we began after the “freeze” in the Windows 7 release cycle ultimately found their way out in Windows 8/8.1 – I hope the rest of the things this team were doing find their way out someday soon also.

Understanding Windows Automatic Root Update

Windows has a feature called Automatic Root Update, when CryptoAPI does a chain build, exhausts the locally installed root certificates it downloads (if it has not already done so) a list of certificates it should trust.

This list contains attributes about those certificates (hashes of their subject name and keys, what Microsoft believes it should be trusted for, etc.).

If it finds the certificate it needs in that list it downloads it and installs it.

So how does this technically work?

There is a pre-configured location where Windows looks for this Certificate Trust List (CTL), it is http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab.

NOTE: Technically they do use different language codes in the URLs based on the client local but to the best of my knowledge they all map to the same files today.

This list is downloaded and de-compressed; you can do the same thing on Windows (with curl) like this:

mkdir authroot

cd authroot

curl http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab>authrootstl.cab

expand authrootstl.cab .\authroot.stl

You can open authroot.stl with explorer and look at some of its contents but for the purpose of our exercise that won’t be necessary.

This file is a signed PKCS #7 file, Windows expects this to be signed with key material they own (and protect dearly).

It contains a Microsoft specific ContentInfo structure for CTLs and a few special attributes. WinCrypt.h has the OIDs for these special attributes defined in it but for brevity sake here are the ones you will need for this file:

1.3.6.1.4.1.311.10.1 OID_CTL

1.3.6.1.4.1.311.10.3.9 OID_ROOT_LIST_SIGNER

1.3.6.1.4.1.311.10.11.9 OID_CERT_PROP_ID_METAEKUS

1.3.6.1.4.1.311.10.11.11 CERT_FRIENDLY_NAME_PROP_ID

1.3.6.1.4.1.311.10.11.20 OID_CERT_KEY_IDENTIFIER_PROP_ID

1.3.6.1.4.1.311.10.11.29 OID_CERT_SUBJECT_NAME_MD5_HASH_PROP_ID

1.3.6.1.4.1.311.10.11.83 CERT_ROOT_PROGRAM_CERT_POLICIES_PROP_ID

1.3.6.1.4.1.311.10.11.98 OID_CERT_PROP_ID_PREFIX_98

1.3.6.1.4.1.311.10.11.105 OID_CERT_PROP_ID_PREFIX_105

1.3.6.1.4.1.311.20.2 szOID_ENROLL_CERTTYPE_EXTENSION

1.3.6.1.4.1.311.21.1 szOID_CERTSRV_CA_VERSION

1.3.6.1.4.1.311.60.1.1 OID_ROOT_PROGRAM_FLAGS_BITSTRING

Copy this list of OIDs and constants into a file called authroot.oids and put it where we extracted the STL file.

We can now use the following OpenSSL command to inspect the contents in more detail:

openssl asn1parse -oid authrootstl.oids -in authroot.stl -inform DER

There is lots of stuff in here, but for this exercise we will just download the certificates referenced in this list.

To do that we need to understand which of the attributes are used to construct the URL we will use to download the actual certificate.

This list values we want are just after the OID_ROOT_LIST_SIGNER, the first one being “CDD4EEAE6000AC7F40C3802C171E30148030C072”, its entry will look like this:

SEQUENCE

  128:d=8  hl=2 l=  20 prim:         OCTET STRING      [HEX DUMP]:CDD4EEAE6000AC7F40C3802C171E30148030C072

  150:d=8  hl=3 l= 246 cons:         SET

  153:d=9  hl=2 l=  30 cons:          SEQUENCE

  155:d=10 hl=2 l=  10 prim:           OBJECT            :OID_CERT_PROP_ID_PREFIX_105

  167:d=10 hl=2 l=  16 cons:           SET

  169:d=11 hl=2 l=  14 prim:            OCTET STRING      [HEX DUMP]:300C060A2B0601040182373C0302

  185:d=9  hl=2 l=  32 cons:          SEQUENCE

  187:d=10 hl=2 l=  10 prim:           OBJECT            :OID_CERT_SUBJECT_NAME_MD5_HASH_PROP_ID

  199:d=10 hl=2 l=  18 cons:           SET

  201:d=11 hl=2 l=  16 prim:            OCTET STRING      [HEX DUMP]:F0C402F0404EA9ADBF25A03DDF2CA6FA

  219:d=9  hl=2 l=  36 cons:          SEQUENCE

  221:d=10 hl=2 l=  10 prim:           OBJECT            :OID_CERT_KEY_IDENTIFIER_PROP_ID

  233:d=10 hl=2 l=  22 cons:           SET

  235:d=11 hl=2 l=  20 prim:            OCTET STRING      [HEX DUMP]:0EAC826040562797E52513FC2AE10A539559E4A4

  257:d=9  hl=2 l=  48 cons:          SEQUENCE

  259:d=10 hl=2 l=  10 prim:           OBJECT            :OID_CERT_PROP_ID_PREFIX_98

  271:d=10 hl=2 l=  34 cons:           SET

  273:d=11 hl=2 l=  32 prim:            OCTET STRING      [HEX DUMP]:885DE64C340E3EA70658F01E1145F957FCDA27AABEEA1AB9FAA9FDB0102D4077

  307:d=9  hl=2 l=  90 cons:          SEQUENCE

  309:d=10 hl=2 l=  10 prim:           OBJECT            :CERT_FRIENDLY_NAME_PROP_ID

  321:d=10 hl=2 l=  76 cons:           SET

  323:d=11 hl=2 l=  74 prim:            OCTET STRING      [HEX DUMP]:4D006900630072006F0073006F0066007400200052006F006F007400200043006500720074006900660069006300610074006500200041007500740068006F0072006900740079000000

We can download this certificate with the following command:

curl http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/CDD4EEAE6000AC7F40C3802C171E30148030C072.crt> CDD4EEAE6000AC7F40C3802C171E30148030C072.crt

If we look at the contents of the certificate we can see this is the 4096 bit “Microsoft Root Certificate Authority”.

The next in the list is 245C97DF7514E7CF2DF8BE72AE957B9E04741E85, and then the next is 18F7C1FCC3090203FD5BAA2F861A754976C8DD25 and so forth.

We could go through and parse the ASN.1 to get these values, iterate on them and download them all if we wanted. Of course if we wanted to get all of the root certificates we might as well just download the most recent root update here: http://www.microsoft.com/en-us/download/details.aspx?id=29434

It contains the same information just in a self-contained format (this is whats used by down-level clients that do not have Automatic Root Update).

Anyhow hopefully this will be useful for someone,

Ryan

How to seed the CryptoAPI URL cache with an OCSP response

It is possible to “staple” an OCSP response into higher level protocols such as TLS. This concept has been supported in Windows since Windows VISTA, shortly after it was added to OpenSSL/Apache and soon it will also be in Nginx.

When “stapling” is used the subscriber (the web server in the TLS case) requests the status of his own certificate from the OCSP responder his CA operates to get a time valid OCSP response for his own certificate.

Since the OCSP response is signed by the CA it can be relayed by the web server for the duration in which that OCSP response is time valid to save the client of the web server (the relying party, aka the browser) the need to make an additional socket connection back to the CA.

This has both performance and privacy benefits.

You can apply the same concept to other PKI related protocols/applications as well, for example in a document signing application like Adobe Acrobat. In such an application the subscriber might sign the document, timestamp it using a timestamp protocol like RFC 3161 and then attach a time valid OCSP response to it so that the document is verifiable at a later date.

This scenario is important not only for its performance and privacy benefits but because it is a practical necessity because CAs do not typically maintain revocation information (OCSP responses and CRLs) for expired certificates.

By stapling the OCSP response to the signed and time-stamped document the relying party can verify the signature, the certificates and the revocation status of the certificates in the context of the timestamp that was attached to the document.

But how do you do that with CryptoAPI?

It’s actually pretty straight forward, as the relying party when you call CertGetCertificateChain to validate the associated certificate you need to:

  1. Once you have verified your timestamp is cryptographically valid and trusted, take the time it and pass it in as pTime.
  2. On the CERT_CONTEXT there is a CERT_INFO structure that contains an array of CERT_EXTENSION, here you create an extension of type CERT_OCSP_RESPONSE_PROP_ID and in there you put a basic signed OCSP response .

When CryptoAPI does the chain validation it will try to use the OCSP response you passed in, if it finds a problem with the provided response it may go online to get a new one that is “OK”.

This online behavior can be controlled by indicating to CertGetCertificateChain you do not want online revocation checking (see CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY).

Ryan

CryptoAPI, Revocation checking, OCSP and the Unknown certStatus

In CryptoAPI one can use the CertGetCertificateChain API to do the path building and basic chain validation, this validation may include revocation checking depending on which flags you pass via dwFlags; for example these flags control if revocation checking occurs, and if so, on which certificates:

  • CERT_CHAIN_REVOCATION_CHECK_END_CERT
  • CERT_CHAIN_REVOCATION_CHECK_CHAIN
  • CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT

Typically you would specify CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT which ensures the whole chain is checked (where possible – e.g. one shouldn’t bother asking the root if he considers himself revoked).

But in the context of OCSP what are the potential revocation related returns we might see?

  1. Revoked – I have received a signed response from the CA or have had policy pushed to me that tells me that this certificate is not to be trusted.
  2. Not Revoked – I have received a signed response from the CA that says this certificate was not revoked.
  3. Unknown – I have received signed response from the CA that says it doesn’t know anything about this certificate.
  4. Offline – I was unable to reach the responder to verify the status of the certificate.

Each of these cases are clearly represented in the API that is used by CertGetCertificateChain to perform the revocation check, this API is CertVerifyRevocation. The higher level CertGetCertificateChain however only has two possible returns: Revoked and Unknown outside the “not revoked” case.

One might assume the OCSP Unknown would get mapped into the Revoked state, this unfortunately is not the case, it is returned as unknown, as does the Offline error.

This means that if OCSP was used you cannot tell what the actual status was, this is especially problematic since IE and Chrome both default to modes where they ignore “Unknown” revocations due to concerns over Revocation responder performance and reliability.

It is possible to work around this platform behavior though — the problem is that it’s not documented anywhere, let’s take a quick stab at doing that here.

First since CertGetCertificateChain doesn’t tell us what method was used to do revocation checking we have to use heuristics to figure it out. Thankfully to enable OCSP stapling in higher level protocols like TLS the OCSP response is passed back to the caller if OCSP was used; to get that we need to know:

1. The CERT_CHAIN_ELEMENT in the returned CHAIN_CONTEXT points to the following revocation information:

  • PCERT_REVOCATION_INFO pRevocationInfo;
  • PCERT_REVOCATION_CRL_INFO   pCrlInfo;
  • PCCRL_CONTEXT           pBaseCrlContext;

2. For an OCSP response, the CRL_CONTEXT is specially created to contain the full OCSP response in the following critical extension szOID_PKIX_OCSP_BASIC_SIGNED_RESPONSE.

  • The presence of this extension indicates an OCSP response was used.
  • The Issuer name in the CRL is the name of the OCSP signer.
  • The signature algorithm is sha1NoSign.
  • ThisUpdate and NextUpdate contain the response validity period.

With this we can take the OCSP response from the CRL_CONTEXT and then look at the “ResponseData” within it, you will need to look within the “responses” here,  you will need to find the right “SingleResponse” based on its “CertID”.

NOTE: Some responders will return the status of multiple certificates in a response even if the status of only one was requested.

You now can determine what the responder said the status of the certificate was by inspecting “certStatus” element.

This is a fair amount of work unfortunately but it does enable you to do the right thing with authoritative “Unknown” responses.

Ryan

A look at the new Windows Update SSL certificates

This morning I noticed a tweet by Mikko about the Windows Update certificate chain looking odd so I decided to take a look myself.

I started with the webserver configuration using SSLLABS, unfortunately it did not fare well:

Looking a little closer we see a few things of interest:

  • SSLLABS is unable to validate the certificate
  • The server is using weak ciphers
  • The server is vulnerable to the BEAST attack
  • The server is not using an Extended Validation  (EV) Certificate
  • The server is supporting SSL 2.0

To understand the specifics here we needed to look a little deeper, the OpenSSL s_client is a great tool for this:

openssl s_client –showcerts -status –connect www.update.microsoft.com:443

Loading ‘screen’ into random state – done

CONNECTED(0000017C)

OCSP response: no response sent

depth=1 C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Update Secure Server CA 1

verify error:num=20:unable to get local issuer certificate

verify return:0

Certificate chain

0 s:/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=WUPDS/CN=www.update.microsoft.com

i:/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Update Secure Server CA 1

1 s:/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Update Secure Server CA 1

i:/DC=com/DC=microsoft/CN=Microsoft Root Certificate Authority

Server certificate

—–BEGIN CERTIFICATE—–

MIIF4TCCA8mgAwIBAgITMwAAAAPxs7enAjT5gQAAAAAAAzANBgkqhkiG9w0BAQUF

—–END CERTIFICATE—–

1 s:/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Update S

ecure Server CA 1

i:/DC=com/DC=microsoft/CN=Microsoft Root Certificate Authority

—–BEGIN CERTIFICATE—–

MIIGwDCCBKigAwIBAgITMwAAADTNCXaXRxx1YwAAAAAANDANBgkqhkiG9w0BAQUF

—–END CERTIFICATE—–

subject=/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=WUPDS/CN=www.update.microsoft.com issuer=/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Update

Secure Server CA 1

No client certificate CA names sent

SSL handshake has read 3403 bytes and written 536 bytes

New, TLSv1/SSLv3, Cipher is AES128-SHA

Server public key is 2048 bit

Secure Renegotiation IS supported

Compression: NONE

Expansion: NONE

SSL-Session:

Protocol  : TLSv1

Cipher    : AES128-SHA

Session-ID: 33240000580DB2DE3D476EDAF84BEF7B357988A66A05249F71F4B7C90AB62986

 

Session-ID-ctx:

Master-Key: BD56664815654CA31DF75E7D6C35BD43D03186A2BDA4071CE188DF3AA296B1F9674BE721C90109179749AF2D7F1F6EE5

Key-Arg   : None

PSK identity: None

PSK identity hint: None

Start Time: 1339954151

Timeout   : 300 (sec)

Verify return code: 20 (unable to get local issuer certificate)

read:errno=10054

 

With this detail we can also look at the certificates with the Windows Certificate viewer, we just extract the server certificate Base64 and put it into a text file with a .cer extension and open it with Explorer:

   
   
   

 

From these we see a few additional things:

  • OCSP Stapling is not enabled on the server
  • The issuing CA was created on 5/30/2012 at 8:49pm
  • The issuing CA was issued by the 2001 SHA1 “Microsoft Root Authority”

So with this extra information let’s tackle each of these observations and see what conclusions we come to.

 

SSLLABS is unable to validate the certificate; there are two possible reasons:

a. The server isn’t including the intermediate certificates (it is) and SSLLABS doesn’t chase intermediates specified in the AIA:IssuerCert extension (doubt it does) or that extension isn’t present (it is).

b. The Root CA isn’t trusted by SSLLABS (which appears to be the case here).

My guess based on this is that Ivan only included the certificates in the “Third-Party Root Certification Authorities” store and did not include those in the “Trusted Root Certification Authorities” which are required for Windows to work.

Basically he never expected these Roots to be used to authenticate a public website.

[2:00 PM 6/18/2012] Ivan has confirmed he currently only checks the Mozilla trusted roots, therefor this root wouldn’t be trusted by SSLLABS.

Microsoft’s decision to use this roots means that any browser that doesn’t use the CryptoAPI certificate validation functions (Safari, Opera, Chrome on non-Windows platforms, Firefox, etc.) will fail to validate this certificate.

This was probably done to allow them to do pinning using the “Microsoft” policy in CertVerifyCertificateChainPolicy.

I believe this was not the right approach since I think it’s probably legitimate to use another browser to download patches.

[2:00 PM 6/18/2012] The assumption in this statement (and it may turn out I am wrong) is that it is possible for someone to reach a path where from a browser they can download patches; its my understanding this is an experience that XP machines using a different browser have when visiting this URL I — I have not verified this.

[3:00 PM 6/18/2012] Harry says that you have not been able to download from these URLs without IE ever, so this would be a non-issue if that is the case.

To address this Microsoft would need to either:

  • Have their PKI operate in accordance with the requirements that other CAs have to meet and be audited and be found to meet the requirements of each of the root programs that are out there.
  • Have two separate URLs and certificate chains one for the website anchored under a publicly trusted CA and another under this private “Product” root. The manifests would be downloaded from the “Product” root backed host and the web experience would be from the “Public” root backed host.
  • Cross certifying the issuing CA “Microsoft Update Secure Server CA 1” under a public CA also (cross certification), for example under their IT root that is publically trusted and include that intermediate in the web server configuration also. Then have a CertVerifyCertificateChainPolicy implementation that checks for that CA instead of the “Product” roots.

 

The server is using weak ciphers; the server is using several weak ciphers:


I see no reason to support the MD5 based ciphers as I find it hard to believe that there are any clients that can communicate with this site that do not support their SHA1 equivalents.

 

[2:00 PM 6/18/2012] I have been told I am too critical by calling these MD5 based ciphers as weak in that they are used as HMAC, it is true that when used with a key as is the case with HMAC the current attacks are not relevant. With that said any client that supports these suites will also support their SHA1 counterpart and there is no reason to support the weaker suites that use MD5.

 

The server is vulnerable to the BEAST attack; and SSLLABS isn’t able to tell if the server is specifying a cipher suite preference, this means it probably is not.

It is the cipher suite ordering issue that is actually resulting in the warning about the BEAST attack though. It is addressed by putting RC4 cipher suites at the top of the cipher suite order list.

[2:00 PM 6/18/2012] It’s been argued the BEAST attack isn’t relevant here because the client is normally not a browser, these pages that are returned do contain JS and there are cases where users visit it via the browser — otherwise there would not be HTML and JS in them. As such the attacker could use the attack to influence you to install malicious content as if it came from Microsoft. Maybe its not a leakage of personal information initially but its an issue.

 

It is not using an Extended Validation (EV) Certificate; this is an odd one, is an EV certificates necessary when someone is attesting to their own identity? Technically I would argue no, however no one can reasonably expect a user to go and look at a certificate chain and be knowledgeable enough to that this is what is going on.

The only mechanism to communicate the identity to the user in as clear a way is to make the certificate be an EV certificate.

Microsoft really should re-issue this certificate as an EV certificate – if there was ever a case to be sure who you are talking to it would certainly include when you are installing kernel mode drivers.

 

The server is supporting SSL 2.0; this also has to be an oversight in the servers configuration of SSL 2.0 has been known to have numerous security issues for some time.

They need to disable this weak version of SSL.

 

OCSP Stapling is not enabled on the server; OCSP stapling allows a webserver to send its own revocations status along with its certificate improving performance, reliability and privacy for revocation checking. According to Netcraft Windows Update is running on IIS 7 which supports it by default.

This means Microsoft is either not allowing these web servers to make outbound connections or they have explicitly disabled this feature (login.live.com has it enabled and working). While it is not a security issue per-se enabling it certainly is a best practice and since it’s on by default it seems they are intentionally not doing it for some reason.

 

The issuing CA was created on 5/30/2012 at 8:49pm; this isn’t a security issue but it’s interesting that the issuing CA was created four days before the Flame Security advisory. It was a late night for the folks operating the CA.

 

That’s it for now,

 

Ryan

Redirecting HTTP to HTTPS in IIS

So you have been using SSL on your IIS 7.5 or greater server for some time now; to get here you had to do a few things:

  1. You scrubbed your site content to ensure all URLs are using their relative form, e.g. “src=’//images\image.png” or explicitly reference the use of HTTPS.
  2. You have tested for certificate and SSL related problems like mixed content, appropriately tagging cookies as secure.
  3. You have ensured that you follow the best practices guidance for SSL server configuration and verified you get an A on  SSLLabs.

Are you done? Not yet there are a few things left for you to do, the most obvious being redirecting all traffic to the SSL version of your site!

This is easy enough to accomplish but before you do so you should probably monitor your CPU usage during your peak so to ensure you have some headroom. This isn’t likely to be a problem as most web-servers are not CPU bound but it’s always good to check.

Once you know you are OK then it’s just a matter of deciding which approach to use, you have two choices:

  1. Dynamically rewriting via code in your ASPX pages
  2. Using the IIS URL Rewrite  module

If you are familiar with the IIS configuration you’re probably asking yourself what about the “Require secure channel (SSL)” option in the IIS MMC? Unfortunately this doesn’t do redirecting it only requires the use of SSL on a given site/folder/file.

So how do you decide which approach to use? The answer to that question is dependent on both your environment and personal preference.

For example if 100% of your site is ASPX based (no static HTML), you have your code structured so that there is a common include and you are not already using the URL Rewrite module I would use method one based on KB239875.

I suspect that these conditions will not be met for most people so let’s focus on method two, using the URL Rewrite  module.

This approach has a number of benefits, for one having this module allows you to leverage remapping for other purposes also for example maintaining old links that have SEO value. From a security standpoint it’s also a good approach as it keeps this decision one of policy that is enforced in a central place.

To use the URL rewrite approach you will need to do the following:

 

1. Install the URL Rewrite module (x86, x64).

2. Add a rule to rewrite all HTTP URLs to HTTPS.

a. Open your “web.config” with your favorite editor.

b. Find the “configuration\system.webserver\rewrite\rules” section.

c. Add the following text block:

<rule name=”Redirect to HTTPS” stopProcessing=”true”>

<match url=”(.*)” />

<conditions>

<add input=”{HTTPS}” pattern=”^OFF$” />

</conditions>

<action type=”Redirect” url=”https://{HTTP_HOST}/{R:1}” redirectType=”Permanent” />

</rule>

3. Restart IIS.

Now just go to your website over HTTP and you will see you are redirected to the HTTPS instance of the site.

 

Ryan

Additional Resources

IIS Rewrite Module Configuration Reference

10 URL Rewriting Tips and Tricks

Automatically redirect HTTP requests to HTTPS on IIS7 using URL Rewrite 2.0

 

 

OCSP Stapling in IIS

Windows Server 2008 and later support a feature called OCSP stapling. When enabled a server pre-fetches the OCSP response for its own certificate and delivers it to the user’s browser during the TLS handshake. This approach offers a privacy advantage. But, the main benefit is the browser doesn’t have to make a separate connection to the CA’s revocation service before it can display the Web page. This gives better performance and reliability.

For this pre-fetching to work the web-server certificate needs to contain a pointer to the OCSP responder, this is a best practice and a recommendation of the CA/Browser Forums baseline requirements so it’s almost certain your certificate has it.

Unlike Apache this feature is enabled by default, it’s possible your servers are already doing OCSP stapling and you do not even know it.

With that said chances are you have a firewall between your webservers and the internet; it’s also likely that firewall disallows outbound connections from your servers unless explicitly allowed. So you might need to allow your web servers to communicate with the OCSP responder before it will work.

To figure out what host and port you will need to open you will need to look at the certificates you use on your webserver; one way to do that is to browse to your current site and view the details of the certificates you are currently using, for example:

   

The value you want is in the “Authority Information Access” field, you want the ones (there may be multiple) that have the “Access Method” of “On-line Certificate Status Protocol”.

Once these two conditions are met OCSP Stapling will “Just work” there is nothing else you need to do.

Ryan

Flame was just one use of the Terminal Services Licensing PKI

I wanted to do a post on how the Terminal Services Licensing PKI could be used in another attack; though the variants are endless I have one concrete example of how this was used in in an attack in 2002 in this certificate:

   
   

 

What we see in this certificate is that the attacker took the License Certificate (Terminal Services LS) and issued himself a certificate underneath it. This only worked because of another defect in the Windows chain engine, this one relating to how it handled Basic Constraints (see MS 02-050) – that was fixed in 2003.

But why would he have done this? I see two possible reasons:

  1. Bypassing the terminal services licensing mechanism.
  2. Bypassing some client authentication scheme based on X.509.

We won’t explore #1 as I am not interested in the attacks on license revenue for Microsoft but how this infrastructure designed to protect that license revenue was used to attack customers and as such I will focus on #2.

Now, before I go much further I have to be clear – I am just guessing here, I don’t have enough data to be 100% sure of what this was used for but it seems pretty likely I am right.

What I see here is the X.509 serial number is different than the Serial Number RDN the attacker put into the Subject’s DN.

This certificate also has a value in the CN of the Subject DN that looks like it is a user name (PORTATILE).

Neither of these should be necessary to attack the licensing mechanism as legitimate license certificates don’t have these properties or anything that looks roughly like them.

My theory is that the attacker found some Windows Server configured to do client authentication (possibly for LDAPS or HTTPS) and wanted to trick the server into mapping this certificate into the principal represented by that CN and Serial Number in the DN.

Why would this have worked? Well as I said there was the Basic Constraints handling defect, but that wouldn’t have  been enough the server would have had to had blindly trusted all the root certificates in the root store for “all usages”.

This was a fairly common practices back then, web servers and other server applications would be based on other libraries (for example SSLEAY/OpenSSL) and just import all the roots in the CryptoAPI store and use them with this other library.

This is actually still done by some applications today, for example Adobe Reader X:

 

The problem with this behavior is that these applications do not necessarily (read almost never) import the properties associated with these certificates, nor do they support the same enforcement constraints (for example Nested Extended Key usages).

The net effect of which is that when they import the roots they end up trusting them for more than the underlying Windows subsystem does.

The attackers in this case were likely taking advantage of this bad design of this client authentication solution as well as the bad design of the Terminal Services Licensing PKI.

The combination of which would have allowed the attacker to impersonate the user PORTATILE and perform any actions as that user they liked.

Even if I am wrong in this particular case, this sort of thing was definitely possible.

What lessons should we take away from this?

For one always do a formal security review of your solutions as you build them as well as before you deploy them; pay special attention to your dependencies – sometimes they are configuration as well as code.

Also if an issue as fundamental as the Terminal Services Licensing PKI can fly under the radar of a world class security program like Microsoft’s you probably have some sleepers in your own infrastructure too – go take a look once more for the assumptions of the past before they bite you too.

Ryan

How did the Terminal Services Licensing PKI effect you?

The other day I did a post on the age of the Microsoft PKI that was used for Terminal Services Licensing, today I thought I would talk about what that age meant in the context of the vulnerabilities it introduced.

The oldest certificate I have been able to find from the same hierarchy is from April 1999 (that’s the issuance date for the Microsoft Enforced Licensing PCA).

Based on the post from the Microsoft Security Research & Defense blog  we know that the reason the attacker had to do the MD5 collision was that as of Vista there was a change in the way critical extensions were handled.

This change made it so that Vista clients would fail when they saw a certificate that contained an unknown critical extension in a signing certificate making it an ineffective attack vector for those clients.

But what does this mean for the period of time before that? Well Windows Vista was released in November of 2006, that’s nearly 8 years in which any enterprise with a terminal services deployment could have owned a Windows PC “As Microsoft” or potentially attack a PKI based system with “trusted” but fraudulent certificate.

But did it really get better in with the release of VISTA? According to StatCounter Windows Vista received its maximum market share of 23% in October of 2009. Yes, two years after the release of Vista 77% of the Windows clients on the Internet were still vulnerable as a result of the design of the terminal services licensing solution.

Things didn’t really start to get better until XP SP3 which was released in April of 2008 as it contained the same certificate validation engine that was found in Vista.

While I do not have any public statistics I can share I can say that this service pack was picked up faster than any other service pack up until that point which says a lot since it was not a “forced” update.

If we are optimistic and say that it took only one year to get 100% penetration and we believe stat counters statistics for XPs Market share of 71% in April 2009 that it took till 2009 to get to 95% patched.

Now these numbers are just for clients on the Internet and not servers. This “fixed” chain validation engine wouldn’t have even found its way into the Windows Server code base until Windows Server 2008 which was released in February 2008 but took some time to get broadly used.

While Windows Servers are not terribly common on the Internet they are extremely common in the Enterprise, especially in 2009 where it had 73.9% market share. Again I don’t have numbers but antidotal we know that Enterprises are notoriously slow to upgrade or patch.

So where does this leave us in 2012? Still vulnerable that’s where.

The other day Microsoft released a patch that in-essence revokes the PKI in question and today WSUS announced their patch that introduces additional pinning.

You need to apply both to secure your systems.

Ryan