Reluctant enforcers: certificate authorities as malware police

Learning the wrong lessons from Internet Exploder [sic]

Previous posts have alluded to the role certificate authorities play— or at least are expected to play when operating effectively— in response to discovery of digitally signed malware. Part of the bargain for inclusion in the Windows code-signing ecosystem is that CAs have an obligation to revoke code-signing certificate known to have signed malicious code. This is not exactly a new, onerous condition that MSFT has foisted on certificate authorities in a bid to raise the bar. (Unlike the way Chrome monopoly was leveraged effectively to compel CAs to adopt certificate transparency, after they had been operating for decades with no such requirement.)

The idea that CAs can be enlisted to “police” the third-party software ecosystem on Windows is almost as old as the history of Authenticode. In 1996, Seattle-area developer Fred McLain decided to make a point about the danger of ActiveX controls, by writing one subversively named “Internet Exploder” [sic] riffing on the name of the MSFT browser and signed it using an Authenticode certificate from VeriSign. By modern standards, it was a measured, responsible proof-of-concept: when the control executed in a web browser, it initiated a shutdown of the PC. Nothing particularly destructive or irreversible. MSFT, stuck at the nadir of its pre-Trustworthy Computing dark-ages approach to security, was not amused. Neither was VeriSign, which promptly revoked the certificate on the grounds of breaching the subscriber agreement, sparing Microsoft any additional work or further embarrassment— thus initiating a long-running tradition of conscripting reluctant third-parties into policing the software ecosystem.

From a narrow perspective, the intervention “worked:” because Authenticode involves mandatory revocation checks, that particular ActiveX control would be flagged as untrusted and could no longer be executed. Never mind that the broader point this developer tried to make was completely missed: namely, running native code downloaded from random websites without any semblance of sandboxing is a Bad Idea™. ActiveX was a certifiably bad idea for many reasons beyond security: native code was necessarily OS and platform dependent. Even viewed as typical, knee-jerk Redmond reaction to the peril of portable Java applets in the browser— “write once, run anywhere” Sun promised, and how exactly did that turn out?— the concept made no sense when MSFT was hawking multiple operating systems (Windows 95/98 and NT4, with different kernels and significant API differences) with the “favored” OS shipping on multiple hardware architectures: Intel x86, DEC Alpha, MIPS and PowerPC.

Relics of the ActiveX trust model

While ActiveX was quickly relegated to two niches—the backwaters of enterprise “line of business” applications and the far more vibrant ecosystem of malware development— and eventually put out to pasture, its precedent of equating “signed” with “trusted” would remain a fundamental tenet of Windows. Part of the reason is the open ecosystem: unlike mobile devices which are designed from day-one as locked down appliance with centralized control over app distribution— often by multiple actors vying for influence, such as Google vs Samsung vs T-Mobile— the PC is an open platform. To this day, it is not uncommon for legitimate Windows applications to be downloaded and installed from third-party websites, an act of “side-loading” that would be considered borderline irresponsible and dangerous on Android. Without a single app-store curating selections and keeping out bad actors, trust decisions require a correspondingly open, distributed solution. Authenticode is one piece of the puzzle. Having an ecosystem of CAs trusted to issue code-signing certificates gives developers a choice of providers for sourcing their credential.

But implicit in the Authenticode model is an unstated assumption that trust is entirely a function of publisher identity. That knowing the provenance of an application is sufficient to determine whether it is safe to run that code. That premise is suspect, even in an ideal world where we posit:

  • CAs are infallible and will never issue a code-signing certificate to the wrong person
  • Software publishers have perfect opsec around key-management and will never allow a threat actor to misuse their private key.

Even under these wildly unrealistic assumptions— easily debunked by contemporary real-life examples from that era— this model breaks down. It places the burden on consumers to become experts in the competitive dynamics of the software industry. Authenticode can answer the question of who published the software, but it can not distinguish between a reputable vendor and a fly-by-night operation. Who is to say the reputable vendor will not be tempted into bundling some spyware for a price or that unknown garage-company with the strange name one day becomes the most valuable company on Earth? Brand recognition only goes so far. At best it stacks the deck towards established incumbents with familiar names, casting suspicion on software from upstarts seeking to challenge the status quo. “What kind of person names their company Google?” one can imagine a Windows user asking, while considering whether to install the Google toolbar extension for IE back in 2000.

Creative justifications for revocation

For all of the dubious premises behind equating code-signing with trust in software, it pales in comparison to the conceptual muddle behind leveraging revocation to remove that trust:

