In my last post I explained how it is possible for most governments, Wire, anyone who compromises Wire, and many employers to invisibly intercept Wire voice and video calls without being detected.

Wire responded to say that this attack is partially mitigated, because they do certificate pinning, while pointing to this code.

One week ago, I notified them that this code does not actually implement certificate pinning, but they have yet to create a fix or notify their users that they are vulnerable.

The Wire source code is very sloppy, and many choices were not made defensively. Here we can see that instead of pinning to the host name the app is trying to connect to, the app applies pinning based on what is presented in the certificate. The certificate being presented over a network is what a defensive programmer would usually consider an “untrusted input,” (the entire reason the app needs pinning to begin with) but Wire chooses to make trust decisions based on what it is given.

The app then only apply the pins based on the host names in the certificate’s Subject Alternative Name:

private def isCertForDomain(domain: String, cert: X509Certificate): Boolean = cert.getSubjectAlternativeNames.asScala.map(_.asScala match { case Seq(_, name) => name.toString}).forall { name => name == domain || name.endsWith(s".$domain")} }))

This is pretty dumb and obviously doesn’t work. An attacker only needs to create a certificate with a Common Name for “wire.com” then either leave out the Subject Alternative Name or fill it with “nothingtoseehere.com” to disable all certificate pinning logic.

They’ve known about this for a week, all user voice and video calls are vulnerable to invisible interception, but they still haven’t committed a fix or notified their users.