1. Revocation is not a precision instrument: it does not simply blacklist one binary, it invalidates all code signed using that certificate after the effective date of revocation. (Third-party trusted timestamps are used to establish the signing time; otherwise a malicious signer could back/future-date signatures.) If a vendor accidentally signs a back-doored version once in the middle of a sequence of ten legitimate releases, there is no way to only revoke that single instance. At best one can specify a revocation time to shield past releases; anything after the malicious sample will still become collateral damage. There is no way to achieve the opposite effect and preserve validity of latest versions while revoking older ones. That seems reasonable when focusing on the threat model of key-compromise. The implicit assumption is, if an attacker could sign using a key once, they can do so again in the future. Strangely that is less likely to hold today when code-signing certificates are required to be held in cryptographic hardware, creating a new failure mode: an attacker can get temporary access to the code-signing infrastructure to sign some unauthorized code but they can not extract the private key and walk away with it for indefinite access.

2. There is no global “do-not-issue” list that is the equivalent of the TSA No-Fly list for digital certificates. One CA revoking a developer certificate for creating malware has no effect on whether the same developer can provision another valid Authenticode certificate from another CA to sign the exact same offending code. (Or, as in the recent case of short-lived Azure Code Signing certificates appearing on malware, to obtain them from the same issuer.)

3. Stepping back: revocation was never intended as a policing mechanism on the behavior of software publishers. Let’s look at the revocation reasons standardized in RFC 5280. This document lists a closed-ended set of choices the issuer can state as the justification. This reason appears in the CRL entry and OCSP response. These are precisely:

CRLReason ::= ENUMERATED {
unspecified (0),
keyCompromise (1),
cACompromise (2),
affiliationChanged (3),
superseded (4),
cessationOfOperation (5),
certificateHold (6),
-- value 7 is not used
removeFromCRL (8),
privilegeWithdrawn (9),
aACompromise (10) }

Nowhere in this list is an option for “behaved badly” or “wrote malware.” Such scenarios were historically outside the purview of PKI. Code-signing certificates are statements of identity. They are not merit badges awarded for ethical standards or excellence in software engineering. When McLain signed a malicious ActiveX control to make a point about Internet Explorer, he did not impersonate anyone, make false representations to VeriSign or deliberately divulge his private-key for others to misuse.

CAs commonly opt for “privilegeWithdrawn” as the putative reason when certificates are revoked for malware authorship. But historically that reason code meant something different. X509 distinguished between identity assertions and privilege assertions, with the latter encoding specific (as in, not unique) information about a person such as being employed by a particular company. This was envisioned as the grand Privilege Management Infrastructure counterpart to its better-known brethren PKI. PMI motivated the introduction of new reason codes #9 and #10. “aaCompromise” is the logical parallel to “caCompromise” but “privilegeWithdrawn” is something unique, with no equivalent in identity analog. It refers to a privilege contained in the certificate no longer applying to the grantee. With the benefit of 30 years, it is safe to say this grant vision of PMI went nowhere. In theory identity certificates can encode privilege attributes, but Authenticode never made use of that. There was no “virtuous developer” privilege to withdraw begin with.

Authentication vs authorization

There is a fundamental category error in using revocation to combat malware: certificates are intended for authentication. Whether a piece of code is allowed to execute is a question of authorization. Trying to deny authorization by withholding authentication is akin to combating crime by having the DMV deny driver’s licenses to people convicted of fraud, on the theory that it will prevent them from opening additional bank accounts to perpetrate more fraud.1 An Authenticode certificate is not a guarantee of developer integrity: if Bernie Madoff had been sentenced to writing Windows apps as part of his penance, nothing in the Authenticode issuance policies would stop a CA from issuing him a certificate. Given that CAs are not in the business of running background checks on software publishers as a gating factor prior to issuing credentials, it is strange to enlist them into an enforcement role after the fact when their customer turns out not to be an upstanding citizen.

In the case of Windows applications, there are already multiple authorization systems: SmartScreen for binary reputation, Windows Defender malware scanning and WDAC policies for enterprise enforcement. There is no reason to burden the identity system with solving emergent problems belonging to a higher layer. Tellingly, this is not done for TLS certificates: CAs are not obligated to revoke server certificates when a website is caught hosting scams. Those CAs have significant leverage: loud browser warnings for unencrypted traffic have made possession of a valid TLS certificate table-stakes for web presence. Yet we do not conscript CAs into policing the web.

Code Signing Baseline Requirements— the policies and procedures Authenticode CAs are expected to follow— solidified this responsibility on CAs without addressing the category error. 2024 CSBR changes require CAs to revoke certificates that signed “Suspect Code” within 24 hours While it is difficult to argue with demanding more accountability from CAs. CSBR are a contractual agreement between the platform owner and an open ecosystem of CAs hoping for a slice of the pie from issuing code-signing certificates. Microsoft can impose its terms on that captive audience, but contractual obligations are not X509 semantics.

CP

1 This pattern would repeat in the early 2000s with “Kids Passport,” a feature in Microsoft’s online identity platform for complying with COPPA requirements, a precursor to controversial age verification requirements being contemplated today. If a user was known to be underage, the centralized authentication system would refuse to log them into certain Microsoft sites—a clear example of denying authorization by denying authentication.